Browse Source

Merge branch 'master' of https://github.com/odin-lang/Odin

ThisDrunkDane 7 years ago
parent
commit
e225158a6f
10 changed files with 147 additions and 146 deletions
  1. 4 3
      core/_preload.odin
  2. 31 36
      core/fmt.odin
  3. 44 3
      examples/demo.odin
  4. 1 1
      src/build_settings.cpp
  5. 1 1
      src/check_decl.cpp
  6. 28 75
      src/check_stmt.cpp
  7. 11 5
      src/check_type.cpp
  8. 4 4
      src/checker.cpp
  9. 7 3
      src/checker.hpp
  10. 16 15
      src/ir.cpp

+ 4 - 3
core/_preload.odin

@@ -84,9 +84,10 @@ Type_Info_Union :: struct {
 	tag_type:   ^Type_Info,
 	tag_type:   ^Type_Info,
 };
 };
 Type_Info_Enum :: struct {
 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 {
 Type_Info_Map :: struct {
 	key:              ^Type_Info,
 	key:              ^Type_Info,

+ 31 - 36
core/fmt.odin

@@ -32,11 +32,12 @@ Fmt_Info :: struct {
 
 
 string_buffer_from_slice :: proc(backing: []byte) -> String_Buffer {
 string_buffer_from_slice :: proc(backing: []byte) -> String_Buffer {
 	s := transmute(raw.Slice)backing;
 	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;
 	return transmute(String_Buffer)d;
 }
 }
 
 
@@ -276,6 +277,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 	case Type_Info_Enum:
 	case Type_Info_Enum:
 		write_string(buf, "enum ");
 		write_string(buf, "enum ");
 		write_type(buf, info.base);
 		write_type(buf, info.base);
+		if info.is_export do write_string(buf, " #export");
 		write_string(buf, " {");
 		write_string(buf, " {");
 		for name, i in info.names {
 		for name, i in info.names {
 			if i > 0 do write_string(buf, ", ");
 			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) {
 fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) {
 	switch verb {
 	switch verb {
 	case 't', 'v':
 	case 't', 'v':
-		s := "false";
-		if b do s = "true";
-		write_string(buf, s);
+		write_string(buf, b ? "true" : "false");
 	case:
 	case:
 		fmt_bad_verb(fi, verb);
 		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) {
 fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
 	switch verb {
 	switch verb {
 	case 'p', 'v':
 	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:
 	case:
 		fmt_bad_verb(fi, verb);
 		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) {
 enum_value_to_string :: proc(v: any) -> (string, bool) {
@@ -945,38 +943,35 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
 		return;
 		return;
 	}
 	}
 
 
-
 	base_arg := arg;
 	base_arg := arg;
 	base_arg.type_info = type_info_base(base_arg.type_info);
 	base_arg.type_info = type_info_base(base_arg.type_info);
 	switch a in base_arg {
 	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 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 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 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 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);
 	case string:  fmt_string(fi, a, verb);
 
 

+ 44 - 3
examples/demo.odin

@@ -13,6 +13,7 @@ import "core:types.odin"
 import "core:utf16.odin"
 import "core:utf16.odin"
 import "core:utf8.odin"
 import "core:utf8.odin"
 
 
+// File scope `when` statements
 when ODIN_OS == "windows" {
 when ODIN_OS == "windows" {
 	import "core:atomics.odin"
 	import "core:atomics.odin"
 	import "core:thread.odin"
 	import "core:thread.odin"
@@ -643,6 +644,7 @@ array_programming :: proc() {
 using println in import "core:fmt.odin"
 using println in import "core:fmt.odin"
 
 
 using_in :: proc() {
 using_in :: proc() {
+	fmt.println("# using in");
 	using print in fmt;
 	using print in fmt;
 
 
 	println("Hellope1");
 	println("Hellope1");
@@ -660,7 +662,9 @@ using_in :: proc() {
 	println(f);
 	println(f);
 }
 }
 
 
-named_proc_parameters :: proc() {
+named_proc_return_parameters :: proc() {
+	fmt.println("# named proc return parameters");
+
 	foo0 :: proc() -> int {
 	foo0 :: proc() -> int {
 		return 123;
 		return 123;
 	}
 	}
@@ -681,6 +685,8 @@ named_proc_parameters :: proc() {
 
 
 
 
 enum_export :: proc() {
 enum_export :: proc() {
+	fmt.println("# enum #export");
+
 	Foo :: enum #export {A, B, C};
 	Foo :: enum #export {A, B, C};
 
 
 	f0 := A;
 	f0 := A;
@@ -689,8 +695,42 @@ enum_export :: proc() {
 	fmt.println(f0, f1, f2);
 	fmt.println(f0, f1, f2);
 }
 }
 
 
+explicit_procedure_overloading :: proc() {
+	fmt.println("# explicit procedure overloading");
+
+	add_ints :: proc(a, b: int) -> int {
+		x := a + b;
+		fmt.println("add_ints", x);
+		return x;
+	}
+	add_floats :: proc(a, b: f32) -> f32 {
+		x := a + b;
+		fmt.println("add_floats", x);
+		return x;
+	}
+	add_numbers :: proc(a: int, b: f32, c: u8) -> int {
+		x := int(a) + int(b) + int(c);
+		fmt.println("add_numbers", x);
+		return x;
+	}
+
+	add :: proc[add_ints, add_floats, add_numbers];
+
+	add(int(1), int(2));
+	add(f32(1), f32(2));
+	add(int(1), f32(2), u8(3));
+
+	add(1, 2);     // untyped ints coerce to int tighter than f32
+	add(1.0, 2.0); // untyped floats coerce to f32 tighter than int
+	add(1, 2, 3);  // three parameters
+
+	// Ambiguous answers
+	// add(1.0, 2);
+	// add(1, 2.0);
+}
+
 main :: proc() {
 main :: proc() {
-	when false {
+	when true {
 		general_stuff();
 		general_stuff();
 		default_struct_values();
 		default_struct_values();
 		union_type();
 		union_type();
@@ -698,7 +738,8 @@ main :: proc() {
 		threading_example();
 		threading_example();
 		array_programming();
 		array_programming();
 		using_in();
 		using_in();
-		named_proc_parameters();
+		named_proc_return_parameters();
 		enum_export();
 		enum_export();
+		explicit_procedure_overloading();
 	}
 	}
 }
 }

+ 1 - 1
src/build_settings.cpp

@@ -309,7 +309,7 @@ String get_fullpath_core(gbAllocator a, String path) {
 }
 }
 
 
 
 
-String const ODIN_VERSION = str_lit("0.8.0-dev");
+String const ODIN_VERSION = str_lit("0.8.1");
 String cross_compile_target = str_lit("");
 String cross_compile_target = str_lit("");
 String cross_compile_lib_dir = str_lit("");
 String cross_compile_lib_dir = str_lit("");
 
 

+ 1 - 1
src/check_decl.cpp

@@ -305,7 +305,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
 			return;
 			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:
 		case Addressing_Builtin:
 			if (e->type != nullptr) {
 			if (e->type != nullptr) {
 				error(type_expr, "A constant alias of a built-in procedure may not have a type initializer");
 				error(type_expr, "A constant alias of a built-in procedure may not have a type initializer");

+ 28 - 75
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
 // 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): 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) {
 bool check_is_terminating(AstNode *node) {
 	switch (node->kind) {
 	switch (node->kind) {
 	case_ast_node(rs, ReturnStmt, node);
 	case_ast_node(rs, ReturnStmt, node);
@@ -344,22 +343,6 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) {
 	return rhs->type;
 	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_internal(Checker *c, AstNode *node, u32 flags);
 void check_stmt(Checker *c, AstNode *node, u32 flags) {
 void check_stmt(Checker *c, AstNode *node, u32 flags) {
@@ -387,12 +370,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 }
 }
 
 
 
 
-
-struct TypeAndToken {
-	Type *type;
-	Token token;
-};
-
 void check_when_stmt(Checker *c, AstNodeWhenStmt *ws, u32 flags) {
 void check_when_stmt(Checker *c, AstNodeWhenStmt *ws, u32 flags) {
 	Operand operand = {Addressing_Invalid};
 	Operand operand = {Addressing_Invalid};
 	check_expr(c, &operand, ws->cond);
 	check_expr(c, &operand, ws->cond);
@@ -634,6 +611,11 @@ void check_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
 		}
 		}
 	}
 	}
 
 
+	struct TypeAndToken {
+		Type *type;
+		Token token;
+	};
+
 	Map<TypeAndToken> seen = {}; // NOTE(bill): Multimap
 	Map<TypeAndToken> seen = {}; // NOTE(bill): Multimap
 	map_init(&seen, heap_allocator());
 	map_init(&seen, heap_allocator());
 	defer (map_destroy(&seen));
 	defer (map_destroy(&seen));
@@ -772,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) {
 void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
 	ast_node(ss, TypeSwitchStmt, node);
 	ast_node(ss, TypeSwitchStmt, node);
 	Operand x = {};
 	Operand x = {};
 
 
 	mod_flags |= Stmt_BreakAllowed;
 	mod_flags |= Stmt_BreakAllowed;
 	check_open_scope(c, node);
 	check_open_scope(c, node);
+	defer (check_close_scope(c));
+
 	check_label(c, ss->label); // TODO(bill): What should the label's "scope" be?
 	check_label(c, ss->label); // TODO(bill): What should the label's "scope" be?
 
 
 	SwitchKind switch_kind = Switch_Invalid;
 	SwitchKind switch_kind = Switch_Invalid;
@@ -803,7 +805,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
 	check_expr(c, &x, rhs);
 	check_expr(c, &x, rhs);
 	check_assignment(c, &x, nullptr, str_lit("type switch expression"));
 	check_assignment(c, &x, nullptr, str_lit("type switch expression"));
 	switch_kind = check_valid_type_switch_type(x.type);
 	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);
 		gbString str = type_to_string(x.type);
 		error(x.expr, "Invalid type for this type switch expression, got '%s'", str);
 		error(x.expr, "Invalid type for this type switch expression, got '%s'", str);
 		gb_string_free(str);
 		gb_string_free(str);
@@ -839,15 +841,14 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
 		}
 		}
 	}
 	}
 
 
-
 	if (lhs->kind != AstNode_Ident) {
 	if (lhs->kind != AstNode_Ident) {
 		error(rhs, "Expected an identifier, got '%.*s'", LIT(ast_node_strings[rhs->kind]));
 		error(rhs, "Expected an identifier, got '%.*s'", LIT(ast_node_strings[rhs->kind]));
 		return;
 		return;
 	}
 	}
 
 
-
-	Map<bool> seen = {}; // Multimap, Key: Type *
+	Map<bool> seen = {}; // Key: Type *
 	map_init(&seen, heap_allocator());
 	map_init(&seen, heap_allocator());
+	defer (map_destroy(&seen));
 
 
 	for_array(i, bs->stmts) {
 	for_array(i, bs->stmts) {
 		AstNode *stmt = bs->stmts[i];
 		AstNode *stmt = bs->stmts[i];
@@ -934,9 +935,6 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
 		check_stmt_list(c, cc->stmts, mod_flags);
 		check_stmt_list(c, cc->stmts, mod_flags);
 		check_close_scope(c);
 		check_close_scope(c);
 	}
 	}
-	map_destroy(&seen);
-
-	check_close_scope(c);
 }
 }
 
 
 void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
@@ -990,51 +988,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		check_stmt(c, ts->stmt, flags);
 		check_stmt(c, ts->stmt, flags);
 	case_end;
 	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);
 	case_ast_node(as, AssignStmt, node);
 		switch (as->op.kind) {
 		switch (as->op.kind) {
 		case Token_Eq: {
 		case Token_Eq: {

+ 11 - 5
src/check_type.cpp

@@ -2008,6 +2008,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
 			return false;
 			return false;
 		}
 		}
 		*type = t;
 		*type = t;
+		set_base_type(named_type, *type);
 		return true;
 		return true;
 	case_end;
 	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);
 	case_ast_node(pe, ParenExpr, e);
 		*type = check_type(c, pe->expr, named_type);
 		*type = check_type(c, pe->expr, named_type);
+		set_base_type(named_type, *type);
 		return true;
 		return true;
 	case_end;
 	case_end;
 
 
 	case_ast_node(ue, UnaryExpr, e);
 	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));
 			*type = make_type_pointer(c->allocator, check_type(c, ue->expr));
+			set_base_type(named_type, *type);
 			return true;
 			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_end;
 
 
 	case_ast_node(pt, PointerType, e);
 	case_ast_node(pt, PointerType, e);
 		*type = make_type_pointer(c->allocator, check_type(c, pt->type));
 		*type = make_type_pointer(c->allocator, check_type(c, pt->type));
+		set_base_type(named_type, *type);
 		return true;
 		return true;
 	case_end;
 	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 *elem = check_type(c, at->elem);
 			*type = make_type_slice(c->allocator, elem);
 			*type = make_type_slice(c->allocator, elem);
 		}
 		}
+		set_base_type(named_type, *type);
 		return true;
 		return true;
 	case_end;
 	case_end;
 
 
 	case_ast_node(dat, DynamicArrayType, e);
 	case_ast_node(dat, DynamicArrayType, e);
 		Type *elem = check_type(c, dat->elem);
 		Type *elem = check_type(c, dat->elem);
 		*type = make_type_dynamic_array(c->allocator, elem);
 		*type = make_type_dynamic_array(c->allocator, elem);
+		set_base_type(named_type, *type);
 		return true;
 		return true;
 	case_end;
 	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);
 		check_expr_or_type(c, &o, e);
 		if (o.mode == Addressing_Type) {
 		if (o.mode == Addressing_Type) {
 			*type = o.type;
 			*type = o.type;
+			set_base_type(named_type, *type);
 			return true;
 			return true;
 		}
 		}
 	case_end;
 	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);
 		check_expr_or_type(c, &o, e);
 		if (o.mode == Addressing_Type) {
 		if (o.mode == Addressing_Type) {
 			*type = o.type;
 			*type = o.type;
+			set_base_type(named_type, *type);
 			return true;
 			return true;
 		}
 		}
 	case_end;
 	case_end;

+ 4 - 4
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) {
 	if (mode == Addressing_Constant && type == t_invalid) {
 		compiler_error("add_untyped - invalid type: %s", type_to_string(type));
 		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) {
 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(identifier->kind == AstNode_Ident);
 	GB_ASSERT(e != nullptr && d != nullptr);
 	GB_ASSERT(e != nullptr && d != nullptr);
 	GB_ASSERT(identifier->Ident.token.string == e->token.string);
 	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);
 	add_entity_definition(&c->info, identifier, e);
 	GB_ASSERT(e->decl_info == nullptr);
 	GB_ASSERT(e->decl_info == nullptr);
 	e->decl_info = d;
 	e->decl_info = d;
 	array_add(&c->info.entities, e);
 	array_add(&c->info.entities, e);
 	e->order_in_src = c->info.entities.count;
 	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;
 }
 }
 
 
 
 

+ 7 - 3
src/checker.hpp

@@ -31,14 +31,18 @@ struct TypeAndValue {
 
 
 // ExprInfo stores information used for "untyped" expressions
 // ExprInfo stores information used for "untyped" expressions
 struct ExprInfo {
 struct ExprInfo {
-	bool           is_lhs; // Debug info
 	AddressingMode mode;
 	AddressingMode mode;
 	Type *         type; // Type_Basic
 	Type *         type; // Type_Basic
 	ExactValue     value;
 	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;
 	return ei;
 }
 }
 
 

+ 16 - 15
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);
 	irValue **args = gb_alloc_array(a, irValue *, 2);
 	args[0] = ir_emit_conv(p, address, t_rawptr);
 	args[0] = ir_emit_conv(p, address, t_rawptr);
 	args[1] = ir_const_int(a, type_size_of(a, t));
 	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") {
 	if (p->entity->token.string != "__mem_zero") {
 		ir_emit_global_call(p, "__mem_zero", args, 2, expr);
 		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) {
 irValue *ir_emit_comment(irProcedure *p, String text) {
@@ -4272,7 +4272,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 			ir_emit_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, false);
 			ir_emit_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, false);
 
 
 			irValue *slice_size = len;
 			irValue *slice_size = len;
-			if (eal != 1) {
+			if (esz != 1) {
 				slice_size = ir_emit_arith(proc, Token_Mul, elem_size, len, t_int);
 				slice_size = ir_emit_arith(proc, Token_Mul, elem_size, len, t_int);
 			}
 			}
 
 
@@ -5578,7 +5578,10 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 	case_end;
 	case_end;
 
 
 	case_ast_node(be, BinaryExpr, expr);
 	case_ast_node(be, BinaryExpr, expr);
-		GB_PANIC("Invalid binary expression for ir_build_addr: %.*s\n", LIT(be->op.string));
+		irValue *v = ir_build_expr(proc, expr);
+		Type *t = ir_type(v);
+		GB_ASSERT(is_type_pointer(t));
+		return ir_addr(v);
 	case_end;
 	case_end;
 
 
 	case_ast_node(ie, IndexExpr, expr);
 	case_ast_node(ie, IndexExpr, expr);
@@ -8033,6 +8036,9 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 				irValue *base = ir_type_info(proc, t->Enum.base_type);
 				irValue *base = ir_type_info(proc, t->Enum.base_type);
 				ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), base);
 				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) {
 				if (t->Enum.field_count > 0) {
 					Entity **fields = t->Enum.fields;
 					Entity **fields = t->Enum.fields;
 					isize count = t->Enum.field_count;
 					isize count = t->Enum.field_count;
@@ -8342,22 +8348,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);
 			ir_module_add_value(m, e, g);
 			map_set(&m->members, hash_string(name), g);
 			map_set(&m->members, hash_string(name), g);