diff --git a/core/_preload.odin b/core/_preload.odin index bcc9a5545..ece158fe9 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -84,9 +84,10 @@ Type_Info_Union :: struct { tag_type: ^Type_Info, }; Type_Info_Enum :: struct { - base: ^Type_Info, - names: []string, - values: []Type_Info_Enum_Value, + base: ^Type_Info, + names: []string, + values: []Type_Info_Enum_Value, + is_export: bool, }; Type_Info_Map :: struct { key: ^Type_Info, diff --git a/core/fmt.odin b/core/fmt.odin index 63c83dce7..201cdd36b 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -32,11 +32,12 @@ Fmt_Info :: struct { string_buffer_from_slice :: proc(backing: []byte) -> String_Buffer { s := transmute(raw.Slice)backing; - d: raw.Dynamic_Array; - d.data = s.data; - d.len = 0; - d.cap = s.len; - d.allocator = nil_allocator(); + d := raw.Dynamic_Array{ + data = s.data, + len = 0, + cap = s.len, + allocator = nil_allocator(), + }; return transmute(String_Buffer)d; } @@ -276,6 +277,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { case Type_Info_Enum: write_string(buf, "enum "); write_type(buf, info.base); + if info.is_export do write_string(buf, " #export"); write_string(buf, " {"); for name, i in info.names { if i > 0 do write_string(buf, ", "); @@ -394,9 +396,7 @@ fmt_bad_verb :: proc(using fi: ^Fmt_Info, verb: rune) { fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) { switch verb { case 't', 'v': - s := "false"; - if b do s = "true"; - write_string(buf, s); + write_string(buf, b ? "true" : "false"); case: fmt_bad_verb(fi, verb); } @@ -603,16 +603,14 @@ fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) { fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) { switch verb { case 'p', 'v': - // Okay + u := u64(uintptr(p)); + if !fi.hash || verb == 'v' { + write_string(fi.buf, "0x"); + } + _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER); case: fmt_bad_verb(fi, verb); - return; } - u := u64(uintptr(p)); - if !fi.hash || verb == 'v' { - write_string(fi.buf, "0x"); - } - _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER); } enum_value_to_string :: proc(v: any) -> (string, bool) { @@ -945,38 +943,35 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { return; } - base_arg := arg; base_arg.type_info = type_info_base(base_arg.type_info); switch a in base_arg { - case bool: fmt_bool(fi, bool(a), verb); - case b8: fmt_bool(fi, bool(a), verb); - case b16: fmt_bool(fi, bool(a), verb); - case b32: fmt_bool(fi, bool(a), verb); - case b64: fmt_bool(fi, bool(a), verb); + case bool: fmt_bool(fi, bool(a), verb); + case b8: fmt_bool(fi, bool(a), verb); + case b16: fmt_bool(fi, bool(a), verb); + case b32: fmt_bool(fi, bool(a), verb); + case b64: fmt_bool(fi, bool(a), verb); - case any: fmt_arg(fi, a, verb); - case rune: fmt_rune(fi, a, verb); + case any: fmt_arg(fi, a, verb); + case rune: fmt_rune(fi, a, verb); - case f32: fmt_float(fi, f64(a), 32, verb); - case f64: fmt_float(fi, a, 64, verb); + case f32: fmt_float(fi, f64(a), 32, verb); + case f64: fmt_float(fi, a, 64, verb); - case complex64: fmt_complex(fi, complex128(a), 64, verb); - case complex128: fmt_complex(fi, a, 128, verb); + case complex64: fmt_complex(fi, complex128(a), 64, verb); + case complex128: fmt_complex(fi, a, 128, verb); - case int: fmt_int(fi, u64(a), true, 8*size_of(int), verb); - case i8: fmt_int(fi, u64(a), true, 8, verb); + case i8: fmt_int(fi, u64(a), true, 8, verb); + case u8: fmt_int(fi, u64(a), false, 8, verb); case i16: fmt_int(fi, u64(a), true, 16, verb); - case i32: fmt_int(fi, u64(a), true, 32, verb); - case i64: fmt_int(fi, u64(a), true, 64, verb); - - case uintptr: fmt_int(fi, u64(a), false, 8*size_of(uintptr), verb); - - case uint: fmt_int(fi, u64(a), false, 8*size_of(uint), verb); - case u8: fmt_int(fi, u64(a), false, 8, verb); case u16: fmt_int(fi, u64(a), false, 16, verb); + case i32: fmt_int(fi, u64(a), true, 32, verb); case u32: fmt_int(fi, u64(a), false, 32, verb); + case i64: fmt_int(fi, u64(a), true, 64, verb); case u64: fmt_int(fi, u64(a), false, 64, verb); + case int: fmt_int(fi, u64(a), true, 8*size_of(int), verb); + case uint: fmt_int(fi, u64(a), false, 8*size_of(uint), verb); + case uintptr: fmt_int(fi, u64(a), false, 8*size_of(uintptr), verb); case string: fmt_string(fi, a, verb); diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 0c4ff6735..7ac2cd7ac 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -305,7 +305,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, return; } - // NOTE(bill): Check to see if the expression it to be aliases + // NOTE(bill): Check to see if the expression it to be aliases case Addressing_Builtin: if (e->type != nullptr) { error(type_expr, "A constant alias of a built-in procedure may not have a type initializer"); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 180fc430f..1014b8c46 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -94,7 +94,6 @@ bool check_has_break(AstNode *stmt, bool implicit) { // NOTE(bill): The last expression has to be a 'return' statement // TODO(bill): This is a mild hack and should be probably handled properly -// TODO(bill): Warn/err against code after 'return' that it won't be executed bool check_is_terminating(AstNode *node) { switch (node->kind) { case_ast_node(rs, ReturnStmt, node); @@ -344,22 +343,6 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) { return rhs->type; } -enum SwitchKind { - Switch_Invalid, - Switch_Union, - Switch_Any, -}; - -SwitchKind check_valid_type_switch_type(Type *type) { - type = type_deref(type); - if (is_type_union(type)) { - return Switch_Union; - } - if (is_type_any(type)) { - return Switch_Any; - } - return Switch_Invalid; -} void check_stmt_internal(Checker *c, AstNode *node, u32 flags); void check_stmt(Checker *c, AstNode *node, u32 flags) { @@ -771,12 +754,32 @@ void check_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { } } + +enum SwitchKind { + Switch_Invalid, + Switch_Union, + Switch_Any, +}; + +SwitchKind check_valid_type_switch_type(Type *type) { + type = type_deref(type); + if (is_type_union(type)) { + return Switch_Union; + } + if (is_type_any(type)) { + return Switch_Any; + } + return Switch_Invalid; +} + void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { ast_node(ss, TypeSwitchStmt, node); Operand x = {}; mod_flags |= Stmt_BreakAllowed; check_open_scope(c, node); + defer (check_close_scope(c)); + check_label(c, ss->label); // TODO(bill): What should the label's "scope" be? SwitchKind switch_kind = Switch_Invalid; @@ -802,7 +805,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { check_expr(c, &x, rhs); check_assignment(c, &x, nullptr, str_lit("type switch expression")); switch_kind = check_valid_type_switch_type(x.type); - if (check_valid_type_switch_type(x.type) == Switch_Invalid) { + if (switch_kind == Switch_Invalid) { gbString str = type_to_string(x.type); error(x.expr, "Invalid type for this type switch expression, got '%s'", str); gb_string_free(str); @@ -838,15 +841,14 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { } } - if (lhs->kind != AstNode_Ident) { error(rhs, "Expected an identifier, got '%.*s'", LIT(ast_node_strings[rhs->kind])); return; } - - Map seen = {}; // Multimap, Key: Type * + Map seen = {}; // Key: Type * map_init(&seen, heap_allocator()); + defer (map_destroy(&seen)); for_array(i, bs->stmts) { AstNode *stmt = bs->stmts[i]; @@ -933,9 +935,6 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { check_stmt_list(c, cc->stmts, mod_flags); check_close_scope(c); } - map_destroy(&seen); - - check_close_scope(c); } void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { @@ -989,51 +988,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { check_stmt(c, ts->stmt, flags); case_end; - #if 0 - case_ast_node(s, IncDecStmt, node); - TokenKind op = s->op.kind; - switch (op) { - case Token_Inc: op = Token_Add; break; - case Token_Dec: op = Token_Sub; break; - default: - error(node, "Invalid inc/dec operation"); - return; - } - - Operand x = {}; - check_expr(c, &x, s->expr); - if (x.mode == Addressing_Invalid) { - return; - } - if (!is_type_integer(x.type) && !is_type_float(x.type)) { - gbString e = expr_to_string(s->expr); - gbString t = type_to_string(x.type); - error(node, "%s%.*s used on non-numeric type %s", e, LIT(s->op.string), t); - gb_string_free(t); - gb_string_free(e); - return; - } - AstNode *left = s->expr; - AstNode *right = gb_alloc_item(c->allocator, AstNode); - right->kind = AstNode_BasicLit; - right->BasicLit.pos = s->op.pos; - right->BasicLit.kind = Token_Integer; - right->BasicLit.string = str_lit("1"); - - AstNode *be = gb_alloc_item(c->allocator, AstNode); - be->kind = AstNode_BinaryExpr; - be->BinaryExpr.op = s->op; - be->BinaryExpr.op.kind = op; - be->BinaryExpr.left = left; - be->BinaryExpr.right = right; - check_binary_expr(c, &x, be); - if (x.mode == Addressing_Invalid) { - return; - } - check_assignment_variable(c, &x, left); - case_end; - #endif - case_ast_node(as, AssignStmt, node); switch (as->op.kind) { case Token_Eq: { diff --git a/src/check_type.cpp b/src/check_type.cpp index 3252c8bf6..46399f7f1 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2008,6 +2008,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) return false; } *type = t; + set_base_type(named_type, *type); return true; case_end; @@ -2038,21 +2039,22 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_ast_node(pe, ParenExpr, e); *type = check_type(c, pe->expr, named_type); + set_base_type(named_type, *type); return true; case_end; case_ast_node(ue, UnaryExpr, e); - if (ue->op.kind == Token_Pointer) { + switch (ue->op.kind) { + case Token_Pointer: *type = make_type_pointer(c->allocator, check_type(c, ue->expr)); + set_base_type(named_type, *type); return true; - } /* else if (ue->op.kind == Token_Maybe) { - *type = make_type_maybe(c->allocator, check_type(c, ue->expr)); - return true; - } */ + } case_end; case_ast_node(pt, PointerType, e); *type = make_type_pointer(c->allocator, check_type(c, pt->type)); + set_base_type(named_type, *type); return true; case_end; @@ -2074,12 +2076,14 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) Type *elem = check_type(c, at->elem); *type = make_type_slice(c->allocator, elem); } + set_base_type(named_type, *type); return true; case_end; case_ast_node(dat, DynamicArrayType, e); Type *elem = check_type(c, dat->elem); *type = make_type_dynamic_array(c->allocator, elem); + set_base_type(named_type, *type); return true; case_end; @@ -2143,6 +2147,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) check_expr_or_type(c, &o, e); if (o.mode == Addressing_Type) { *type = o.type; + set_base_type(named_type, *type); return true; } case_end; @@ -2152,6 +2157,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) check_expr_or_type(c, &o, e); if (o.mode == Addressing_Type) { *type = o.type; + set_base_type(named_type, *type); return true; } case_end; diff --git a/src/checker.cpp b/src/checker.cpp index 2dec1a7c7..d0495e2d3 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -782,7 +782,7 @@ void add_untyped(CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode m if (mode == Addressing_Constant && type == t_invalid) { compiler_error("add_untyped - invalid type: %s", type_to_string(type)); } - map_set(&i->untyped, hash_node(expression), make_expr_info(lhs, mode, type, value)); + map_set(&i->untyped, hash_node(expression), make_expr_info(mode, type, value, lhs)); } void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value) { @@ -880,14 +880,14 @@ void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclIn GB_ASSERT(identifier->kind == AstNode_Ident); GB_ASSERT(e != nullptr && d != nullptr); GB_ASSERT(identifier->Ident.token.string == e->token.string); - if (e->scope != nullptr) add_entity(c, e->scope, identifier, e); + if (e->scope != nullptr) { + add_entity(c, e->scope, identifier, e); + } add_entity_definition(&c->info, identifier, e); GB_ASSERT(e->decl_info == nullptr); e->decl_info = d; array_add(&c->info.entities, e); e->order_in_src = c->info.entities.count; - // map_set(&c->info.entities, hash_entity(e), d); - // e->order_in_src = c->info.entities.entries.count; } diff --git a/src/checker.hpp b/src/checker.hpp index 8b610f4fe..0e453c91d 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -31,14 +31,18 @@ struct TypeAndValue { // ExprInfo stores information used for "untyped" expressions struct ExprInfo { - bool is_lhs; // Debug info AddressingMode mode; Type * type; // Type_Basic ExactValue value; + bool is_lhs; // Debug info }; -gb_inline ExprInfo make_expr_info(bool is_lhs, AddressingMode mode, Type *type, ExactValue value) { - ExprInfo ei = {is_lhs, mode, type, value}; +gb_inline ExprInfo make_expr_info(AddressingMode mode, Type *type, ExactValue value, bool is_lhs) { + ExprInfo ei = {}; + ei.is_lhs = is_lhs; + ei.mode = mode; + ei.type = type; + ei.value = value; return ei; } diff --git a/src/ir.cpp b/src/ir.cpp index eb9ba8979..c6093948c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1603,10 +1603,10 @@ void ir_emit_zero_init(irProcedure *p, irValue *address, AstNode *expr) { irValue **args = gb_alloc_array(a, irValue *, 2); args[0] = ir_emit_conv(p, address, t_rawptr); args[1] = ir_const_int(a, type_size_of(a, t)); - ir_emit(p, ir_instr_zero_init(p, address)); if (p->entity->token.string != "__mem_zero") { ir_emit_global_call(p, "__mem_zero", args, 2, expr); } + ir_emit(p, ir_instr_zero_init(p, address)); } irValue *ir_emit_comment(irProcedure *p, String text) { @@ -8033,6 +8033,9 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info irValue *base = ir_type_info(proc, t->Enum.base_type); ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), base); + // is_export + ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), ir_const_bool(a, t->Enum.is_export)); + if (t->Enum.field_count > 0) { Entity **fields = t->Enum.fields; isize count = t->Enum.field_count; @@ -8342,22 +8345,17 @@ void ir_gen_tree(irGen *s) { } } - if (decl->init_expr != nullptr) { - if (is_type_any(e->type)) { - } else { - TypeAndValue tav = type_and_value_of_expr(info, decl->init_expr); - if (tav.mode != Addressing_Invalid) { - if (tav.value.kind != ExactValue_Invalid) { - ExactValue v = tav.value; - g->Global.value = ir_add_module_constant(m, tav.type, v); - } + if (decl->init_expr != nullptr && !is_type_any(e->type)) { + TypeAndValue tav = type_and_value_of_expr(info, decl->init_expr); + if (tav.mode != Addressing_Invalid) { + if (tav.value.kind != ExactValue_Invalid) { + ExactValue v = tav.value; + g->Global.value = ir_add_module_constant(m, tav.type, v); } } } - // if (g->Global.value == nullptr) { - array_add(&global_variables, var); - // } + array_add(&global_variables, var); ir_module_add_value(m, e, g); map_set(&m->members, hash_string(name), g);