diff --git a/core/fmt.odin b/core/fmt.odin index c1191f500..36a0cc808 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -234,7 +234,6 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { case Type_Info_Array: write_string(buf, "["); - fi := Fmt_Info{buf = buf}; write_i64(buf, i64(info.count), 10); write_string(buf, "]"); write_type(buf, info.elem); @@ -313,8 +312,6 @@ _parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: boo } result := 0; - ok := true; - i := 0; for i < len(s[offset..]) { c := rune(s[offset+i]); @@ -855,11 +852,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { write_byte(fi.buf, '{'); defer write_byte(fi.buf, '}'); - hash := fi.hash; defer fi.hash = hash; - indent := fi.indent; defer fi.indent -= 1; - + fi.indent += 1; defer fi.indent -= 1; + hash := fi.hash; defer fi.hash = hash; fi.hash = false; - fi.indent += 1; + if hash do write_byte(fi.buf, '\n'); @@ -1016,7 +1012,7 @@ sbprintln :: proc(buf: ^String_Buffer, args: ...any) -> string { fi: Fmt_Info; fi.buf = buf; - for arg, i in args { + for _, i in args { if i > 0 do write_byte(buf, ' '); fmt_value(&fi, args[i], 'v'); diff --git a/core/os.odin b/core/os.odin index 5e552a246..5927d8012 100644 --- a/core/os.odin +++ b/core/os.odin @@ -49,7 +49,7 @@ write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (succ } defer close(fd); - bytes_written, write_err := write(fd, data); + _, write_err := write(fd, data); return write_err == 0; } diff --git a/core/types.odin b/core/types.odin index 338ae902e..fefcf00ae 100644 --- a/core/types.odin +++ b/core/types.odin @@ -49,6 +49,7 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { case Type_Info_Pointer: y, ok := b.variant.(Type_Info_Pointer); + if !ok do return false; return are_types_identical(x.elem, y.elem); case Type_Info_Procedure: diff --git a/core/utf16.odin b/core/utf16.odin index a375f416c..2a677ee06 100644 --- a/core/utf16.odin +++ b/core/utf16.odin @@ -30,25 +30,23 @@ encode_surrogate_pair :: proc(r: rune) -> (r1, r2: rune) { } encode :: proc(d: []u16, s: []rune) -> int { - n := len(s); - for r in s do if r >= _surr_self do n += 1; - - max_n := min(len(d), n); - n = 0; - - for r in s { + n, m := 0, len(d); + loop: for r in s { switch r { case 0.._surr1, _surr3 .. _surr_self: + if m+1 < n do break loop; d[n] = u16(r); n += 1; case _surr_self .. MAX_RUNE: + if m+2 < n do break loop; r1, r2 := encode_surrogate_pair(r); d[n] = u16(r1); d[n+1] = u16(r2); n += 2; case: + if m+1 < n do break loop; d[n] = u16(REPLACEMENT_CHAR); n += 1; } @@ -58,25 +56,23 @@ encode :: proc(d: []u16, s: []rune) -> int { encode_string :: proc(d: []u16, s: string) -> int { - n := utf8.rune_count_from_string(s); - for r in s do if r >= _surr_self do n += 1; - - max_n := min(len(d), n); - n = 0; - - for r in s { + n, m := 0, len(d); + loop: for r in s { switch r { case 0.._surr1, _surr3 .. _surr_self: + if m+1 < n do break loop; d[n] = u16(r); n += 1; case _surr_self .. MAX_RUNE: + if m+2 < n do break loop; r1, r2 := encode_surrogate_pair(r); d[n] = u16(r1); d[n+1] = u16(r2); n += 2; case: + if m+1 < n do break loop; d[n] = u16(REPLACEMENT_CHAR); n += 1; } diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 97acc20cd..351a8d0a0 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -265,7 +265,6 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, } // NOTE(bill): Check to see if the expression it to be aliases - #if 1 case Addressing_Builtin: if (e->type != nullptr) { error(type_expr, "A constant alias of a built-in procedure may not have a type initializer"); @@ -275,18 +274,16 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, e->type = t_invalid; return; - case Addressing_ProcGroup: { + case Addressing_ProcGroup: GB_ASSERT(operand.proc_group != nullptr); GB_ASSERT(operand.proc_group->kind == Entity_ProcGroup); e->kind = Entity_ProcGroup; e->type = t_invalid; - gb_memcopy(&e->ProcGroup, &operand.proc_group->ProcGroup, gb_size_of(e->ProcGroup)); + gb_memmove(&e->ProcGroup, &operand.proc_group->ProcGroup, gb_size_of(e->ProcGroup)); return; } - #endif - } - #if 1 + if (entity != nullptr) { switch (entity->kind) { case Entity_Alias: @@ -316,7 +313,6 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, return; } } - #endif } if (init != nullptr) { @@ -858,7 +854,6 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { case Entity_Procedure: check_proc_decl(c, e, d); break; - case Entity_ProcGroup: check_proc_group_decl(c, e, d); break; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index da830aab1..b153b65a3 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -267,6 +267,8 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ } + gb_mutex_lock(&c->mutex); + defer (gb_mutex_unlock(&c->mutex)); auto *found_gen_procs = map_get(&c->info.gen_procs, hash_pointer(base_entity->identifier)); if (found_gen_procs) { @@ -553,7 +555,6 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) { } } -#if defined(ALLOW_ARRAY_PROGRAMMING) if (is_type_array(dst)) { Type *elem = base_array_type(dst); i64 distance = check_distance_between_types(c, operand, elem); @@ -561,7 +562,6 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) { return distance + 6; } } -#endif if (is_type_any(dst)) { if (!is_type_polymorphic(src)) { @@ -2235,7 +2235,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) { } break; -#if defined(ALLOW_ARRAY_PROGRAMMING) case Type_Array: { Type *elem = base_array_type(t); if (check_is_assignable_to(c, operand, elem)) { @@ -2248,7 +2247,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) { break; } -#endif case Type_Union: if (!is_operand_nil(*operand) && !is_operand_undef(*operand)) { diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 17d50fb6d..140e5a5ea 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1682,6 +1682,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count); isize entity_count = 0; + isize new_name_count = 0; for_array(i, vd->names) { AstNode *name = vd->names[i]; Entity *entity = nullptr; @@ -1694,6 +1695,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { // NOTE(bill): Ignore assignments to '_' if (!is_blank_ident(str)) { found = current_scope_lookup_entity(c->context.scope, str); + new_name_count += 1; } if (found == nullptr) { entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false); @@ -1721,6 +1723,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { entities[entity_count++] = entity; } + if (new_name_count == 0) { + error(node, "No new declarations on the lhs"); + } + Type *init_type = nullptr; if (vd->type != nullptr) { init_type = check_type(c, vd->type, nullptr); diff --git a/src/check_type.cpp b/src/check_type.cpp index d1552a965..8600f1a55 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -34,198 +34,6 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map } - -void check_struct_field_decl(Checker *c, AstNode *decl, Array *fields, Map *entity_map, AstNode *struct_node, String context, bool allow_default_values) { - GB_ASSERT(fields != nullptr); - if (decl->kind == AstNode_WhenStmt) { - ast_node(ws, WhenStmt, decl); - Operand operand = {Addressing_Invalid}; - check_expr(c, &operand, ws->cond); - if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) { - error(ws->cond, "Non-constant boolean 'when' condition"); - return; - } - if (ws->body == nullptr || ws->body->kind != AstNode_BlockStmt) { - error(ws->cond, "Invalid body for 'when' statement"); - return; - } - if (operand.value.kind == ExactValue_Bool && - operand.value.value_bool) { - for_array(i, ws->body->BlockStmt.stmts) { - AstNode *stmt = ws->body->BlockStmt.stmts[i]; - check_struct_field_decl(c, stmt, fields, entity_map, struct_node, context, allow_default_values); - } - } else if (ws->else_stmt) { - switch (ws->else_stmt->kind) { - case AstNode_BlockStmt: - for_array(i, ws->else_stmt->BlockStmt.stmts) { - AstNode *stmt = ws->else_stmt->BlockStmt.stmts[i]; - check_struct_field_decl(c, stmt, fields, entity_map, struct_node, context, allow_default_values); - } - break; - case AstNode_WhenStmt: - check_struct_field_decl(c, ws->else_stmt, fields, entity_map, struct_node, context, allow_default_values); - break; - default: - error(ws->else_stmt, "Invalid 'else' statement in 'when' statement"); - break; - } - } - } - - if (decl->kind != AstNode_ValueDecl) { - return; - } - - - ast_node(vd, ValueDecl, decl); - - if (!vd->is_mutable) return; - - bool is_using = vd->is_using; - - if (is_using && vd->names.count > 1) { - error(vd->names[0], "Cannot apply 'using' to more than one of the same type"); - is_using = false; - } - - bool arity_ok = check_arity_match(c, vd); - - if (vd->values.count > 0 && !allow_default_values) { - error(vd->values[0], "Default values are not allowed within a %.*s", LIT(context)); - } - - - Type *type = nullptr; - if (vd->type != nullptr) { - type = check_type(c, vd->type); - } else if (!allow_default_values) { - error(vd->names[0], "Expected a type for this field"); - type = t_invalid; - } - - if (type != nullptr) { - if (is_type_empty_union(type)) { - error(vd->names[0], "An empty union cannot be used as a field type in %.*s", LIT(context)); - type = t_invalid; - } - if (!c->context.allow_polymorphic_types && is_type_polymorphic(base_type(type))) { - error(vd->names[0], "Invalid use of a polymorphic type in %.*s", LIT(context)); - type = t_invalid; - } - } - - Array default_values = {}; - defer (array_free(&default_values)); - if (vd->values.count > 0 && allow_default_values) { - array_init(&default_values, heap_allocator(), 2*vd->values.count); - - Type *type_hint = nullptr; - if (type != t_invalid && type != nullptr) { - type_hint = type; - } - - for_array(i, vd->values) { - AstNode *v = vd->values[i]; - Operand o = {}; - - check_expr_base(c, &o, v, type_hint); - check_not_tuple(c, &o); - - if (o.mode == Addressing_NoValue) { - error_operand_no_value(&o); - } else { - if (o.mode == Addressing_Value && o.type->kind == Type_Tuple) { - // NOTE(bill): Tuples are not first class thus never named - for_array(index, o.type->Tuple.variables) { - Operand single = {Addressing_Value}; - single.type = o.type->Tuple.variables[index]->type; - single.expr = v; - array_add(&default_values, single); - } - } else { - array_add(&default_values, o); - } - } - } - } - - - isize name_field_index = 0; - for_array(name_index, vd->names) { - AstNode *name = vd->names[name_index]; - if (!ast_node_expect(name, AstNode_Ident)) { - return; - } - - Token name_token = name->Ident.token; - - Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, is_using, cast(i32)fields->count); - e->identifier = name; - - if (name_field_index < default_values.count) { - Operand a = default_values[name_field_index]; - Operand b = default_values[name_field_index]; - check_init_variable(c, e, &b, str_lit("struct field assignment")); - if (is_operand_nil(a)) { - e->Variable.default_is_nil = true; - } else if (is_operand_undef(a)) { - e->Variable.default_is_undef = true; - } else if (b.mode != Addressing_Constant) { - error(b.expr, "Default field value must be a constant"); - } else if (is_type_any(e->type) || is_type_union(e->type)) { - gbString str = type_to_string(e->type); - error(b.expr, "A struct field of type '%s' cannot have a default value", str); - gb_string_free(str); - } else { - e->Variable.default_value = b.value; - } - - name_field_index++; - } - - GB_ASSERT(e->type != nullptr); - GB_ASSERT(is_type_typed(e->type)); - - if (is_blank_ident(name_token)) { - array_add(fields, e); - } else { - HashKey key = hash_string(name_token.string); - Entity **found = map_get(entity_map, key); - if (found != nullptr) { - Entity *e = *found; - // NOTE(bill): Scope checking already checks the declaration but in many cases, this can happen so why not? - // This may be a little janky but it's not really that much of a problem - error(name_token, "'%.*s' is already declared in this type", LIT(name_token.string)); - error(e->token, "\tpreviously declared"); - } else { - map_set(entity_map, key, e); - array_add(fields, e); - add_entity(c, c->context.scope, name, e); - } - add_entity_use(c, name, e); - } - - } - - - if (is_using && fields->count > 0) { - Type *first_type = (*fields)[fields->count-1]->type; - Type *t = base_type(type_deref(first_type)); - if (!is_type_struct(t) && !is_type_raw_union(t) && !is_type_bit_field(t) && - vd->names.count >= 1 && - vd->names[0]->kind == AstNode_Ident) { - Token name_token = vd->names[0]->Ident.token; - gbString type_str = type_to_string(first_type); - error(name_token, "'using' cannot be applied to the field '%.*s' of type '%s'", LIT(name_token.string), type_str); - gb_string_free(type_str); - return; - } - - populate_using_entity_map(c, struct_node, type, entity_map); - } -} - // Returns filled field_count Array check_struct_fields(Checker *c, AstNode *node, Array params, isize init_field_capacity, Type *named_type, String context) { @@ -301,6 +109,10 @@ Array check_struct_fields(Checker *c, AstNode *node, Array type = default_type(o.type); } else { + if (type_expr->kind == AstNode_Ident && type_expr->Ident.token.string == "Element") { + gb_printf_err("Element\n"); + } + type = check_type(c, type_expr); if (default_value != nullptr) { @@ -398,11 +210,6 @@ Array check_struct_fields(Checker *c, AstNode *node, Array } } - // for_array(decl_index, params) { - // check_struct_field_decl(c, params[decl_index], &fields, &entity_map, node, context, context == "struct"); - // } - - return fields; } @@ -488,8 +295,10 @@ bool check_custom_align(Checker *c, AstNode *node, i64 *align_) { Entity *find_polymorphic_struct_entity(Checker *c, Type *original_type, isize param_count, Array ordered_operands) { - auto *found_gen_types = map_get(&c->info.gen_types, hash_pointer(original_type)); + gb_mutex_lock(&c->mutex); + defer (gb_mutex_unlock(&c->mutex)); + auto *found_gen_types = map_get(&c->info.gen_types, hash_pointer(original_type)); if (found_gen_types != nullptr) { for_array(i, *found_gen_types) { Entity *e = (*found_gen_types)[i]; @@ -761,12 +570,15 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, ArrayStruct.is_raw_union) { type_set_offsets(c->allocator, struct_type); if (!struct_type->failure && !st->is_packed && !st->is_ordered) { struct_type->failure = false; struct_type->Struct.are_offsets_set = false; + struct_type->Struct.are_offsets_being_processed = false; gb_zero_item(&struct_type->Struct.offsets); // NOTE(bill): Reorder fields for reduced size/performance @@ -791,7 +603,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Arrayallocator, struct_type); } - +#endif if (st->align != nullptr) { if (st->is_packed) { @@ -2195,9 +2007,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(pt, PointerType, e); - Type *elem = check_type(c, pt->type); - i64 esz = type_size_of(c->allocator, elem); - *type = make_type_pointer(c->allocator, elem); + *type = make_type_pointer(c->allocator, check_type(c, pt->type)); return true; case_end; diff --git a/src/checker.cpp b/src/checker.cpp index 16bc32ca1..b352ab780 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -464,6 +464,7 @@ struct CheckerInfo { struct Checker { Parser * parser; CheckerInfo info; + gbMutex mutex; AstFile * curr_ast_file; Scope * global_scope; @@ -792,8 +793,40 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) { } +GB_COMPARE_PROC(entity_variable_pos_cmp) { + Entity *x = *cast(Entity **)a; + Entity *y = *cast(Entity **)b; + + return token_pos_cmp(x->token.pos, y->token.pos); +} + void check_scope_usage(Checker *c, Scope *scope) { // TODO(bill): Use this? + Array unused = {}; + array_init(&unused, heap_allocator()); + defer (array_free(&unused)); + + for_array(i, scope->elements.entries) { + Entity *e = scope->elements.entries[i].value; + if (e != nullptr && e->kind == Entity_Variable && (e->flags&EntityFlag_Used) == 0) { + array_add(&unused, e); + } + } + + gb_sort_array(unused.data, unused.count, entity_variable_pos_cmp); + + for_array(i, unused) { + Entity *e = unused[i]; + error(e->token, "'%.*s' declared but not used", LIT(e->token.string)); + } + + for (Scope *child = scope->first_child; + child != nullptr; + child = child->next) { + if (!child->is_proc && !child->is_struct && !child->is_file) { + check_scope_usage(c, child); + } + } } @@ -941,6 +974,7 @@ void init_checker(Checker *c, Parser *parser) { c->parser = parser; init_checker_info(&c->info); + gb_mutex_init(&c->mutex); array_init(&c->proc_stack, a); map_init(&c->procs, a); @@ -973,6 +1007,8 @@ void init_checker(Checker *c, Parser *parser) { void destroy_checker(Checker *c) { destroy_checker_info(&c->info); + gb_mutex_destroy(&c->mutex); + destroy_scope(c->global_scope); array_free(&c->proc_stack); map_destroy(&c->procs); @@ -3282,7 +3318,6 @@ void check_parsed_files(Checker *c) { bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0; bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0; - if (bounds_check) { c->context.stmt_state_flags |= StmtStateFlag_bounds_check; c->context.stmt_state_flags &= ~StmtStateFlag_no_bounds_check; diff --git a/src/entity.cpp b/src/entity.cpp index 3f81a066d..fcc06f01e 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -189,6 +189,7 @@ Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, T entity->using_parent = parent; entity->parent_proc_decl = parent->parent_proc_decl; entity->flags |= EntityFlag_Using; + entity->flags |= EntityFlag_Used; return entity; } diff --git a/src/ir.cpp b/src/ir.cpp index c05fb0bf3..25e21ad2e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -2093,7 +2093,6 @@ irValue *ir_emit_unary_arith(irProcedure *proc, TokenKind op, irValue *x, Type * break; } -#if defined(ALLOW_ARRAY_PROGRAMMING) if (is_type_array(ir_type(x))) { ir_emit_comment(proc, str_lit("array.arith.begin")); // IMPORTANT TODO(bill): This is very wasteful with regards to stack memory @@ -2112,7 +2111,6 @@ irValue *ir_emit_unary_arith(irProcedure *proc, TokenKind op, irValue *x, Type * return ir_emit_load(proc, res); } -#endif return ir_emit(proc, ir_instr_unary_op(proc, op, x, type)); } @@ -2123,7 +2121,6 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue * Type *t_left = ir_type(left); Type *t_right = ir_type(right); -#if defined(ALLOW_ARRAY_PROGRAMMING) if (is_type_array(t_left) || is_type_array(t_right)) { ir_emit_comment(proc, str_lit("array.arith.begin")); // IMPORTANT TODO(bill): This is very wasteful with regards to stack memory @@ -2145,7 +2142,6 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue * ir_emit_comment(proc, str_lit("array.arith.end")); return ir_emit_load(proc, res); } -#endif if (is_type_complex(t_left)) { ir_emit_comment(proc, str_lit("complex.arith.begin")); @@ -2404,7 +2400,6 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal } Type *result = t_bool; -#if defined(ALLOW_ARRAY_PROGRAMMING) if (is_type_array(a)) { ir_emit_comment(proc, str_lit("array.comp.begin")); defer (ir_emit_comment(proc, str_lit("array.comp.end"))); @@ -2432,8 +2427,6 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal return ir_emit_conv(proc, res, result); } -#endif - if (is_type_string(a)) { char *runtime_proc = nullptr; switch (op_kind) { @@ -3188,7 +3181,6 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { return ir_emit_load(proc, slice); } -#if defined(ALLOW_ARRAY_PROGRAMMING) if (is_type_array(dst)) { Type *elem = dst->Array.elem; irValue *e = ir_emit_conv(proc, value, elem); @@ -3201,7 +3193,6 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { } return ir_emit_load(proc, v); } -#endif if (is_type_any(dst)) { irValue *result = ir_add_local_generated(proc, t_any); @@ -4672,7 +4663,6 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { #endif if (tv.value.kind != ExactValue_Invalid) { -#if defined(ALLOW_ARRAY_PROGRAMMING) // NOTE(bill): Edge case if (tv.value.kind != ExactValue_Compound && is_type_array(tv.type)) { @@ -4681,7 +4671,6 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { irValue *x = ir_add_module_constant(proc->module, elem, value); return ir_emit_conv(proc, x, tv.type); } -#endif return ir_add_module_constant(proc->module, tv.type, tv.value); } diff --git a/src/main.cpp b/src/main.cpp index 5df246e7f..2a1ee6017 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,5 @@ -#define ALLOW_ARRAY_PROGRAMMING // #define NO_ARRAY_BOUNDS_CHECK - #include "common.cpp" #include "timings.cpp" #include "build_settings.cpp" @@ -248,6 +246,7 @@ bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_CrossLibDir, str_lit("cross-lib-dir"), BuildFlagParam_String); + GB_ASSERT(args.count >= 3); Array flag_args = args; flag_args.data += 3; flag_args.count -= 3; @@ -296,29 +295,13 @@ bool parse_build_flags(Array args) { switch (bf.param_kind) { default: ok = false; break; case BuildFlagParam_Boolean: { - if (param == "t") { + if (str_eq_ignore_case(param, str_lit("t")) || + str_eq_ignore_case(param, str_lit("true")) || + param == "1") { value = exact_value_bool(true); - } else if (param == "T") { - value = exact_value_bool(true); - } else if (param == "true") { - value = exact_value_bool(true); - } else if (param == "TRUE") { - value = exact_value_bool(true); - } else if (param == "True") { - value = exact_value_bool(true); - } else if (param == "1") { - value = exact_value_bool(true); - } else if (param == "f") { - value = exact_value_bool(false); - } else if (param == "F") { - value = exact_value_bool(false); - } else if (param == "false") { - value = exact_value_bool(false); - } else if (param == "FALSE") { - value = exact_value_bool(false); - } else if (param == "False") { - value = exact_value_bool(false); - } else if (param == "0") { + } else if (str_eq_ignore_case(param, str_lit("f")) || + str_eq_ignore_case(param, str_lit("false")) || + param == "0") { value = exact_value_bool(false); } else { gb_printf_err("Invalid flag parameter for '%.*s' = '%.*s'\n", LIT(name), LIT(param)); diff --git a/src/map.cpp b/src/map.cpp index 152b8cb39..0ff39cac6 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -127,14 +127,12 @@ template void multi_map_remove_all(Map *h, HashKey key); template gb_inline void map_init(Map *h, gbAllocator a, isize capacity) { array_init(&h->hashes, a, capacity); - array_init(&h->entries, a, capacity); -} + array_init(&h->entries, a, capacity);} template gb_inline void map_destroy(Map *h) { array_free(&h->entries); - array_free(&h->hashes); -} + array_free(&h->hashes);} template gb_internal isize map__add_entry(Map *h, HashKey key) { @@ -237,8 +235,9 @@ template void map_set(Map *h, HashKey key, T const &value) { isize index; MapFindResult fr; - if (h->hashes.count == 0) + if (h->hashes.count == 0) { map_grow(h); + } fr = map__find(h, key); if (fr.entry_index >= 0) { index = fr.entry_index; diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index ac055f41d..d16002b3e 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -30,14 +30,12 @@ template void ptr_set_rehash (PtrSet *s, isize new_cou template void ptr_set_init(PtrSet *s, gbAllocator a, isize capacity) { array_init(&s->hashes, a, capacity); - array_init(&s->entries, a, capacity); -} + array_init(&s->entries, a, capacity);} template void ptr_set_destroy(PtrSet *s) { array_free(&s->hashes); - array_free(&s->entries); -} + array_free(&s->entries);} template gb_internal isize ptr_set__add_entry(PtrSet *s, T ptr) { diff --git a/src/types.cpp b/src/types.cpp index 64822dd88..cbf55ac4b 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -659,11 +659,9 @@ bool is_type_numeric(Type *t) { return (t->Basic.flags & BasicFlag_Numeric) != 0; } // TODO(bill): Should this be here? -#if defined(ALLOW_ARRAY_PROGRAMMING) if (t->kind == Type_Array) { return is_type_numeric(t->Array.elem); } -#endif return false; } bool is_type_string(Type *t) { @@ -1973,8 +1971,9 @@ Array type_set_offsets_of(gbAllocator allocator, Array fields, bo } } else { for_array(i, fields) { - i64 align = gb_max(type_align_of(allocator, fields[i]->type), 1); - i64 size = gb_max(type_size_of(allocator, fields[i]->type), 0); + Type *t = fields[i]->type; + i64 align = gb_max(type_align_of(allocator, t), 1); + i64 size = gb_max(type_size_of(allocator, t), 0); curr_offset = align_formula(curr_offset, align); offsets[i] = curr_offset; curr_offset += size; @@ -1989,6 +1988,7 @@ bool type_set_offsets(gbAllocator allocator, Type *t) { if (!t->Struct.are_offsets_set) { t->Struct.are_offsets_being_processed = true; t->Struct.offsets = type_set_offsets_of(allocator, t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union); + t->Struct.are_offsets_being_processed = false; t->Struct.are_offsets_set = true; return true; } @@ -1996,6 +1996,7 @@ bool type_set_offsets(gbAllocator allocator, Type *t) { if (!t->Tuple.are_offsets_set) { t->Struct.are_offsets_being_processed = true; t->Tuple.offsets = type_set_offsets_of(allocator, t->Tuple.variables, false, false); + t->Struct.are_offsets_being_processed = false; t->Tuple.are_offsets_set = true; return true; } @@ -2037,6 +2038,9 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { } } break; + case Type_Pointer: + return build_context.word_size; + case Type_Array: { i64 count, align, size, alignment; count = t->Array.count; @@ -2105,9 +2109,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { t->Union.tag_size = tag_size; t->Union.variant_block_size = size - field_size; - size += tag_size; - size = align_formula(size, align); - return size; + return align_formula(size + tag_size, align); } break; @@ -2128,11 +2130,13 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { // TODO(bill): Is this how it should work? return align_formula(max, align); } else { - i64 count = t->Struct.fields.count; + i64 count = 0, size = 0, align = 0; + + count = t->Struct.fields.count; if (count == 0) { return 0; } - i64 align = type_align_of_internal(allocator, t, path); + align = type_align_of_internal(allocator, t, path); if (path->failure) { return FAILURE_SIZE; } @@ -2141,7 +2145,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { return FAILURE_SIZE; } type_set_offsets(allocator, t); - i64 size = t->Struct.offsets[count-1] + type_size_of_internal(allocator, t->Struct.fields[count-1]->type, path); + size = t->Struct.offsets[count-1] + type_size_of_internal(allocator, t->Struct.fields[count-1]->type, path); return align_formula(size, align); } } break;