#rune "" to ''; Remove infix and postfix call notation

This commit is contained in:
Ginger Bill
2016-11-28 20:39:43 +00:00
parent cbb70c7873
commit 598dab5bc4
19 changed files with 367 additions and 320 deletions

View File

@@ -16,7 +16,7 @@ if %release_mode% EQU 0 ( rem Debug
)
set compiler_warnings= ^
-we4013 -we4706 -we4002 ^
-we4013 -we4706 -we4002 -we4133 ^
-wd4100 -wd4101 -wd4127 -wd4189 ^
-wd4201 -wd4204 -wd4244 ^
-wd4306 ^

View File

@@ -1,5 +1,34 @@
#import "fmt.odin"
#import "utf8.odin"
main :: proc() {
fmt.println("Hellope, World!")
MAX :: 64
buf: [MAX]rune
backing: [MAX]byte
offset: int
msg := "Hello"
count := utf8.rune_count(msg)
assert(count <= MAX)
runes := buf[:count]
offset = 0
for i := 0; i < count; i++ {
s := msg[offset:]
r, len := utf8.decode_rune(s)
runes[count-i-1] = r
offset += len
}
offset = 0
for i := 0; i < count; i++ {
data, len := utf8.encode_rune(runes[i])
for j := 0; j < len; j++ {
backing[offset+j] = data[j]
}
offset += len
}
reverse := backing[:count] as string
fmt.println(reverse)
}

View File

@@ -4,7 +4,7 @@
#import "os.odin"
#import "opengl.odin" as gl
TWO_HEARTS :: #rune "💕"
TWO_HEARTS :: '💕'
win32_perf_count_freq := win32.GetQueryPerformanceFrequency()
time_now :: proc() -> f64 {

View File

@@ -76,8 +76,8 @@ print_rune_to_buffer :: proc(buf: ^[]byte, r: rune) {
print_string_to_buffer(buf, b[:n] as string)
}
print_space_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune " ") }
print_nl_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune "\n") }
print_space_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, ' ') }
print_nl_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, '\n') }
__NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"
@@ -99,7 +99,7 @@ print_u64_to_buffer :: proc(buffer: ^[]byte, value: u64) {
buf: [20]byte
len := 0
if i == 0 {
buf[len] = #rune "0"
buf[len] = '0'
len++
}
for i > 0 {
@@ -115,7 +115,7 @@ print_i64_to_buffer :: proc(buffer: ^[]byte, value: i64) {
neg := i < 0
if neg {
i = -i
print_rune_to_buffer(buffer, #rune "-")
print_rune_to_buffer(buffer, '-')
}
print_u64_to_buffer(buffer, i as u64)
}
@@ -132,7 +132,7 @@ print_i128_to_buffer :: proc(buffer: ^[]byte, value: i128) {
neg := i < 0
if neg {
i = -i
print_rune_to_buffer(buffer, #rune "-")
print_rune_to_buffer(buffer, '-')
}
print_u128_to_buffer(buffer, i as u128)
}
@@ -142,11 +142,11 @@ print_i128_to_buffer :: proc(buffer: ^[]byte, value: i128) {
print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
f := value
if f == 0 {
print_rune_to_buffer(buffer, #rune "0")
print_rune_to_buffer(buffer, '0')
return
}
if f < 0 {
print_rune_to_buffer(buffer, #rune "-")
print_rune_to_buffer(buffer, '-')
f = -f
}
@@ -154,7 +154,7 @@ print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
print_u64_to_buffer(buffer, i)
f -= i as f64
print_rune_to_buffer(buffer, #rune ".")
print_rune_to_buffer(buffer, '.')
mult: f64 = 10.0
for ; decimal_places >= 0; decimal_places-- {
@@ -488,7 +488,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
is_digit :: proc(r: rune) -> bool #inline {
return r >= #rune "0" && r <= #rune "9"
return '0' <= r && r <= '9'
}
parse_int :: proc(s: string, offset: int) -> (int, int) {
@@ -501,7 +501,7 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
}
result *= 10
result += (c - #rune "0") as int
result += (c - '0') as int
}
return result, offset
@@ -514,7 +514,7 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
r := fmt[i] as rune
index := implicit_index
if r != #rune "%" {
if r != '%' {
continue
}
@@ -523,7 +523,7 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
if i < fmt.count {
next := fmt[i] as rune
if next == #rune "%" {
if next == '%' {
print_string_to_buffer(buf, "%")
i++
prev = i
@@ -582,7 +582,7 @@ bprint :: proc(buf: ^[]byte, args: ..any) -> int {
bprintln :: proc(buf: ^[]byte, args: ..any) -> int {
for i := 0; i < args.count; i++ {
if i > 0 {
append(buf, #rune " ")
append(buf, ' ')
}
print_any_to_buffer(buf, args[i])
}

View File

@@ -1,8 +1,8 @@
RUNE_ERROR :: #rune "\ufffd"
RUNE_ERROR :: '\ufffd'
RUNE_SELF :: 0x80
RUNE_BOM :: 0xfeff
RUNE_EOF :: ~(0 as rune)
MAX_RUNE :: #rune "\U0010ffff"
MAX_RUNE :: '\U0010ffff'
UTF_MAX :: 4

View File

@@ -1,6 +1,8 @@
#foreign_system_library "user32"
#foreign_system_library "gdi32"
_:= compile_assert(ODIN_OS == "windows")
HANDLE :: type rawptr
HWND :: type HANDLE
HDC :: type HANDLE
@@ -387,43 +389,43 @@ Key_Code :: enum i32 {
DELETE = 0x2E,
HELP = 0x2F,
NUM0 = #rune "0",
NUM1 = #rune "1",
NUM2 = #rune "2",
NUM3 = #rune "3",
NUM4 = #rune "4",
NUM5 = #rune "5",
NUM6 = #rune "6",
NUM7 = #rune "7",
NUM8 = #rune "8",
NUM9 = #rune "9",
NUM0 = '0',
NUM1 = '1',
NUM2 = '2',
NUM3 = '3',
NUM4 = '4',
NUM5 = '5',
NUM6 = '6',
NUM7 = '7',
NUM8 = '8',
NUM9 = '9',
A = #rune "A",
B = #rune "B",
C = #rune "C",
D = #rune "D",
E = #rune "E",
F = #rune "F",
G = #rune "G",
H = #rune "H",
I = #rune "I",
J = #rune "J",
K = #rune "K",
L = #rune "L",
M = #rune "M",
N = #rune "N",
O = #rune "O",
P = #rune "P",
Q = #rune "Q",
R = #rune "R",
S = #rune "S",
T = #rune "T",
U = #rune "U",
V = #rune "V",
W = #rune "W",
X = #rune "X",
Y = #rune "Y",
Z = #rune "Z",
A = 'A',
B = 'B',
C = 'C',
D = 'D',
E = 'E',
F = 'F',
G = 'G',
H = 'H',
I = 'I',
J = 'J',
K = 'K',
L = 'L',
M = 'M',
N = 'N',
O = 'O',
P = 'P',
Q = 'Q',
R = 'R',
S = 'S',
T = 'T',
U = 'U',
V = 'V',
W = 'W',
X = 'X',
Y = 'Y',
Z = 'Z',
LWIN = 0x5B,
RWIN = 0x5C,

View File

@@ -11,8 +11,8 @@ GB_STATIC_ASSERT(ARRAY_GROW_FORMULA(0) > 0);
typedef Array(void) ArrayVoid;
#define array_init_reserve(x_, allocator_, init_capacity_) do { \
GB_ASSERT((x_) != NULL); \
void **e = cast(void **)&((x_)->e); \
GB_ASSERT((x_) != NULL); \
(x_)->allocator = (allocator_); \
(x_)->count = 0; \
(x_)->capacity = (init_capacity_); \
@@ -20,8 +20,8 @@ typedef Array(void) ArrayVoid;
} while (0)
#define array_init_count(x_, allocator_, init_count_) do { \
GB_ASSERT((x_) != NULL); \
void **e = cast(void **)&((x_)->e); \
GB_ASSERT((x_) != NULL); \
(x_)->allocator = (allocator_); \
(x_)->count = (init_count_); \
(x_)->capacity = (init_count_); \
@@ -67,8 +67,8 @@ typedef Array(void) ArrayVoid;
void array__set_capacity(void *ptr, isize capacity, isize element_size) {
GB_ASSERT(ptr != NULL);
ArrayVoid *x = cast(ArrayVoid *)ptr;
GB_ASSERT(ptr != NULL);
GB_ASSERT(element_size > 0);

View File

@@ -271,8 +271,9 @@ CycleChecker *cycle_checker_add(CycleChecker *cc, Entity *e) {
if (cc->path.e == NULL) {
array_init(&cc->path, heap_allocator());
}
GB_ASSERT(e != NULL && e->kind == Entity_TypeName);
array_add(&cc->path, e);
if (e != NULL && e->kind == Entity_TypeName) {
array_add(&cc->path, e);
}
return cc;
}
@@ -508,6 +509,11 @@ void add_global_constant(gbAllocator a, String name, Type *type, ExactValue valu
}
void add_global_string_constant(gbAllocator a, String name, String value) {
add_global_constant(a, name, t_untyped_string, make_exact_value_string(value));
}
void init_universal_scope(void) {
// NOTE(bill): No need to free these
@@ -528,9 +534,11 @@ void init_universal_scope(void) {
add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil));
add_global_constant(a, str_lit("ODIN_OS"), t_untyped_string, make_exact_value_string(str_lit("windows")));
add_global_constant(a, str_lit("ODIN_ARCH"), t_untyped_string, make_exact_value_string(str_lit("amd64")));
add_global_constant(a, str_lit("ODIN_VERSION"), t_untyped_string, make_exact_value_string(str_lit(VERSION_STRING)));
add_global_string_constant(a, str_lit("ODIN_OS"), str_lit("windows"));
add_global_string_constant(a, str_lit("ODIN_ARCH"), str_lit("amd64"));
add_global_string_constant(a, str_lit("ODIN_VENDOR"), str_lit("odin"));
add_global_string_constant(a, str_lit("ODIN_VERSION"), str_lit(VERSION_STRING));
add_global_string_constant(a, str_lit("ODIN_ENDIAN"), str_lit("little"));
// Builtin Procedures

View File

@@ -713,12 +713,10 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
if (o.mode != Addressing_Invalid) {
iota = o.value;
} else {
Token add_token = {Token_Add};
iota = exact_binary_operator_value(add_token, iota, make_exact_value_integer(1));
iota = exact_binary_operator_value(Token_Add, iota, make_exact_value_integer(1));
}
} else {
Token add_token = {Token_Add};
iota = exact_binary_operator_value(add_token, iota, make_exact_value_integer(1));
iota = exact_binary_operator_value(Token_Add, iota, make_exact_value_integer(1));
}
@@ -1492,7 +1490,7 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
if (is_type_unsigned(type)) {
precision = cast(i32)(8 * type_size_of(c->sizes, c->allocator, type));
}
o->value = exact_unary_operator_value(op, o->value, precision);
o->value = exact_unary_operator_value(op.kind, o->value, precision);
if (is_type_typed(type)) {
if (node != NULL) {
@@ -1558,7 +1556,7 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
} else {
if (x->mode == Addressing_Constant &&
y->mode == Addressing_Constant) {
x->value = make_exact_value_bool(compare_exact_values(op, x->value, y->value));
x->value = make_exact_value_bool(compare_exact_values(op.kind, x->value, y->value));
} else {
x->mode = Addressing_Value;
@@ -1645,7 +1643,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
x->type = t_untyped_integer;
}
x->value = exact_value_shift(be->op, x_val, make_exact_value_integer(amount));
x->value = exact_value_shift(be->op.kind, x_val, make_exact_value_integer(amount));
if (is_type_typed(x->type)) {
check_is_expressible(c, x, base_type(x->type));
@@ -2168,7 +2166,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
if (op.kind == Token_Quo && is_type_integer(type)) {
op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers
}
x->value = exact_binary_operator_value(op, a, b);
x->value = exact_binary_operator_value(op.kind, a, b);
if (is_type_typed(type)) {
if (node != NULL) {
x->expr = node;
@@ -3166,7 +3164,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
case BuiltinProc_min: {
// min :: proc(a, b: comparable) -> comparable
Type *type = base_type(operand->type);
if (!is_type_comparable(type) || !is_type_numeric(type)) {
if (!is_type_comparable(type) || !(is_type_numeric(type) || is_type_string(type))) {
gbString type_str = type_to_string(operand->type);
error(ast_node_token(call),
"Expected a comparable numeric type to `min`, got `%s`",
@@ -3182,7 +3180,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
if (b.mode == Addressing_Invalid) {
return false;
}
if (!is_type_comparable(b.type) || !is_type_numeric(type)) {
if (!is_type_comparable(b.type) || !(is_type_numeric(b.type) || is_type_string(b.type))) {
gbString type_str = type_to_string(b.type);
error(ast_node_token(call),
"Expected a comparable numeric type to `min`, got `%s`",
@@ -3195,10 +3193,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
b.mode == Addressing_Constant) {
ExactValue x = a.value;
ExactValue y = b.value;
Token lt = {Token_Lt};
operand->mode = Addressing_Constant;
if (compare_exact_values(lt, x, y)) {
if (compare_exact_values(Token_Lt, x, y)) {
operand->value = x;
operand->type = a.type;
} else {
@@ -3235,10 +3232,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
case BuiltinProc_max: {
// min :: proc(a, b: comparable) -> comparable
Type *type = base_type(operand->type);
if (!is_type_comparable(type) || !is_type_numeric(type)) {
if (!is_type_comparable(type) || !(is_type_numeric(type) || is_type_string(type))) {
gbString type_str = type_to_string(operand->type);
error(ast_node_token(call),
"Expected a comparable numeric type to `max`, got `%s`",
"Expected a comparable numeric or string type to `max`, got `%s`",
type_str);
gb_string_free(type_str);
return false;
@@ -3251,10 +3248,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
if (b.mode == Addressing_Invalid) {
return false;
}
if (!is_type_comparable(b.type) || !is_type_numeric(type)) {
if (!is_type_comparable(b.type) || !(is_type_numeric(type) || is_type_string(type))) {
gbString type_str = type_to_string(b.type);
error(ast_node_token(call),
"Expected a comparable numeric type to `max`, got `%s`",
"Expected a comparable numeric or string type to `max`, got `%s`",
type_str);
gb_string_free(type_str);
return false;
@@ -3264,10 +3261,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
b.mode == Addressing_Constant) {
ExactValue x = a.value;
ExactValue y = b.value;
Token gt = {Token_Gt};
operand->mode = Addressing_Constant;
if (compare_exact_values(gt, x, y)) {
if (compare_exact_values(Token_Gt, x, y)) {
operand->value = x;
operand->type = a.type;
} else {

View File

@@ -683,7 +683,8 @@ bool is_type_comparable(Type *t) {
return false;
} break;
case Type_Array:
return is_type_comparable(t->Array.elem);
return false;
// return is_type_comparable(t->Array.elem);
case Type_Vector:
return is_type_comparable(t->Vector.elem);
case Type_Proc:

View File

@@ -14,14 +14,19 @@ gb_global bool global_module_path_set = false;
String get_module_dir() {
String path = global_module_path;
Array(wchar_t) path_buf;
isize len, i;
gbTempArenaMemory tmp;
wchar_t *text;
if (global_module_path_set) {
return global_module_path;
}
Array(wchar_t) path_buf;
array_init_count(&path_buf, heap_allocator(), 300);
isize len = 0;
len = 0;
for (;;) {
len = GetModuleFileNameW(NULL, &path_buf.e[0], path_buf.count);
if (len == 0) {
@@ -33,13 +38,13 @@ String get_module_dir() {
array_resize(&path_buf, 2*path_buf.count + 300);
}
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
GetModuleFileNameW(NULL, text, len);
String path = string16_to_string(heap_allocator(), make_string16(text, len));
for (isize i = path.len-1; i >= 0; i--) {
path = string16_to_string(heap_allocator(), make_string16(text, len));
for (i = path.len-1; i >= 0; i--) {
u8 c = path.text[i];
if (c == '/' || c == '\\') {
break;
@@ -141,8 +146,9 @@ i16 f32_to_f16(f32 value) {
if (e > 30) {
float volatile f = 1e12f;
int j;
for (j = 0; j < 10; j++)
for (j = 0; j < 10; j++) {
f *= f; /* NOTE(bill): Cause overflow */
}
return cast(i16)(s | 0x7c00);
}

View File

@@ -148,8 +148,8 @@ ExactValue exact_value_to_float(ExactValue v) {
}
ExactValue exact_unary_operator_value(Token op, ExactValue v, i32 precision) {
switch (op.kind) {
ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision) {
switch (op) {
case Token_Add: {
switch (v.kind) {
case ExactValue_Invalid:
@@ -207,7 +207,7 @@ ExactValue exact_unary_operator_value(Token op, ExactValue v, i32 precision) {
}
failure:
GB_PANIC("Invalid unary operation, %.*s", LIT(token_strings[op.kind]));
GB_PANIC("Invalid unary operation, %.*s", LIT(token_strings[op]));
ExactValue error_value = {0};
return error_value;
@@ -270,7 +270,7 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
}
// TODO(bill): Allow for pointer arithmetic? Or are pointer slices good enough?
ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y) {
match_exact_values(&x, &y);
switch (x.kind) {
@@ -278,7 +278,7 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
return x;
case ExactValue_Bool:
switch (op.kind) {
switch (op) {
case Token_CmpAnd: return make_exact_value_bool(x.value_bool && y.value_bool);
case Token_CmpOr: return make_exact_value_bool(x.value_bool || y.value_bool);
case Token_And: return make_exact_value_bool(x.value_bool & y.value_bool);
@@ -291,7 +291,7 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
i64 a = x.value_integer;
i64 b = y.value_integer;
i64 c = 0;
switch (op.kind) {
switch (op) {
case Token_Add: c = a + b; break;
case Token_Sub: c = a - b; break;
case Token_Mul: c = a * b; break;
@@ -312,7 +312,7 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
case ExactValue_Float: {
f64 a = x.value_float;
f64 b = y.value_float;
switch (op.kind) {
switch (op) {
case Token_Add: return make_exact_value_float(a + b);
case Token_Sub: return make_exact_value_float(a - b);
case Token_Mul: return make_exact_value_float(a * b);
@@ -324,22 +324,22 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
error:
ExactValue error_value = {0};
// gb_printf_err("Invalid binary operation: %s\n", token_kind_to_string(op.kind));
// gb_printf_err("Invalid binary operation: %s\n", token_kind_to_string(op));
return error_value;
}
gb_inline ExactValue exact_value_add(ExactValue x, ExactValue y) { Token op = {Token_Add}; return exact_binary_operator_value(op, x, y); }
gb_inline ExactValue exact_value_sub(ExactValue x, ExactValue y) { Token op = {Token_Sub}; return exact_binary_operator_value(op, x, y); }
gb_inline ExactValue exact_value_mul(ExactValue x, ExactValue y) { Token op = {Token_Mul}; return exact_binary_operator_value(op, x, y); }
gb_inline ExactValue exact_value_quo(ExactValue x, ExactValue y) { Token op = {Token_Quo}; return exact_binary_operator_value(op, x, y); }
gb_inline ExactValue exact_value_shift(Token op, ExactValue x, ExactValue y) { return exact_binary_operator_value(op, x, y); }
gb_inline ExactValue exact_value_add(ExactValue x, ExactValue y) { return exact_binary_operator_value(Token_Add, x, y); }
gb_inline ExactValue exact_value_sub(ExactValue x, ExactValue y) { return exact_binary_operator_value(Token_Sub, x, y); }
gb_inline ExactValue exact_value_mul(ExactValue x, ExactValue y) { return exact_binary_operator_value(Token_Mul, x, y); }
gb_inline ExactValue exact_value_quo(ExactValue x, ExactValue y) { return exact_binary_operator_value(Token_Quo, x, y); }
gb_inline ExactValue exact_value_shift(TokenKind op, ExactValue x, ExactValue y) { return exact_binary_operator_value(op, x, y); }
i32 cmp_f64(f64 a, f64 b) {
return (a > b) - (a < b);
}
bool compare_exact_values(Token op, ExactValue x, ExactValue y) {
bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
match_exact_values(&x, &y);
switch (x.kind) {
@@ -347,7 +347,7 @@ bool compare_exact_values(Token op, ExactValue x, ExactValue y) {
return false;
case ExactValue_Bool:
switch (op.kind) {
switch (op) {
case Token_CmpEq: return x.value_bool == y.value_bool;
case Token_NotEq: return x.value_bool != y.value_bool;
}
@@ -356,7 +356,7 @@ bool compare_exact_values(Token op, ExactValue x, ExactValue y) {
case ExactValue_Integer: {
i64 a = x.value_integer;
i64 b = y.value_integer;
switch (op.kind) {
switch (op) {
case Token_CmpEq: return a == b;
case Token_NotEq: return a != b;
case Token_Lt: return a < b;
@@ -369,7 +369,7 @@ bool compare_exact_values(Token op, ExactValue x, ExactValue y) {
case ExactValue_Float: {
f64 a = x.value_float;
f64 b = y.value_float;
switch (op.kind) {
switch (op) {
case Token_CmpEq: return cmp_f64(a, b) == 0;
case Token_NotEq: return cmp_f64(a, b) != 0;
case Token_Lt: return cmp_f64(a, b) < 0;
@@ -384,7 +384,7 @@ bool compare_exact_values(Token op, ExactValue x, ExactValue y) {
String b = y.value_string;
isize len = gb_min(a.len, b.len);
// TODO(bill): gb_memcompare is used because the strings are UTF-8
switch (op.kind) {
switch (op) {
case Token_CmpEq: return gb_memcompare(a.text, b.text, len) == 0;
case Token_NotEq: return gb_memcompare(a.text, b.text, len) != 0;
case Token_Lt: return gb_memcompare(a.text, b.text, len) < 0;

View File

@@ -243,6 +243,7 @@ void _J2(MAP_PROC,set)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
void _J2(MAP_PROC,_erase)(MAP_NAME *h, MapFindResult fr) {
MapFindResult last;
if (fr.entry_prev < 0) {
h->hashes.e[fr.hash_index] = h->entries.e[fr.entry_index].next;
} else {
@@ -253,7 +254,7 @@ void _J2(MAP_PROC,_erase)(MAP_NAME *h, MapFindResult fr) {
return;
}
h->entries.e[fr.entry_index] = h->entries.e[h->entries.count-1];
MapFindResult last = _J2(MAP_PROC,_find)(h, h->entries.e[fr.entry_index].key);
last = _J2(MAP_PROC,_find)(h, h->entries.e[fr.entry_index].key);
if (last.entry_prev >= 0) {
h->entries.e[last.entry_prev].next = fr.entry_index;
} else {
@@ -314,11 +315,13 @@ void _J2(MAP_PROC,multi_get_all)(MAP_NAME *h, HashKey key, MAP_TYPE *items) {
}
void _J2(MAP_PROC,multi_insert)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
MapFindResult fr;
isize i;
if (h->hashes.count == 0) {
_J2(MAP_PROC,grow)(h);
}
MapFindResult fr = _J2(MAP_PROC,_find)(h, key);
isize i = _J2(MAP_PROC,_add_entry)(h, key);
fr = _J2(MAP_PROC,_find)(h, key);
i = _J2(MAP_PROC,_add_entry)(h, key);
if (fr.entry_prev < 0) {
h->hashes.e[fr.hash_index] = i;
} else {

View File

@@ -32,7 +32,7 @@ typedef struct AstFile {
isize expr_level;
AstNodeArray decls;
bool is_global_scope;
bool is_global_scope;
AstNode * curr_proc;
isize scope_level;
@@ -86,13 +86,6 @@ typedef enum StmtStateFlag {
StmtStateFlag_no_bounds_check = GB_BIT(1),
} StmtStateFlag;
typedef enum CallExprKind {
CallExpr_Prefix, // call(...)
CallExpr_Postfix, // a'call
CallExpr_Infix, // a ''call b
} CallExprKind;
AstNodeArray make_ast_node_array(AstFile *f) {
AstNodeArray a;
array_init(&a, gb_arena_allocator(&f->arena));
@@ -134,7 +127,6 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
AstNodeArray args; \
Token open, close; \
Token ellipsis; \
CallExprKind kind; \
}) \
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
AstNode *expr; \
@@ -256,9 +248,10 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
}) \
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
Token token, relpath; \
String os, arch; \
String fullpath; \
Token import_name; \
bool is_load; \
bool is_load; \
AstNode *note; \
}) \
AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \
@@ -959,11 +952,15 @@ AstNode *make_type_decl(AstFile *f, Token token, AstNode *name, AstNode *type) {
return result;
}
AstNode *make_import_decl(AstFile *f, Token token, Token relpath, Token import_name, bool is_load) {
AstNode *make_import_decl(AstFile *f, Token token, Token relpath, Token import_name,
String os, String arch,
bool is_load) {
AstNode *result = make_node(f, AstNode_ImportDecl);
result->ImportDecl.token = token;
result->ImportDecl.relpath = relpath;
result->ImportDecl.import_name = import_name;
result->ImportDecl.os = os;
result->ImportDecl.arch = arch;
result->ImportDecl.is_load = is_load;
return result;
}
@@ -1374,19 +1371,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
case Token_Hash: {
Token token = expect_token(f, Token_Hash);
Token name = expect_token(f, Token_Identifier);
if (str_eq(name.string, str_lit("rune"))) {
if (f->curr_token.kind == Token_String) {
Token *s = &f->curr_token;
if (gb_utf8_strnlen(s->string.text, s->string.len) != 1) {
syntax_error(*s, "Invalid rune literal %.*s", LIT(s->string));
}
s->kind = Token_Rune; // NOTE(bill): Change it
} else {
expect_token(f, Token_String);
}
operand = parse_operand(f, lhs);
} else if (str_eq(name.string, str_lit("file"))) {
if (str_eq(name.string, str_lit("file"))) {
Token token = name;
token.kind = Token_String;
token.string = token.pos.file;
@@ -1513,19 +1498,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
bool loop = true;
while (loop) {
switch (f->curr_token.kind) {
case Token_Prime: {
Token op = expect_token(f, Token_Prime);
if (lhs) {
// TODO(bill): Handle this
}
AstNode *proc = parse_identifier(f);
AstNodeArray args;
array_init_reserve(&args, gb_arena_allocator(&f->arena), 1);
array_add(&args, operand);
operand = make_call_expr(f, proc, args, ast_node_token(operand), op, empty_token);
} break;
case Token_OpenParen: {
if (lhs) {
// TODO(bill): Handle this shit! Is this even allowed in this language?!
@@ -1680,13 +1652,11 @@ i32 token_precedence(Token t) {
case Token_Shl:
case Token_Shr:
return 5;
case Token_DoublePrime:
return 6;
case Token_as:
case Token_transmute:
case Token_down_cast:
case Token_union_cast:
return 7;
return 6;
}
return 0;
@@ -1708,28 +1678,6 @@ AstNode *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
}
switch (op.kind) {
case Token_DoublePrime: {
// TODO(bill): Properly define semantic for in-fix and post-fix calls
AstNode *proc = parse_identifier(f);
/* if (f->curr_token.kind == Token_OpenParen) {
AstNode *call = parse_call_expr(f, proc);
array_add(&call->CallExpr.args, expression);
for (isize i = gb_array_count(call->CallExpr.args)-1; i > 0; i--) {
gb_swap(AstNode *, call->CallExpr.args[i], call->CallExpr.args[i-1]);
}
expression = call;
} else */{
right = parse_binary_expr(f, false, prec+1);
AstNodeArray args = {0};
array_init_reserve(&args, gb_arena_allocator(&f->arena), 2);
array_add(&args, expression);
array_add(&args, right);
expression = make_call_expr(f, proc, args, op, ast_node_token(right), empty_token);
}
continue;
} break;
case Token_as:
case Token_transmute:
case Token_down_cast:
@@ -2755,42 +2703,6 @@ AstNode *parse_stmt(AstFile *f) {
}
syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope");
return make_bad_decl(f, token, f->curr_token);
} else if (str_eq(tag, str_lit("import"))) {
// TODO(bill): better error messages
Token import_name = {0};
Token file_path = expect_token_after(f, Token_String, "#import");
if (allow_token(f, Token_as)) {
// NOTE(bill): Custom import name
if (f->curr_token.kind == Token_Period) {
import_name = f->curr_token;
import_name.kind = Token_Identifier;
next_token(f);
} else {
import_name = expect_token_after(f, Token_Identifier, "`as` for import declaration");
}
if (str_eq(import_name.string, str_lit("_"))) {
syntax_error(token, "Illegal import name: `_`");
return make_bad_decl(f, token, f->curr_token);
}
}
if (f->curr_proc == NULL) {
return make_import_decl(f, s->TagStmt.token, file_path, import_name, false);
}
syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope");
return make_bad_decl(f, token, file_path);
} else if (str_eq(tag, str_lit("load"))) {
// TODO(bill): better error messages
Token file_path = expect_token(f, Token_String);
Token import_name = file_path;
import_name.string = str_lit(".");
if (f->curr_proc == NULL) {
return make_import_decl(f, s->TagStmt.token, file_path, import_name, true);
}
syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope");
return make_bad_decl(f, token, file_path);
} else if (str_eq(tag, str_lit("foreign_system_library"))) {
Token file_path = expect_token(f, Token_String);
if (f->curr_proc == NULL) {
@@ -2831,6 +2743,54 @@ AstNode *parse_stmt(AstFile *f) {
syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
}
return s;
} else if (str_eq(tag, str_lit("import"))) {
String os = {0};
String arch = {0};
// if (tag.len > 6) {
// String sub = make_string(tag.text+6, tag.len-6);
// }
// TODO(bill): better error messages
Token import_name = {0};
Token file_path = expect_token_after(f, Token_String, "#import");
if (allow_token(f, Token_as)) {
// NOTE(bill): Custom import name
if (f->curr_token.kind == Token_Period) {
import_name = f->curr_token;
import_name.kind = Token_Identifier;
next_token(f);
} else {
import_name = expect_token_after(f, Token_Identifier, "`as` for import declaration");
}
if (str_eq(import_name.string, str_lit("_"))) {
syntax_error(token, "Illegal import name: `_`");
return make_bad_decl(f, token, f->curr_token);
}
}
if (f->curr_proc != NULL) {
syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope");
return make_bad_decl(f, token, file_path);
}
return make_import_decl(f, s->TagStmt.token, file_path, import_name, os, arch, false);
} else if (str_eq(tag, str_lit("load"))) {
String os = {0};
String arch = {0};
// TODO(bill): better error messages
Token file_path = expect_token(f, Token_String);
Token import_name = file_path;
import_name.string = str_lit(".");
if (f->curr_proc == NULL) {
return make_import_decl(f, s->TagStmt.token, file_path, import_name, os, arch, true);
}
syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope");
return make_bad_decl(f, token, file_path);
} else {
}
s->TagStmt.stmt = parse_stmt(f); // TODO(bill): Find out why this doesn't work as an argument

View File

@@ -2447,27 +2447,11 @@ void ssa_emit_slice_bounds_check(ssaProcedure *proc, Token token, ssaValue *low,
return;
}
low = ssa_emit_conv(proc, low, t_int);
high = ssa_emit_conv(proc, high, t_int);
max = ssa_emit_conv(proc, max, t_int);
ssa_emit(proc, ssa_make_instr_slice_bounds_check(proc, token.pos, low, high, max, is_substring));
// gbAllocator a = proc->module->allocator;
// ssaValue **args = gb_alloc_array(a, ssaValue *, 6);
// args[0] = ssa_emit_global_string(proc, token.pos.file);
// args[1] = ssa_make_const_int(a, token.pos.line);
// args[2] = ssa_make_const_int(a, token.pos.column);
// args[3] = ssa_emit_conv(proc, low, t_int);
// args[4] = ssa_emit_conv(proc, high, t_int);
// args[5] = ssa_emit_conv(proc, max, t_int);
// if (!is_substring) {
// ssa_emit_global_call(proc, "__slice_expr_error", args, 6);
// } else {
// ssa_emit_global_call(proc, "__substring_expr_error", args, 5);
// }
}
@@ -2878,7 +2862,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
Type *elem_type = slice_type->Slice.elem;
i64 size_of_elem = type_size_of(proc->module->sizes, proc->module->allocator, elem_type);
ssaValue *dst = ssa_emit_conv(proc, ssa_slice_elem(proc, dst_slice), t_rawptr);
ssaValue *src = ssa_emit_conv(proc, ssa_slice_elem(proc, src_slice), t_rawptr);
@@ -3031,7 +3014,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssa_emit_comment(proc, str_lit("min"));
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
ssaValue *y = ssa_build_expr(proc, ce->args.e[1]);
Type *t = base_type(ssa_type(x));
ssaValue *cond = ssa_emit_comp(proc, Token_Lt, x, y);
return ssa_emit_select(proc, cond, x, y);
} break;
@@ -3040,7 +3022,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssa_emit_comment(proc, str_lit("max"));
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
ssaValue *y = ssa_build_expr(proc, ce->args.e[1]);
Type *t = base_type(ssa_type(x));
ssaValue *cond = ssa_emit_comp(proc, Token_Gt, x, y);
return ssa_emit_select(proc, cond, x, y);
} break;

View File

@@ -52,7 +52,8 @@ gb_inline String make_string_c(char *text) {
gb_inline bool str_eq_ignore_case(String a, String b) {
if (a.len == b.len) {
for (isize i = 0; i < a.len; i++) {
isize i;
for (i = 0; i < a.len; i++) {
char x = cast(char)a.text[i];
char y = cast(char)b.text[i];
if (gb_char_to_lower(x) != gb_char_to_lower(y))
@@ -64,39 +65,40 @@ gb_inline bool str_eq_ignore_case(String a, String b) {
}
int string_compare(String x, String y) {
if (x.len == y.len &&
x.text == y.text) {
return 0;
}
if (!(x.len == y.len &&
x.text == y.text)) {
isize n, fast, offset, curr_block;
isize *la, *lb;
isize pos;
isize n = gb_min(x.len, y.len);
n = gb_min(x.len, y.len);
isize fast = n/gb_size_of(isize) + 1;
isize offset = (fast-1)*gb_size_of(isize);
isize curr_block = 0;
if (n <= gb_size_of(isize)) {
fast = 0;
}
fast = n/gb_size_of(isize) + 1;
offset = (fast-1)*gb_size_of(isize);
curr_block = 0;
if (n <= gb_size_of(isize)) {
fast = 0;
}
isize *la = cast(isize *)x.text;
isize *lb = cast(isize *)y.text;
la = cast(isize *)x.text;
lb = cast(isize *)y.text;
for (; curr_block < fast; curr_block++) {
if (la[curr_block] ^ lb[curr_block]) {
for (isize pos = curr_block*gb_size_of(isize); pos < n; pos++) {
if (x.text[pos] ^ y.text[pos]) {
return cast(int)x.text[pos] - cast(int)y.text[pos];
for (; curr_block < fast; curr_block++) {
if (la[curr_block] ^ lb[curr_block]) {
for (pos = curr_block*gb_size_of(isize); pos < n; pos++) {
if (x.text[pos] ^ y.text[pos]) {
return cast(int)x.text[pos] - cast(int)y.text[pos];
}
}
}
}
}
for (; offset < n; offset++) {
if (x.text[offset] ^ y.text[offset]) {
return cast(int)x.text[offset] - cast(int)y.text[offset];
for (; offset < n; offset++) {
if (x.text[offset] ^ y.text[offset]) {
return cast(int)x.text[offset] - cast(int)y.text[offset];
}
}
}
return 0;
}
@@ -126,7 +128,18 @@ gb_inline bool str_gt(String a, String b) { return string_compare(a, b) > 0;
gb_inline bool str_le(String a, String b) { return string_compare(a, b) <= 0; }
gb_inline bool str_ge(String a, String b) { return string_compare(a, b) >= 0; }
gb_inline bool str_has_prefix(String s, String prefix) {
isize i;
if (prefix.len < s.len) {
return false;
}
for (i = 0; i < prefix.len; i++) {
if (s.text[i] != prefix.text[i]) {
return false;
}
}
return true;
}
gb_inline isize string_extension_position(String str) {
isize dot_pos = -1;
@@ -157,7 +170,8 @@ gb_inline bool string_has_extension(String str, String ext) {
}
bool string_contains_char(String s, u8 c) {
for (isize i = 0; i < s.len; i++) {
isize i;
for (i = 0; i < s.len; i++) {
if (s.text[i] == c)
return true;
}
@@ -166,20 +180,23 @@ bool string_contains_char(String s, u8 c) {
// TODO(bill): Make this non-windows specific
String16 string_to_string16(gbAllocator a, String s) {
int len, len1;
wchar_t *text;
if (s.len < 1) {
return make_string16(NULL, 0);
}
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
cast(char *)s.text, s.len, NULL, 0);
len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
cast(char *)s.text, s.len, NULL, 0);
if (len == 0) {
return make_string16(NULL, 0);
}
wchar_t *text = gb_alloc_array(a, wchar_t, len+1);
text = gb_alloc_array(a, wchar_t, len+1);
int len1 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
cast(char *)s.text, s.len, text, len);
len1 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
cast(char *)s.text, s.len, text, len);
if (len1 == 0) {
gb_free(a, text);
return make_string16(NULL, 0);
@@ -190,22 +207,23 @@ String16 string_to_string16(gbAllocator a, String s) {
}
String string16_to_string(gbAllocator a, String16 s) {
int len, len1;
u8 *text;
if (s.len < 1) {
return make_string(NULL, 0);
}
int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
s.text, s.len, NULL, 0,
NULL, NULL);
len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
s.text, s.len, NULL, 0, NULL, NULL);
if (len == 0) {
return make_string(NULL, 0);
}
u8 *text = gb_alloc_array(a, u8, len+1);
text = gb_alloc_array(a, u8, len+1);
int len1 = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
s.text, s.len, cast(char *)text, len,
NULL, NULL);
len1 = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
s.text, s.len, cast(char *)text, len, NULL, NULL);
if (len1 == 0) {
gb_free(a, text);
return make_string(NULL, 0);
@@ -233,8 +251,10 @@ String string16_to_string(gbAllocator a, String16 s) {
bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *tail_string) {
u8 c;
if (s.text[0] == quote &&
(quote == '$' || quote == '"')) {
(quote == '\'' || quote == '"')) {
return false;
} else if (s.text[0] >= 0x80) {
Rune r = -1;
@@ -252,7 +272,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
if (s.len <= 1) {
return false;
}
u8 c = s.text[1];
c = s.text[1];
s = make_string(s.text+2, s.len-2);
switch (c) {
@@ -268,7 +288,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
case '\\': *rune = '\\'; break;
case '$':
case '\'':
case '"':
if (c != quote) {
return false;
@@ -284,11 +304,12 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
case '5':
case '6':
case '7': {
isize i;
i32 r = gb_digit_to_int(c);
if (s.len < 2) {
return false;
}
for (isize i = 0; i < 2; i++) {
for (i = 0; i < 2; i++) {
i32 d = gb_digit_to_int(s.text[i]);
if (d < 0 || d > 7) {
return false;
@@ -305,18 +326,18 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
case 'x':
case 'u':
case 'U': {
isize count = 0;
Rune r = 0;
isize i, count = 0;
switch (c) {
case 'x': count = 2; break;
case 'u': count = 4; break;
case 'U': count = 8; break;
}
Rune r = 0;
if (s.len < count) {
return false;
}
for (isize i = 0; i < count; i++) {
for (i = 0; i < count; i++) {
i32 d = gb_hex_digit_to_int(s.text[i]);
if (d < 0) {
return false;
@@ -344,14 +365,16 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
// 1 == original memory
// 2 == new allocation
i32 unquote_string(gbAllocator a, String *s_) {
GB_ASSERT(s_ != NULL);
String s = *s_;
isize n = s.len;
if (n < 2)
u8 quote;
if (n < 2) {
return 0;
u8 quote = s.text[0];
if (quote != s.text[n-1])
}
quote = s.text[0];
if (quote != s.text[n-1]) {
return 0;
}
s.text += 1;
s.len -= 2;
@@ -362,17 +385,19 @@ i32 unquote_string(gbAllocator a, String *s_) {
*s_ = s;
return 1;
}
if (quote != '"' && quote != '$')
if (quote != '"' && quote != '\'') {
return 0;
}
if (string_contains_char(s, '\n'))
if (string_contains_char(s, '\n')) {
return 0;
}
if (!string_contains_char(s, '\\') && !string_contains_char(s, quote)) {
if (quote == '"') {
*s_ = s;
return 1;
} else if (quote == '$') {
} else if (quote == '\'') {
Rune r = GB_RUNE_INVALID;
isize size = gb_utf8_decode(s.text, s.len, &r);
if ((size == s.len) && (r != -1 || size != 1)) {
@@ -383,34 +408,36 @@ i32 unquote_string(gbAllocator a, String *s_) {
}
u8 rune_temp[4] = {0};
isize buf_len = 3*s.len / 2;
u8 *buf = gb_alloc_array(a, u8, buf_len);
isize offset = 0;
while (s.len > 0) {
String tail_string = {0};
Rune r = 0;
bool multiple_bytes = false;
bool success = unquote_char(s, quote, &r, &multiple_bytes, &tail_string);
if (!success) {
gb_free(a, buf);
return 0;
}
s = tail_string;
{
u8 rune_temp[4] = {0};
isize buf_len = 3*s.len / 2;
u8 *buf = gb_alloc_array(a, u8, buf_len);
isize offset = 0;
while (s.len > 0) {
String tail_string = {0};
Rune r = 0;
bool multiple_bytes = false;
bool success = unquote_char(s, quote, &r, &multiple_bytes, &tail_string);
if (!success) {
gb_free(a, buf);
return 0;
}
s = tail_string;
if (r < 0x80 || !multiple_bytes) {
buf[offset++] = cast(u8)r;
} else {
isize size = gb_utf8_encode_rune(rune_temp, r);
gb_memmove(buf+offset, rune_temp, size);
offset += size;
}
if (r < 0x80 || !multiple_bytes) {
buf[offset++] = cast(u8)r;
} else {
isize size = gb_utf8_encode_rune(rune_temp, r);
gb_memmove(buf+offset, rune_temp, size);
offset += size;
}
if (quote == '$' && s.len != 0) {
gb_free(a, buf);
return 0;
if (quote == '\'' && s.len != 0) {
gb_free(a, buf);
return 0;
}
}
*s_ = make_string(buf, offset);
}
*s_ = make_string(buf, offset);
return 2;
}

View File

@@ -77,12 +77,13 @@ f64 time_stamp_as_ms(TimeStamp ts, u64 freq) {
}
void timings_print_all(Timings *t) {
char const SPACES[] = " ";
isize max_len, i;
timings__stop_current_section(t);
t->total.finish = time_stamp_time_now();
char const SPACES[] = " ";
isize max_len = t->total.label.len;
max_len = t->total.label.len;
for_array(i, t->sections) {
TimeStamp ts = t->sections.e[i];
max_len = gb_max(max_len, ts.label.len);

View File

@@ -34,9 +34,6 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
TOKEN_KIND(Token_transmute, "transmute"), \
TOKEN_KIND(Token_down_cast, "down_cast"), \
TOKEN_KIND(Token_union_cast, "union_cast"), \
\
TOKEN_KIND(Token_Prime, "'"), \
TOKEN_KIND(Token_DoublePrime, "''"), \
\
TOKEN_KIND(Token_CmpAnd, "&&"), \
TOKEN_KIND(Token_CmpOr, "||"), \
@@ -656,17 +653,50 @@ Token tokenizer_get_token(Tokenizer *t) {
token.kind = Token_EOF;
break;
case '\'':
token.kind = Token_Prime;
if (t->curr_rune == '\'') {
case '\'': // Rune Literal
{
token.kind = Token_Rune;
Rune quote = curr_rune;
bool valid = true;
i32 n = 0, success;
for (;;) {
Rune r = t->curr_rune;
if (r == '\n' || r < 0) {
tokenizer_err(t, "Rune literal not terminated");
break;
}
advance_to_next_rune(t);
token.kind = Token_DoublePrime;
if (r == quote) {
break;
}
n++;
if (r == '\\') {
if (!scan_escape(t, quote)) {
valid = false;
}
}
}
break;
// TODO(bill): Better Error Handling
if (valid && n != 1) {
tokenizer_err(t, "Invalid rune literal");
}
token.string.len = t->curr - token.string.text;
success = unquote_string(heap_allocator(), &token.string);
if (success > 0) {
if (success == 2) {
array_add(&t->allocated_strings, token.string);
}
return token;
} else {
tokenizer_err(t, "Invalid rune literal");
}
} break;
case '`': // Raw String Literal
case '"': // String Literal
{
i32 success;
Rune quote = curr_rune;
token.kind = Token_String;
if (curr_rune == '"') {
@@ -677,10 +707,12 @@ Token tokenizer_get_token(Tokenizer *t) {
break;
}
advance_to_next_rune(t);
if (r == quote)
if (r == quote) {
break;
if (r == '\\')
scan_escape(t, '"');
}
if (r == '\\') {
scan_escape(t, quote);
}
}
} else {
for (;;) {
@@ -690,12 +722,13 @@ Token tokenizer_get_token(Tokenizer *t) {
break;
}
advance_to_next_rune(t);
if (r == quote)
if (r == quote) {
break;
}
}
}
token.string.len = t->curr - token.string.text;
i32 success = unquote_string(heap_allocator(), &token.string);
success = unquote_string(heap_allocator(), &token.string);
if (success > 0) {
if (success == 2) {
array_add(&t->allocated_strings, token.string);

View File

@@ -42,10 +42,10 @@ bool rune_is_whitespace(Rune r) {
bool is_string_an_identifier(String s) {
isize offset = 0;
if (s.len < 1) {
return false;
}
isize offset = 0;
while (offset < s.len) {
bool ok = false;
Rune r = -1;