diff --git a/code/demo.odin b/code/demo.odin index c517169b0..9f9658e08 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -4,16 +4,14 @@ #import "mem.odin" -A :: struct { using e: [12]int } -Vector2 :: raw_union { - using _xy: struct #ordered { x, y: f32 } - using v: {2}f32 - e: [2]f32 -} main :: proc() { - v: Vector2 - v.x = 123 - v[1] = 321 + Vec3 :: struct { + x, y: i16 + z: int + } + + z := 123 + v := Vec3{x = 4, y = 5, z = z} fmt.println(v) } diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 7d32f4cce..f9000446e 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -619,9 +619,11 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode return; if (mode == Addressing_Constant) { - GB_ASSERT(value.kind != ExactValue_Invalid); - if (!(type != t_invalid || is_type_constant_type(type))) { - compiler_error("add_type_and_value - invalid type: %s", type_to_string(type)); + if (is_type_constant_type(type)) { + GB_ASSERT(value.kind != ExactValue_Invalid); + if (!(type != t_invalid || is_type_constant_type(type))) { + compiler_error("add_type_and_value - invalid type: %s", type_to_string(type)); + } } } diff --git a/src/checker/entity.cpp b/src/checker/entity.cpp index 32563de4c..138e46236 100644 --- a/src/checker/entity.cpp +++ b/src/checker/entity.cpp @@ -49,7 +49,8 @@ struct Entity { b8 anonymous; // Variable is an anonymous b8 is_using; // `using` variable - i32 field_index; // Order in source + i32 field_index; + i32 field_src_index; b8 is_field; // Is struct field } Variable; struct { @@ -124,9 +125,10 @@ Entity *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type, return entity; } -Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type, b32 is_anonymous, i32 field_index) { +Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type, b32 is_anonymous, i32 field_src_index) { Entity *entity = make_entity_variable(a, scope, token, type); - entity->Variable.field_index = field_index; + entity->Variable.field_src_index = field_src_index; + entity->Variable.field_index = field_src_index; entity->Variable.is_field = true; entity->Variable.anonymous = cast(b8)is_anonymous; entity->Variable.is_using = cast(b8)is_anonymous; diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 9bb28b2d3..9e2db6544 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -501,13 +501,16 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecke } // NOTE(bill): Hacky thing + // TODO(bill): Probably make an inline sorting procedure rather than use global variables __checker_sizes = c->sizes; __checker_allocator = c->allocator; - // TODO(bill): Figure out rules more - // sorting rules - // compound literal order must match source not layout + // NOTE(bill): compound literal order must match source not layout gb_sort_array(reordered_fields, field_count, cmp_struct_entity_size); + for (isize i = 0; i < field_count; i++) { + reordered_fields[i]->Variable.field_index = i; + } + struct_type->Record.fields = reordered_fields; } @@ -3256,6 +3259,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case_ast_node(cl, CompoundLit, node); Type *type = type_hint; b32 ellipsis_array = false; + b32 is_constant = true; if (cl->type != NULL) { type = NULL; @@ -3297,15 +3301,15 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint "Mixture of `field = value` and value elements in a structure literal is not allowed"); continue; } - ast_node(kv, FieldValue, elem); - if (kv->field->kind != AstNode_Ident) { - gbString expr_str = expr_to_string(kv->field); + ast_node(fv, FieldValue, elem); + if (fv->field->kind != AstNode_Ident) { + gbString expr_str = expr_to_string(fv->field); defer (gb_string_free(expr_str)); error(ast_node_token(elem), "Invalid field name `%s` in structure literal", expr_str); continue; } - String name = kv->field->Ident.string; + String name = fv->field->Ident.string; Selection sel = lookup_field(c->allocator, type, name, o->mode == Addressing_Type); if (sel.entity == NULL) { @@ -3321,7 +3325,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint } Entity *field = t->Record.fields[sel.index[0]]; - add_entity_use(c, kv->field, field); + add_entity_use(c, fv->field, field); if (fields_visited[sel.index[0]]) { error(ast_node_token(elem), @@ -3330,7 +3334,12 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint } fields_visited[sel.index[0]] = true; - check_expr(c, o, kv->value); + check_expr(c, o, fv->value); + + if (is_constant) { + is_constant = o->mode == Addressing_Constant; + } + check_assignment(c, o, field->type, make_string("structure literal")); } } else { @@ -3348,6 +3357,11 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error(ast_node_token(o->expr), "Too many values in structure literal, expected %td", field_count); break; } + + if (is_constant) { + is_constant = o->mode == Addressing_Constant; + } + check_assignment(c, o, field->type, make_string("structure literal")); } if (gb_array_count(cl->elems) < field_count) { @@ -3358,7 +3372,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint } break; - case Type_Slice: + // case Type_Slice: case Type_Array: case Type_Vector: { @@ -3401,6 +3415,10 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint Operand o = {}; check_expr_with_type_hint(c, &o, e, elem_type); check_assignment(c, &o, elem_type, context_name); + + if (is_constant) { + is_constant = o.mode == Addressing_Constant; + } } if (max < index) max = index; @@ -3419,13 +3437,18 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint default: { gbString str = type_to_string(type); - error(ast_node_token(node), "Invalid compound literal type `%s`", str); + error(ast_node_token(node), "Invalid or unyet supported compound literal type `%s`", str); gb_string_free(str); goto error; } break; } - o->mode = Addressing_Value; + if (is_constant) { + o->mode = Addressing_Constant; + o->value = make_exact_value_compound(node); + } else { + o->mode = Addressing_Value; + } o->type = type; case_end; diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index ca6771962..87aaab101 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -151,13 +151,12 @@ void ssa_gen_tree(ssaGen *s) { if (decl->init_expr != NULL) { TypeAndValue *tav = map_get(&info->types, hash_pointer(decl->init_expr)); - if (tav != NULL && tav->value.kind != ExactValue_Invalid) { - ExactValue v = tav->value; - if (v.kind == ExactValue_String) { - // NOTE(bill): The printer will fix the value correctly - // g->Global.value = ssa_add_global_string_array(m, v.value_string); - } else { - g->Global.value = ssa_make_value_constant(a, tav->type, v); + if (tav != NULL) { + if (tav->value.kind != ExactValue_Invalid) { + ExactValue v = tav->value; + if (v.kind != ExactValue_String) { + g->Global.value = ssa_add_module_constant(m, tav->type, v); + } } } } @@ -444,10 +443,10 @@ void ssa_gen_tree(ssaGen *s) { type_set_offsets(m->sizes, a, t); // NOTE(bill): Just incase the offsets have not been set yet for (isize i = 0; i < t->Record.field_count; i++) { - // NOTE(bill): Order fields in source order not layout order - Entity *f = t->Record.fields[i]; + // TODO(bill): Order fields in source order not layout order + Entity *f = t->Record.fields_in_src_order[i]; ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type); - i64 foffset = t->Record.struct_offsets[i]; + i64 foffset = t->Record.struct_offsets[f->Variable.field_index]; GB_ASSERT(f->kind == Entity_Variable && f->Variable.is_field); isize source_index = f->Variable.field_index; diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index 420bb112f..3957b0e36 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -263,6 +263,8 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) { } } +void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type_hint); + void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Type *type) { type = base_type(type); if (is_type_float(type)) { @@ -320,6 +322,122 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ ssa_fprintf(f, ")"); } break; + + case ExactValue_Compound: { + // ssa_fprintf(f, "%s", (value.value_bool ? "true" : "false")); + type = base_type(type); + if (is_type_array(type)) { + ssa_fprintf(f, "["); + Type *elem_type = type->Array.elem; + ast_node(cl, CompoundLit, value.value_compound); + + for (isize i = 0; i < type->Array.count; i++) { + if (i > 0) { + ssa_fprintf(f, ", "); + } + ssa_print_type(f, m, elem_type); + ssa_fprintf(f, " "); + + TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[i]); + GB_ASSERT(tav != NULL); + ssa_print_exact_value(f, m, tav->value, elem_type); + } + + ssa_fprintf(f, "]"); + } else if (is_type_struct(type)) { + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); + + ast_node(cl, CompoundLit, value.value_compound); + + if (cl->elems == NULL || gb_array_count(cl->elems) == 0) { + ssa_fprintf(f, "zeroinitializer"); + break; + } + + + isize value_count = type->Record.field_count; + ExactValue *values = gb_alloc_array(m->tmp_allocator, ExactValue, value_count); + + + if (cl->elems[0]->kind == AstNode_FieldValue) { + isize elem_count = gb_array_count(cl->elems); + for (isize i = 0; i < elem_count; i++) { + ast_node(fv, FieldValue, cl->elems[i]); + String name = fv->field->Ident.string; + + TypeAndValue *tav = type_and_value_of_expression(m->info, fv->value); + GB_ASSERT(tav != NULL); + + Selection sel = lookup_field(m->allocator, type, name, false); + Entity *f = type->Record.fields[sel.index[0]]; + + values[f->Variable.field_index] = tav->value; + } + } else { + for (isize i = 0; i < value_count; i++) { + TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[i]); + GB_ASSERT(tav != NULL); + + Entity *f = type->Record.fields_in_src_order[i]; + + values[f->Variable.field_index] = tav->value; + } + } + + + + if (type->Record.struct_is_packed) { + ssa_fprintf(f, "<"); + } + ssa_fprintf(f, "{"); + + + for (isize i = 0; i < value_count; i++) { + if (i > 0) { + ssa_fprintf(f, ", "); + } + Type *elem_type = type->Record.fields[i]->type; + + ssa_print_type(f, m, elem_type); + ssa_fprintf(f, " "); + + ExactValue v = values[i]; + if (v.kind == ExactValue_Invalid) { + ssa_fprintf(f, "zeroinitializer"); + } else if (v.kind == ExactValue_String) { + // HACK NOTE(bill): This is a hack but it works because strings are created at the very end + // of the .ll file + ssaValue *str_array = ssa_add_global_string_array(m, v.value_string); + + ssa_fprintf(f, "{i8* getelementptr inbounds ("); + ssa_print_type(f, m, str_array->Global.entity->type); + ssa_fprintf(f, ", "); + ssa_print_type(f, m, str_array->Global.entity->type); + ssa_fprintf(f, "* "); + ssa_print_encoded_global(f, str_array->Global.entity->token.string, false); + ssa_fprintf(f, ", "); + ssa_print_type(f, m, t_int); + ssa_fprintf(f, " 0, i32 0), "); + ssa_print_type(f, m, t_int); + ssa_fprintf(f, " %lld}", cast(i64)v.value_string.len); + + } else { + ssa_print_exact_value(f, m, v, elem_type); + } + } + + + ssa_fprintf(f, "}"); + if (type->Record.struct_is_packed) { + ssa_fprintf(f, ">"); + } + } else { + ssa_fprintf(f, "zeroinitializer"); + } + + } break; + default: GB_PANIC("Invalid ExactValue: %d", value.kind); break; diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index c56ff221f..7cc23e2ce 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -64,6 +64,7 @@ struct ssaModule { i32 global_string_index; gbArray(ssaValue *) procs; // NOTE(bill): Procedures to generate + gbArray(ssaValue *) const_compound_lits; }; @@ -290,6 +291,7 @@ enum ssaValueKind { ssaValue_Invalid, ssaValue_Constant, + ssaValue_ConstantArray, ssaValue_TypeName, ssaValue_Global, ssaValue_Param, @@ -310,9 +312,13 @@ struct ssaValue { Type * type; ExactValue value; } Constant; + struct { + Type *type; + gbArray(ssaValue *) values; + } ConstantArray; struct { String name; - Type * type; + Type * type; } TypeName; struct { b32 is_constant; @@ -409,6 +415,7 @@ void ssa_init_module(ssaModule *m, Checker *c) { map_init(&m->debug_info, gb_heap_allocator()); map_init(&m->type_names, gb_heap_allocator()); gb_array_init(m->procs, gb_heap_allocator()); + gb_array_init(m->const_compound_lits, gb_heap_allocator()); // Default states m->stmt_state_flags = 0; @@ -473,6 +480,7 @@ void ssa_destroy_module(ssaModule *m) { map_destroy(&m->type_names); map_destroy(&m->debug_info); gb_array_free(m->procs); + gb_array_free(m->const_compound_lits); gb_arena_free(&m->arena); } @@ -808,6 +816,16 @@ ssaValue *ssa_make_const_bool(gbAllocator a, b32 b) { return ssa_make_value_constant(a, t_bool, make_exact_value_bool(b != 0)); } +ssaValue *ssa_add_module_constant(ssaModule *m, Type *type, ExactValue value) { + ssaValue *v = ssa_make_value_constant(m->allocator, type, value); + + if (!is_type_constant_type(type)) { + gb_array_append(m->const_compound_lits, v); + } + + return v; +} + ssaValue *ssa_make_value_procedure(gbAllocator a, ssaModule *m, Entity *entity, Type *type, AstNode *type_expr, AstNode *body, String name) { ssaValue *v = ssa_alloc_value(a, ssaValue_Proc); @@ -1201,7 +1219,7 @@ ssaValue *ssa_emit_arith(ssaProcedure *proc, Token op, ssaValue *left, ssaValue case Token_AndNot: { // NOTE(bill): x &~ y == x & (~y) == x & (y ~ -1) // NOTE(bill): "not" `x` == `x` "xor" `-1` - ssaValue *neg = ssa_make_value_constant(proc->module->allocator, type, make_exact_value_integer(-1)); + ssaValue *neg = ssa_add_module_constant(proc->module, type, make_exact_value_integer(-1)); op.kind = Token_Xor; right = ssa_emit_arith(proc, op, right, neg, type); GB_ASSERT(right->Instr.kind == ssaInstr_BinaryOp); @@ -1270,7 +1288,7 @@ ssaValue *ssa_emit_struct_gep(ssaProcedure *proc, ssaValue *s, ssaValue *index, } ssaValue *ssa_emit_struct_gep(ssaProcedure *proc, ssaValue *s, i32 index, Type *result_type) { - ssaValue *i = ssa_make_value_constant(proc->module->allocator, t_i32, make_exact_value_integer(index)); + ssaValue *i = ssa_make_const_i32(proc->module->allocator, index); return ssa_emit_struct_gep(proc, s, i, result_type); } @@ -1540,7 +1558,7 @@ ssaValue *ssa_add_global_string_array(ssaModule *m, String string) { Type *type = make_type_array(a, t_u8, string.len); ExactValue ev = make_exact_value_string(string); Entity *entity = make_entity_constant(a, NULL, token, type, ev); - ssaValue *g = ssa_make_value_global(a, entity, ssa_make_value_constant(a, type, ev)); + ssaValue *g = ssa_make_value_global(a, entity, ssa_add_module_constant(m, type, ev)); g->Global.is_private = true; // g->Global.is_constant = true; @@ -1628,10 +1646,10 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg ev = exact_value_to_integer(ev); } else if (is_type_pointer(dst)) { // IMPORTANT NOTE(bill): LLVM doesn't support pointer constants expect `null` - ssaValue *i = ssa_make_value_constant(proc->module->allocator, t_uint, ev); + ssaValue *i = ssa_add_module_constant(proc->module, t_uint, ev); return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_inttoptr, i, t_uint, dst)); } - return ssa_make_value_constant(proc->module->allocator, t, ev); + return ssa_add_module_constant(proc->module, t, ev); } } @@ -2007,7 +2025,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue // NOTE(bill): "not" `x` == `x` "xor" `-1` ExactValue neg_one = make_exact_value_integer(-1); ssaValue *left = ssa_build_expr(proc, ue->expr); - ssaValue *right = ssa_make_value_constant(proc->module->allocator, tv->type, neg_one); + ssaValue *right = ssa_add_module_constant(proc->module, tv->type, neg_one); return ssa_emit_arith(proc, ue->op, left, right, tv->type); } break; } @@ -2105,9 +2123,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break; case Type_Vector: { - isize index = 0; + ssaValue *result = ssa_emit_load(proc, v); - for (; index < gb_array_count(cl->elems); index++) { + for (isize index = 0; index < gb_array_count(cl->elems); index++) { AstNode *elem = cl->elems[index]; ssaValue *field_elem = ssa_build_expr(proc, elem); Type *t = ssa_type(field_elem); @@ -2116,7 +2134,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *i = ssa_make_const_int(proc->module->allocator, index); result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i)); } - if (index == 1 && bt->Vector.count > 1) { + + if (gb_array_count(cl->elems) == 1 && bt->Vector.count > 1) { isize index_count = bt->Vector.count; i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count); for (isize i = 0; i < index_count; i++) { @@ -2677,7 +2696,7 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) { } } - return ssa_make_value_constant(proc->module->allocator, tv->type, tv->value); + return ssa_add_module_constant(proc->module, tv->type, tv->value); } ssaValue *value = NULL; diff --git a/src/common.cpp b/src/common.cpp index 9b38d4859..f5fe5b50c 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -26,6 +26,7 @@ String get_module_dir(gbAllocator a) { path.len--; } + return path; } @@ -211,7 +212,7 @@ gb_inline void map_destroy(Map *h) { template gb_internal isize map__add_entry(Map *h, HashKey key) { - MapEntry e = {0}; + MapEntry e = {}; e.key = key; e.next = -1; gb_array_append(h->entries, e); @@ -267,7 +268,7 @@ gb_inline void map_grow(Map *h) { template void map_rehash(Map *h, isize new_count) { isize i, j; - Map nh = {0}; + Map nh = {}; map_init(&nh, gb_array_allocator(h->hashes)); gb_array_resize(nh.hashes, new_count); gb_array_reserve(nh.entries, gb_array_count(h->entries)); diff --git a/src/exact_value.cpp b/src/exact_value.cpp index e120bff7a..1d4c47520 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -3,6 +3,8 @@ // TODO(bill): Big numbers // IMPORTANT TODO(bill): This needs to be completely fixed!!!!!!!! +struct AstNode; + enum ExactValueKind { ExactValue_Invalid, @@ -11,6 +13,7 @@ enum ExactValueKind { ExactValue_Integer, ExactValue_Float, ExactValue_Pointer, // TODO(bill): Handle ExactValue_Pointer correctly + ExactValue_Compound, ExactValue_Count, }; @@ -18,11 +21,12 @@ enum ExactValueKind { struct ExactValue { ExactValueKind kind; union { - b32 value_bool; - String value_string; - i64 value_integer; - f64 value_float; - void * value_pointer; + b32 value_bool; + String value_string; + i64 value_integer; + f64 value_float; + void * value_pointer; + AstNode *value_compound; }; }; @@ -30,6 +34,13 @@ HashKey hash_exact_value(ExactValue v) { return hashing_proc(&v, gb_size_of(ExactValue)); } + +ExactValue make_exact_value_compound(AstNode *node) { + ExactValue result = {ExactValue_Compound}; + result.value_compound = node; + return result; +} + ExactValue make_exact_value_bool(b32 b) { ExactValue result = {ExactValue_Bool}; result.value_bool = (b != 0); diff --git a/src/main.cpp b/src/main.cpp index cb4605e15..3e1398fb1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,4 @@ -// #define DISPLAY_TIMING +#define DISPLAY_TIMING #include "common.cpp" #include "unicode.cpp" @@ -106,13 +106,17 @@ ArchData make_arch_data(ArchKind kind) { return data; } + + int main(int argc, char **argv) { if (argc < 2) { gb_printf_err("using: %s [run] \n", argv[0]); return 1; } +#if 1 init_string_buffer_memory(); + init_global_error_collector(); String module_dir = get_module_dir(gb_heap_allocator()); // defer (gb_free(gb_heap_allocator(), module_dir.text)); @@ -163,11 +167,11 @@ int main(int argc, char **argv) { ssa_gen_tree(&ssa); PRINT_TIMER("SSA Tree"); - // TODO(bill): Speedup writing to file for IR code ssa_gen_ir(&ssa); PRINT_TIMER("SSA IR"); +#if 1 char const *output_name = ssa.output_file.filename; isize base_name_len = gb_path_extension(output_name)-1 - output_name; @@ -230,12 +234,13 @@ int main(int argc, char **argv) { } PRINT_TIMER("msvc-link"); -#endif PRINT_ACCUMULATION(); if (run_output) { win32_exec_command_line_app("%.*s.exe", cast(int)base_name_len, output_name); } - +#endif +#endif +#endif return 0; } diff --git a/src/parser.cpp b/src/parser.cpp index 5964b0dae..6824d9561 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -54,12 +54,12 @@ struct ImportedFile { struct Parser { String init_fullpath; - gbArray(AstFile) files; + gbArray(AstFile) files; gbArray(ImportedFile) imports; - gbArray(String) libraries; - gbArray(String) system_libraries; - isize load_index; + gbAtomic32 import_index; + gbArray(String) system_libraries; isize total_token_count; + gbMutex mutex; }; enum ProcTag : u64 { @@ -1586,6 +1586,44 @@ AstNode *parse_unary_expr(AstFile *f, b32 lhs) { return parse_atom_expr(f, lhs); } +// NOTE(bill): result == priority +i32 token_precedence(Token t) { + switch (t.kind) { + case Token_CmpOr: + return 1; + case Token_CmpAnd: + return 2; + case Token_CmpEq: + case Token_NotEq: + case Token_Lt: + case Token_Gt: + case Token_LtEq: + case Token_GtEq: + return 3; + case Token_Add: + case Token_Sub: + case Token_Or: + case Token_Xor: + return 4; + case Token_Mul: + case Token_Quo: + case Token_Mod: + case Token_And: + case Token_AndNot: + case Token_Shl: + case Token_Shr: + return 5; + case Token_DoublePrime: + return 6; + case Token_as: + case Token_transmute: + case Token_down_cast: + return 7; + } + + return 0; +} + AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) { AstNode *expression = parse_unary_expr(f, lhs); for (i32 prec = token_precedence(f->curr_token); prec >= prec_in; prec--) { @@ -2826,8 +2864,8 @@ void destroy_ast_file(AstFile *f) { b32 init_parser(Parser *p) { gb_array_init(p->files, gb_heap_allocator()); gb_array_init(p->imports, gb_heap_allocator()); - gb_array_init(p->libraries, gb_heap_allocator()); gb_array_init(p->system_libraries, gb_heap_allocator()); + gb_mutex_init(&p->mutex); return true; } @@ -2843,12 +2881,15 @@ void destroy_parser(Parser *p) { #endif gb_array_free(p->files); gb_array_free(p->imports); - gb_array_free(p->libraries); gb_array_free(p->system_libraries); + gb_mutex_destroy(&p->mutex); } // NOTE(bill): Returns true if it's added b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) { + gb_mutex_lock(&p->mutex); + defer (gb_mutex_unlock(&p->mutex)); + gb_for_array(i, p->imports) { String import = p->imports[i].path; if (import == path) { @@ -2900,6 +2941,9 @@ String get_fullpath_core(gbAllocator a, String path) { // NOTE(bill): Returns true if it's added b32 try_add_foreign_system_library_path(Parser *p, String import_file) { + gb_mutex_lock(&p->mutex); + defer (gb_mutex_unlock(&p->mutex)); + gb_for_array(i, p->system_libraries) { String import = p->system_libraries[i]; if (import == import_file) { @@ -2981,7 +3025,6 @@ void parse_file(Parser *p, AstFile *f) { base_dir.len--; } - gbAllocator allocator = gb_heap_allocator(); // TODO(bill): Change this allocator f->decls = parse_stmt_list(f); @@ -3008,6 +3051,8 @@ void parse_file(Parser *p, AstFile *f) { continue; } + gbAllocator allocator = gb_heap_allocator(); // TODO(bill): Change this allocator + String rel_path = get_fullpath_relative(allocator, base_dir, file_str); String import_file = rel_path; if (!gb_file_exists(cast(char *)rel_path.text)) { // NOTE(bill): This should be null terminated @@ -3038,6 +3083,7 @@ void parse_file(Parser *p, AstFile *f) { } + ParseFileError parse_files(Parser *p, char *init_filename) { char *fullpath_str = gb_path_get_full_name(gb_heap_allocator(), init_filename); String init_fullpath = make_string(fullpath_str); @@ -3053,9 +3099,10 @@ ParseFileError parse_files(Parser *p, char *init_filename) { } gb_for_array(i, p->imports) { - String import_path = p->imports[i].path; - String import_rel_path = p->imports[i].rel_path; - TokenPos pos = p->imports[i].pos; + ImportedFile imported_file = p->imports[i]; + String import_path = imported_file.path; + String import_rel_path = imported_file.rel_path; + TokenPos pos = imported_file.pos; AstFile file = {}; ParseFileError err = init_ast_file(&file, import_path); @@ -3088,9 +3135,18 @@ ParseFileError parse_files(Parser *p, char *init_filename) { return err; } parse_file(p, &file); - file.id = gb_array_count(p->files); - gb_array_append(p->files, file); - p->total_token_count += gb_array_count(file.tokens); + + { + gb_mutex_lock(&p->mutex); + defer (gb_mutex_unlock(&p->mutex)); + + file.id = gb_array_count(p->files); + gb_array_append(p->files, file); + } + } + + gb_for_array(i, p->files) { + p->total_token_count += gb_array_count(p->files[i].tokens); } diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 07220b9dc..c86a4b2f8 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -166,12 +166,20 @@ struct ErrorCollector { TokenPos prev; i64 count; i64 warning_count; + gbMutex mutex; }; gb_global ErrorCollector global_error_collector; +void init_global_error_collector(void) { + gb_mutex_init(&global_error_collector.mutex); +} + void warning(Token token, char *fmt, ...) { + gb_mutex_lock(&global_error_collector.mutex); + defer (gb_mutex_unlock(&global_error_collector.mutex)); + global_error_collector.warning_count++; // NOTE(bill): Duplicate error, skip it if (!token_pos_are_equal(global_error_collector.prev, token.pos)) { @@ -188,6 +196,9 @@ void warning(Token token, char *fmt, ...) { } void error(Token token, char *fmt, ...) { + gb_mutex_lock(&global_error_collector.mutex); + defer (gb_mutex_unlock(&global_error_collector.mutex)); + global_error_collector.count++; // NOTE(bill): Duplicate error, skip it if (!token_pos_are_equal(global_error_collector.prev, token.pos)) { @@ -204,6 +215,9 @@ void error(Token token, char *fmt, ...) { } void syntax_error(Token token, char *fmt, ...) { + gb_mutex_lock(&global_error_collector.mutex); + defer (gb_mutex_unlock(&global_error_collector.mutex)); + global_error_collector.count++; // NOTE(bill): Duplicate error, skip it if (!token_pos_are_equal(global_error_collector.prev, token.pos)) { @@ -232,43 +246,6 @@ void compiler_error(char *fmt, ...) { -// NOTE(bill): result == priority -i32 token_precedence(Token t) { - switch (t.kind) { - case Token_CmpOr: - return 1; - case Token_CmpAnd: - return 2; - case Token_CmpEq: - case Token_NotEq: - case Token_Lt: - case Token_Gt: - case Token_LtEq: - case Token_GtEq: - return 3; - case Token_Add: - case Token_Sub: - case Token_Or: - case Token_Xor: - return 4; - case Token_Mul: - case Token_Quo: - case Token_Mod: - case Token_And: - case Token_AndNot: - case Token_Shl: - case Token_Shr: - return 5; - case Token_DoublePrime: - return 6; - case Token_as: - case Token_transmute: - case Token_down_cast: - return 7; - } - - return 0; -} gb_inline b32 token_is_literal(Token t) {