diff --git a/build.bat b/build.bat index 0b11f4dc210..bd97782128b 100644 --- a/build.bat +++ b/build.bat @@ -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 ^ diff --git a/code/demo.odin b/code/demo.odin index a1916e5893c..e516d3529de 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -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) } diff --git a/code/game.odin b/code/game.odin index c5d0c52f214..4760f024471 100644 --- a/code/game.odin +++ b/code/game.odin @@ -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 { diff --git a/core/fmt.odin b/core/fmt.odin index b2d6e4a09b7..abc2bae8f99 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -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]) } diff --git a/core/utf8.odin b/core/utf8.odin index 330db5b43a3..e4aab0b5559 100644 --- a/core/utf8.odin +++ b/core/utf8.odin @@ -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 diff --git a/core/win32.odin b/core/win32.odin index ffb9d5bd1a7..540990b901e 100644 --- a/core/win32.odin +++ b/core/win32.odin @@ -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", - - 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", + NUM0 = '0', + NUM1 = '1', + NUM2 = '2', + NUM3 = '3', + NUM4 = '4', + NUM5 = '5', + NUM6 = '6', + NUM7 = '7', + NUM8 = '8', + NUM9 = '9', + + 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, diff --git a/src/array.c b/src/array.c index 7e185e87278..d169a99ef28 100644 --- a/src/array.c +++ b/src/array.c @@ -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); diff --git a/src/checker/checker.c b/src/checker/checker.c index ccd97cad32f..e42e6126eb8 100644 --- a/src/checker/checker.c +++ b/src/checker/checker.c @@ -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 diff --git a/src/checker/expr.c b/src/checker/expr.c index 6f16da451ea..de6011a7980 100644 --- a/src/checker/expr.c +++ b/src/checker/expr.c @@ -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 { diff --git a/src/checker/types.c b/src/checker/types.c index f51cbb660ac..26ac633fb61 100644 --- a/src/checker/types.c +++ b/src/checker/types.c @@ -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: diff --git a/src/common.c b/src/common.c index 9b70722d1ce..2d4600b8995 100644 --- a/src/common.c +++ b/src/common.c @@ -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); } diff --git a/src/exact_value.c b/src/exact_value.c index 313cda694fe..d220cac6150 100644 --- a/src/exact_value.c +++ b/src/exact_value.c @@ -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; diff --git a/src/map.c b/src/map.c index eea0e30d6a6..f974a46db09 100644 --- a/src/map.c +++ b/src/map.c @@ -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 { diff --git a/src/parser.c b/src/parser.c index c5eae58b05c..79753c832ef 100644 --- a/src/parser.c +++ b/src/parser.c @@ -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 diff --git a/src/ssa.c b/src/ssa.c index b34bc7c51a5..42437d7e739 100644 --- a/src/ssa.c +++ b/src/ssa.c @@ -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; diff --git a/src/string.c b/src/string.c index b54b1d24fba..75a2e50b7a1 100644 --- a/src/string.c +++ b/src/string.c @@ -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; - } - - isize 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; - } + if (!(x.len == y.len && + x.text == y.text)) { + isize n, fast, offset, curr_block; + isize *la, *lb; + isize pos; + + n = gb_min(x.len, y.len); + + 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; - - 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; - } + { + 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 (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; } diff --git a/src/timings.c b/src/timings.c index a1eecc01abe..a934414ecfa 100644 --- a/src/timings.c +++ b/src/timings.c @@ -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); diff --git a/src/tokenizer.c b/src/tokenizer.c index edf6e972104..c7d62cb2b97 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -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); diff --git a/src/unicode.c b/src/unicode.c index 5c9f91f4681..e4bf28be8ae 100644 --- a/src/unicode.c +++ b/src/unicode.c @@ -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;