Browse Source

Move TypeAndValue to Ast from Map

gingerBill 7 years ago
parent
commit
4d9d38cc28
7 changed files with 135 additions and 136 deletions
  1. 1 1
      src/check_expr.cpp
  2. 2 2
      src/check_stmt.cpp
  3. 18 22
      src/checker.cpp
  4. 8 27
      src/checker.hpp
  5. 48 48
      src/ir.cpp
  6. 3 3
      src/ir_print.cpp
  7. 55 33
      src/parser.hpp

+ 1 - 1
src/check_expr.cpp

@@ -1386,7 +1386,7 @@ bool check_is_not_addressable(CheckerContext *c, Operand *o) {
 			return true;
 			return true;
 		}
 		}
 		ast_node(ta, TypeAssertion, expr);
 		ast_node(ta, TypeAssertion, expr);
-		TypeAndValue tv = type_and_value_of_expr(&c->checker->info, ta->expr);
+		TypeAndValue tv = ta->expr->tav;
 		if (is_type_pointer(tv.type)) {
 		if (is_type_pointer(tv.type)) {
 			return false;
 			return false;
 		}
 		}

+ 2 - 2
src/check_stmt.cpp

@@ -292,7 +292,7 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs)
 		Ast *ln = unparen_expr(lhs->expr);
 		Ast *ln = unparen_expr(lhs->expr);
 		if (ln->kind == Ast_IndexExpr) {
 		if (ln->kind == Ast_IndexExpr) {
 			Ast *x = ln->IndexExpr.expr;
 			Ast *x = ln->IndexExpr.expr;
-			TypeAndValue tav = type_and_value_of_expr(&ctx->checker->info, x);
+			TypeAndValue tav = x->tav;
 			GB_ASSERT(tav.mode != Addressing_Invalid);
 			GB_ASSERT(tav.mode != Addressing_Invalid);
 			if (tav.mode != Addressing_Variable) {
 			if (tav.mode != Addressing_Variable) {
 				if (!is_type_pointer(tav.type)) {
 				if (!is_type_pointer(tav.type)) {
@@ -1072,7 +1072,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
 			}
 			}
 			if (operand.expr->kind == Ast_CallExpr) {
 			if (operand.expr->kind == Ast_CallExpr) {
 				AstCallExpr *ce = &operand.expr->CallExpr;
 				AstCallExpr *ce = &operand.expr->CallExpr;
-				Type *t = type_of_expr(&ctx->checker->info, ce->proc);
+				Type *t = type_of_expr(ce->proc);
 				if (is_type_proc(t)) {
 				if (is_type_proc(t)) {
 					if (t->Proc.require_results) {
 					if (t->Proc.require_results) {
 						gbString expr_str = expr_to_string(ce->proc);
 						gbString expr_str = expr_to_string(ce->proc);

+ 18 - 22
src/checker.cpp

@@ -582,7 +582,6 @@ void init_universal_scope(void) {
 
 
 void init_checker_info(CheckerInfo *i) {
 void init_checker_info(CheckerInfo *i) {
 	gbAllocator a = heap_allocator();
 	gbAllocator a = heap_allocator();
-	map_init(&i->types,           a);
 	array_init(&i->definitions,   a);
 	array_init(&i->definitions,   a);
 	array_init(&i->entities,      a);
 	array_init(&i->entities,      a);
 	map_init(&i->untyped,         a);
 	map_init(&i->untyped,         a);
@@ -597,7 +596,6 @@ void init_checker_info(CheckerInfo *i) {
 }
 }
 
 
 void destroy_checker_info(CheckerInfo *i) {
 void destroy_checker_info(CheckerInfo *i) {
-	map_destroy(&i->types);
 	array_free(&i->definitions);
 	array_free(&i->definitions);
 	array_free(&i->entities);
 	array_free(&i->entities);
 	map_destroy(&i->untyped);
 	map_destroy(&i->untyped);
@@ -669,15 +667,17 @@ Entity *entity_of_ident(Ast *identifier) {
 	return nullptr;
 	return nullptr;
 }
 }
 
 
-TypeAndValue type_and_value_of_expr(CheckerInfo *i, Ast *expr) {
-	TypeAndValue result = {};
-	TypeAndValue *found = map_get(&i->types, hash_node(expr));
-	if (found) result = *found;
-	return result;
+
+TypeAndValue type_and_value_of_expr(Ast *expr) {
+	TypeAndValue tav = {};
+	if (expr != nullptr) {
+		tav = expr->tav;
+	}
+	return tav;
 }
 }
 
 
-Type *type_of_expr(CheckerInfo *i, Ast *expr) {
-	TypeAndValue tav = type_and_value_of_expr(i, expr);
+Type *type_of_expr(Ast *expr) {
+	TypeAndValue tav = expr->tav;
 	if (tav.mode != Addressing_Invalid) {
 	if (tav.mode != Addressing_Invalid) {
 		return tav.type;
 		return tav.type;
 	}
 	}
@@ -691,11 +691,7 @@ Type *type_of_expr(CheckerInfo *i, Ast *expr) {
 	return nullptr;
 	return nullptr;
 }
 }
 
 
-Entity *implicit_entity_of_node(CheckerInfo *i, Ast *clause) {
-	// Entity **found = map_get(&i->implicits, hash_node(clause));
-	// if (found != nullptr) {
-		// return *found;
-	// }
+Entity *implicit_entity_of_node(Ast *clause) {
 	if (clause->kind == Ast_CaseClause) {
 	if (clause->kind == Ast_CaseClause) {
 		return clause->CaseClause.implicit_entity;
 		return clause->CaseClause.implicit_entity;
 	}
 	}
@@ -807,8 +803,8 @@ void add_untyped(CheckerInfo *i, Ast *expression, bool lhs, AddressingMode mode,
 	map_set(&i->untyped, hash_node(expression), make_expr_info(mode, type, value, lhs));
 	map_set(&i->untyped, hash_node(expression), make_expr_info(mode, type, value, lhs));
 }
 }
 
 
-void add_type_and_value(CheckerInfo *i, Ast *expression, AddressingMode mode, Type *type, ExactValue value) {
-	if (expression == nullptr) {
+void add_type_and_value(CheckerInfo *i, Ast *expr, AddressingMode mode, Type *type, ExactValue value) {
+	if (expr == nullptr) {
 		return;
 		return;
 	}
 	}
 	if (mode == Addressing_Invalid) {
 	if (mode == Addressing_Invalid) {
@@ -818,11 +814,9 @@ void add_type_and_value(CheckerInfo *i, Ast *expression, AddressingMode mode, Ty
 		return;
 		return;
 	}
 	}
 
 
-	TypeAndValue tv = {};
-	tv.type  = type;
-	tv.value = value;
-	tv.mode  = mode;
-	map_set(&i->types, hash_node(expression), tv);
+	expr->tav.mode = mode;
+	expr->tav.type = type;
+	expr->tav.value = value;
 }
 }
 
 
 void add_entity_definition(CheckerInfo *i, Ast *identifier, Entity *entity) {
 void add_entity_definition(CheckerInfo *i, Ast *identifier, Entity *entity) {
@@ -1246,7 +1240,9 @@ void add_min_dep_type_info(Checker *c, Type *t) {
 
 
 
 
 void add_dependency_to_set(Checker *c, Entity *entity) {
 void add_dependency_to_set(Checker *c, Entity *entity) {
-	GB_ASSERT(entity != nullptr);
+	if (entity == nullptr) {
+		return;
+	}
 
 
 	CheckerInfo *info = &c->info;
 	CheckerInfo *info = &c->info;
 	auto *set = &info->minimum_dependency_set;
 	auto *set = &info->minimum_dependency_set;

+ 8 - 27
src/checker.hpp

@@ -9,28 +9,8 @@ struct Checker;
 struct CheckerInfo;
 struct CheckerInfo;
 struct CheckerContext;
 struct CheckerContext;
 
 
-enum AddressingMode {
-	Addressing_Invalid,       // invalid addressing mode
-	Addressing_NoValue,       // no value (void in C)
-	Addressing_Value,         // computed value (rvalue)
-	Addressing_Immutable,     // immutable computed value (const rvalue)
-	Addressing_Variable,      // addressable variable (lvalue)
-	Addressing_Constant,      // constant
-	Addressing_Type,          // type
-	Addressing_Builtin,       // built-in procedure
-	Addressing_ProcGroup,     // procedure group (overloaded procedure)
-	Addressing_MapIndex,      // map index expression -
-	                          // 	lhs: acts like a Variable
-	                          // 	rhs: acts like OptionalOk
-	Addressing_OptionalOk,    // rhs: acts like a value with an optional boolean part (for existence check)
-};
-
-struct TypeAndValue {
-	AddressingMode mode;
-	Type *         type;
-	ExactValue     value;
-};
-
+enum AddressingMode;
+struct TypeAndValue;
 
 
 // ExprInfo stores information used for "untyped" expressions
 // ExprInfo stores information used for "untyped" expressions
 struct ExprInfo {
 struct ExprInfo {
@@ -301,8 +281,9 @@ typedef Array<Type *>   CheckerPolyPath;
 
 
 // CheckerInfo stores all the symbol information for a type-checked program
 // CheckerInfo stores all the symbol information for a type-checked program
 struct CheckerInfo {
 struct CheckerInfo {
-	Map<TypeAndValue>     types;           // Key: Ast * | Expression -> Type (and value)
-	Map<ExprInfo>         untyped;         // Key: Ast * | Expression -> ExprInfo
+	Map<ExprInfo>         untyped; // Key: Ast * | Expression -> ExprInfo
+	                               // NOTE(bill): This needs to be a map and not on the Ast
+	                               // as it needs to be iterated across
 	Map<AstFile *>        files;           // Key: String (full path)
 	Map<AstFile *>        files;           // Key: String (full path)
 	Map<AstPackage *>     packages;        // Key: String (full path)
 	Map<AstPackage *>     packages;        // Key: String (full path)
 	Map<Entity *>         foreigns;        // Key: String
 	Map<Entity *>         foreigns;        // Key: String
@@ -377,10 +358,10 @@ HashKey hash_decl_info(DeclInfo *decl) { return hash_pointer(decl); }
 
 
 
 
 // CheckerInfo API
 // CheckerInfo API
-TypeAndValue type_and_value_of_expr (CheckerInfo *i, Ast *expr);
-Type *       type_of_expr           (CheckerInfo *i, Ast *expr);
+TypeAndValue type_and_value_of_expr (Ast *expr);
+Type *       type_of_expr           (Ast *expr);
 Entity *     entity_of_ident        (Ast *identifier);
 Entity *     entity_of_ident        (Ast *identifier);
-Entity *     implicit_entity_of_node(CheckerInfo *i, Ast *clause);
+Entity *     implicit_entity_of_node(Ast *clause);
 Scope *      scope_of_node          (Ast *node);
 Scope *      scope_of_node          (Ast *node);
 DeclInfo *   decl_info_of_ident     (Ast *ident);
 DeclInfo *   decl_info_of_ident     (Ast *ident);
 DeclInfo *   decl_info_of_entity    (Entity * e);
 DeclInfo *   decl_info_of_entity    (Entity * e);

+ 48 - 48
src/ir.cpp

@@ -3671,7 +3671,7 @@ irValue *ir_emit_logical_binary_expr(irProcedure *proc, Ast *expr) {
 	irBlock *rhs  = ir_new_block(proc, nullptr, "logical.cmp.rhs");
 	irBlock *rhs  = ir_new_block(proc, nullptr, "logical.cmp.rhs");
 	irBlock *done = ir_new_block(proc, nullptr, "logical.cmp.done");
 	irBlock *done = ir_new_block(proc, nullptr, "logical.cmp.done");
 
 
-	Type *type = type_of_expr(proc->module->info, expr);
+	Type *type = type_of_expr(expr);
 	type = default_type(type);
 	type = default_type(type);
 
 
 	return ir_emit_logical_binary_expr(proc, be->op.kind, be->left, be->right, type);
 	return ir_emit_logical_binary_expr(proc, be->op.kind, be->left, be->right, type);
@@ -3935,7 +3935,7 @@ irValue *ir_gen_anonymous_proc_lit(irModule *m, String prefix_name, Ast *expr, i
 	name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$anon-%d", LIT(prefix_name), name_id);
 	name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$anon-%d", LIT(prefix_name), name_id);
 	String name = make_string(name_text, name_len-1);
 	String name = make_string(name_text, name_len-1);
 
 
-	Type *type = type_of_expr(m->info, expr);
+	Type *type = type_of_expr(expr);
 	irValue *value = ir_value_procedure(m->allocator,
 	irValue *value = ir_value_procedure(m->allocator,
 	                                    m, nullptr, type, pl->type, pl->body, name);
 	                                    m, nullptr, type, pl->type, pl->body, name);
 
 
@@ -4201,9 +4201,9 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 
 
 	case BuiltinProc_type_info_of: {
 	case BuiltinProc_type_info_of: {
 		Ast *arg = ce->args[0];
 		Ast *arg = ce->args[0];
-		TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg);
+		TypeAndValue tav = type_and_value_of_expr(arg);
 		if (tav.mode == Addressing_Type) {
 		if (tav.mode == Addressing_Type) {
-			Type *t = default_type(type_of_expr(proc->module->info, arg));
+			Type *t = default_type(type_of_expr(arg));
 			return ir_type_info(proc, t);
 			return ir_type_info(proc, t);
 		}
 		}
 		GB_ASSERT(is_type_typeid(tav.type));
 		GB_ASSERT(is_type_typeid(tav.type));
@@ -4215,9 +4215,9 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 
 
 	case BuiltinProc_typeid_of: {
 	case BuiltinProc_typeid_of: {
 		Ast *arg = ce->args[0];
 		Ast *arg = ce->args[0];
-		TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg);
+		TypeAndValue tav = type_and_value_of_expr(arg);
 		if (tav.mode == Addressing_Type) {
 		if (tav.mode == Addressing_Type) {
-			Type *t = default_type(type_of_expr(proc->module->info, arg));
+			Type *t = default_type(type_of_expr(arg));
 			return ir_typeid(proc->module, t);
 			return ir_typeid(proc->module, t);
 		}
 		}
 		Type *t = base_type(tav.type);
 		Type *t = base_type(tav.type);
@@ -4285,7 +4285,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 		// proc new(Type) -> ^Type
 		// proc new(Type) -> ^Type
 		gbAllocator a = proc->module->allocator;
 		gbAllocator a = proc->module->allocator;
 
 
-		Type *type = type_of_expr(proc->module->info, ce->args[0]);
+		Type *type = type_of_expr(ce->args[0]);
 		Type *allocation_type = type;
 		Type *allocation_type = type;
 		i32 variant_index = 0;
 		i32 variant_index = 0;
 		if (is_type_struct(type)) {
 		if (is_type_struct(type)) {
@@ -4321,7 +4321,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 	case BuiltinProc_make: {
 	case BuiltinProc_make: {
 		ir_emit_comment(proc, str_lit("make"));
 		ir_emit_comment(proc, str_lit("make"));
 		gbAllocator a = proc->module->allocator;
 		gbAllocator a = proc->module->allocator;
-		Type *type = type_of_expr(proc->module->info, ce->args[0]);
+		Type *type = type_of_expr(ce->args[0]);
 
 
 		String proc_name = {};
 		String proc_name = {};
 		if (proc->entity != nullptr) {
 		if (proc->entity != nullptr) {
@@ -4414,7 +4414,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 		gbAllocator a = proc->module->allocator;
 		gbAllocator a = proc->module->allocator;
 
 
 		Ast *node = ce->args[0];
 		Ast *node = ce->args[0];
-		TypeAndValue tav = type_and_value_of_expr(proc->module->info, node);
+		TypeAndValue tav = type_and_value_of_expr(node);
 		Type *type = base_type(tav.type);
 		Type *type = base_type(tav.type);
 
 
 		if (is_type_dynamic_array(type)) {
 		if (is_type_dynamic_array(type)) {
@@ -4523,7 +4523,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 	#if 0
 	#if 0
 	case BuiltinProc_clear: {
 	case BuiltinProc_clear: {
 		ir_emit_comment(proc, str_lit("clear"));
 		ir_emit_comment(proc, str_lit("clear"));
-		Type *original_type = type_of_expr(proc->module->info, ce->args[0]);
+		Type *original_type = type_of_expr(ce->args[0]);
 		irAddr const &addr = ir_build_addr(proc, ce->args[0]);
 		irAddr const &addr = ir_build_addr(proc, ce->args[0]);
 		irValue *ptr = addr.addr;
 		irValue *ptr = addr.addr;
 		if (is_double_pointer(ir_type(ptr))) {
 		if (is_double_pointer(ir_type(ptr))) {
@@ -4553,7 +4553,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 		ir_emit_comment(proc, str_lit("append"));
 		ir_emit_comment(proc, str_lit("append"));
 		gbAllocator a = proc->module->allocator;
 		gbAllocator a = proc->module->allocator;
 
 
-		Type *value_type = type_of_expr(proc->module->info, ce->args[0]);
+		Type *value_type = type_of_expr(ce->args[0]);
 		irAddr array_addr = ir_build_addr(proc, ce->args[0]);
 		irAddr array_addr = ir_build_addr(proc, ce->args[0]);
 		irValue *array_ptr = array_addr.addr;
 		irValue *array_ptr = array_addr.addr;
 		if (is_double_pointer(ir_type(array_ptr))) {
 		if (is_double_pointer(ir_type(array_ptr))) {
@@ -4587,7 +4587,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 		isize arg_count = 0;
 		isize arg_count = 0;
 		for_array(i, ce->args) {
 		for_array(i, ce->args) {
 			Ast *a = ce->args[i];
 			Ast *a = ce->args[i];
-			Type *at = base_type(type_of_expr(proc->module->info, a));
+			Type *at = base_type(type_of_expr(a));
 			if (at->kind == Type_Tuple) {
 			if (at->kind == Type_Tuple) {
 				arg_count += at->Tuple.variable_count;
 				arg_count += at->Tuple.variable_count;
 			} else {
 			} else {
@@ -4690,7 +4690,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 		irValue *dst = ir_add_local_generated(proc, tv.type);
 		irValue *dst = ir_add_local_generated(proc, tv.type);
 
 
 		for (i32 i = 1; i < ce->args.count; i++) {
 		for (i32 i = 1; i < ce->args.count; i++) {
-			TypeAndValue tv = type_and_value_of_expr(proc->module->info, ce->args[i]);
+			TypeAndValue tv = type_and_value_of_expr(ce->args[i]);
 			GB_ASSERT(is_type_integer(tv.type));
 			GB_ASSERT(is_type_integer(tv.type));
 			GB_ASSERT(tv.value.kind == ExactValue_Integer);
 			GB_ASSERT(tv.value.kind == ExactValue_Integer);
 
 
@@ -4775,13 +4775,13 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 
 
 	case BuiltinProc_min: {
 	case BuiltinProc_min: {
 		ir_emit_comment(proc, str_lit("min"));
 		ir_emit_comment(proc, str_lit("min"));
-		Type *t = type_of_expr(proc->module->info, expr);
+		Type *t = type_of_expr(expr);
 		return ir_emit_min(proc, t, ir_build_expr(proc, ce->args[0]), ir_build_expr(proc, ce->args[1]));
 		return ir_emit_min(proc, t, ir_build_expr(proc, ce->args[0]), ir_build_expr(proc, ce->args[1]));
 	}
 	}
 
 
 	case BuiltinProc_max: {
 	case BuiltinProc_max: {
 		ir_emit_comment(proc, str_lit("max"));
 		ir_emit_comment(proc, str_lit("max"));
-		Type *t = type_of_expr(proc->module->info, expr);
+		Type *t = type_of_expr(expr);
 		return ir_emit_max(proc, t, ir_build_expr(proc, ce->args[0]), ir_build_expr(proc, ce->args[1]));
 		return ir_emit_max(proc, t, ir_build_expr(proc, ce->args[0]), ir_build_expr(proc, ce->args[1]));
 	}
 	}
 
 
@@ -4817,7 +4817,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 
 
 	case BuiltinProc_clamp: {
 	case BuiltinProc_clamp: {
 		ir_emit_comment(proc, str_lit("clamp"));
 		ir_emit_comment(proc, str_lit("clamp"));
-		Type *t = type_of_expr(proc->module->info, expr);
+		Type *t = type_of_expr(expr);
 		return ir_emit_clamp(proc, t,
 		return ir_emit_clamp(proc, t,
 		                     ir_build_expr(proc, ce->args[0]),
 		                     ir_build_expr(proc, ce->args[0]),
 		                     ir_build_expr(proc, ce->args[1]),
 		                     ir_build_expr(proc, ce->args[1]),
@@ -4840,7 +4840,7 @@ irValue *ir_build_expr(irProcedure *proc, Ast *expr) {
 irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 	expr = unparen_expr(expr);
 	expr = unparen_expr(expr);
 
 
-	TypeAndValue tv = type_and_value_of_expr(proc->module->info, expr);
+	TypeAndValue tv = type_and_value_of_expr(expr);
 	GB_ASSERT(tv.mode != Addressing_Invalid);
 	GB_ASSERT(tv.mode != Addressing_Invalid);
 	GB_ASSERT(tv.mode != Addressing_Type);
 	GB_ASSERT(tv.mode != Addressing_Type);
 
 
@@ -4936,7 +4936,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 	case_end;
 	case_end;
 
 
 	case_ast_node(se, SelectorExpr, expr);
 	case_ast_node(se, SelectorExpr, expr);
-		TypeAndValue tav = type_and_value_of_expr(proc->module->info, expr);
+		TypeAndValue tav = type_and_value_of_expr(expr);
 		GB_ASSERT(tav.mode != Addressing_Invalid);
 		GB_ASSERT(tav.mode != Addressing_Invalid);
 		return ir_addr_load(proc, ir_build_addr(proc, expr));
 		return ir_addr_load(proc, ir_build_addr(proc, expr));
 	case_end;
 	case_end;
@@ -4954,7 +4954,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 		irValue *cond = ir_build_cond(proc, te->cond, then, else_);
 		irValue *cond = ir_build_cond(proc, te->cond, then, else_);
 		ir_start_block(proc, then);
 		ir_start_block(proc, then);
 
 
-		Type *type = type_of_expr(proc->module->info, expr);
+		Type *type = type_of_expr(expr);
 
 
 		ir_open_scope(proc);
 		ir_open_scope(proc);
 		array_add(&edges, ir_emit_conv(proc, ir_build_expr(proc, te->x), type));
 		array_add(&edges, ir_emit_conv(proc, ir_build_expr(proc, te->x), type));
@@ -5016,7 +5016,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 
 
 				ast_node(ta, TypeAssertion, ue_expr);
 				ast_node(ta, TypeAssertion, ue_expr);
 				TokenPos pos = ast_token(expr).pos;
 				TokenPos pos = ast_token(expr).pos;
-				Type *type = type_of_expr(proc->module->info, ue_expr);
+				Type *type = type_of_expr(ue_expr);
 				GB_ASSERT(!is_type_tuple(type));
 				GB_ASSERT(!is_type_tuple(type));
 
 
 				irValue *e = ir_build_expr(proc, ta->expr);
 				irValue *e = ir_build_expr(proc, ta->expr);
@@ -5138,7 +5138,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 
 
 
 
 	case_ast_node(ce, CallExpr, expr);
 	case_ast_node(ce, CallExpr, expr);
-		TypeAndValue proc_tv = type_and_value_of_expr(proc->module->info, ce->proc);
+		TypeAndValue proc_tv = type_and_value_of_expr(ce->proc);
 		AddressingMode proc_mode = proc_tv.mode;
 		AddressingMode proc_mode = proc_tv.mode;
 		if (proc_mode == Addressing_Type) {
 		if (proc_mode == Addressing_Type) {
 			GB_ASSERT(ce->args.count == 1);
 			GB_ASSERT(ce->args.count == 1);
@@ -5176,7 +5176,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 				String name = fv->field->Ident.token.string;
 				String name = fv->field->Ident.token.string;
 				isize index = lookup_procedure_parameter(pt, name);
 				isize index = lookup_procedure_parameter(pt, name);
 				GB_ASSERT(index >= 0);
 				GB_ASSERT(index >= 0);
-				TypeAndValue tav = type_and_value_of_expr(proc->module->info, fv->value);
+				TypeAndValue tav = type_and_value_of_expr(fv->value);
 				if (tav.mode == Addressing_Type) {
 				if (tav.mode == Addressing_Type) {
 					args[index] = ir_value_nil(proc->module->allocator, tav.type);
 					args[index] = ir_value_nil(proc->module->allocator, tav.type);
 				} else {
 				} else {
@@ -5211,7 +5211,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 		isize arg_count = 0;
 		isize arg_count = 0;
 		for_array(i, ce->args) {
 		for_array(i, ce->args) {
 			Ast *arg = ce->args[i];
 			Ast *arg = ce->args[i];
-			TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg);
+			TypeAndValue tav = type_and_value_of_expr(arg);
 			GB_ASSERT_MSG(tav.mode != Addressing_Invalid, "%s", expr_to_string(arg));
 			GB_ASSERT_MSG(tav.mode != Addressing_Invalid, "%s", expr_to_string(arg));
 			GB_ASSERT_MSG(tav.mode != Addressing_ProcGroup, "%s", expr_to_string(arg));
 			GB_ASSERT_MSG(tav.mode != Addressing_ProcGroup, "%s", expr_to_string(arg));
 			Type *at = tav.type;
 			Type *at = tav.type;
@@ -5248,7 +5248,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 
 
 		for_array(i, ce->args) {
 		for_array(i, ce->args) {
 			Ast *arg = ce->args[i];
 			Ast *arg = ce->args[i];
-			TypeAndValue arg_tv = type_and_value_of_expr(proc->module->info, arg);
+			TypeAndValue arg_tv = type_and_value_of_expr(arg);
 			if (arg_tv.mode == Addressing_Type) {
 			if (arg_tv.mode == Addressing_Type) {
 				args[arg_index++] = ir_value_nil(proc->module->allocator, arg_tv.type);
 				args[arg_index++] = ir_value_nil(proc->module->allocator, arg_tv.type);
 			} else {
 			} else {
@@ -5424,7 +5424,7 @@ bool ir_is_elem_const(irModule *m, Ast *elem, Type *elem_type) {
 	if (elem->kind == Ast_FieldValue) {
 	if (elem->kind == Ast_FieldValue) {
 		elem = elem->FieldValue.value;
 		elem = elem->FieldValue.value;
 	}
 	}
-	TypeAndValue tav = type_and_value_of_expr(m->info, elem);
+	TypeAndValue tav = type_and_value_of_expr(elem);
 	GB_ASSERT_MSG(tav.mode != Addressing_Invalid, "%s %s", expr_to_string(elem), type_to_string(tav.type));
 	GB_ASSERT_MSG(tav.mode != Addressing_Invalid, "%s %s", expr_to_string(elem), type_to_string(tav.type));
 	return tav.value.kind != ExactValue_Invalid;
 	return tav.value.kind != ExactValue_Invalid;
 }
 }
@@ -5486,7 +5486,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 		Ast *sel = unparen_expr(se->selector);
 		Ast *sel = unparen_expr(se->selector);
 		if (sel->kind == Ast_Ident) {
 		if (sel->kind == Ast_Ident) {
 			String selector = sel->Ident.token.string;
 			String selector = sel->Ident.token.string;
-			TypeAndValue tav = type_and_value_of_expr(proc->module->info, se->expr);
+			TypeAndValue tav = type_and_value_of_expr(se->expr);
 
 
 			if (tav.mode == Addressing_Invalid) {
 			if (tav.mode == Addressing_Invalid) {
 				// NOTE(bill): Imports
 				// NOTE(bill): Imports
@@ -5551,10 +5551,10 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 			}
 			}
 		} else {
 		} else {
 			// NOTE(bill): x.0
 			// NOTE(bill): x.0
-			Type *type = type_deref(type_of_expr(proc->module->info, se->expr));
-			Type *selector_type = base_type(type_of_expr(proc->module->info, se->selector));
+			Type *type = type_deref(type_of_expr(se->expr));
+			Type *selector_type = base_type(type_of_expr(se->selector));
 			GB_ASSERT_MSG(is_type_integer(selector_type), "%s", type_to_string(selector_type));
 			GB_ASSERT_MSG(is_type_integer(selector_type), "%s", type_to_string(selector_type));
-			ExactValue val = type_and_value_of_expr(proc->module->info, sel).value;
+			ExactValue val = type_and_value_of_expr(sel).value;
 			i64 index = val.value_integer;
 			i64 index = val.value_integer;
 
 
 			Selection sel = lookup_field_from_index(type, index);
 			Selection sel = lookup_field_from_index(type, index);
@@ -5572,14 +5572,14 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 		irValue *e = ir_build_expr(proc, ta->expr);
 		irValue *e = ir_build_expr(proc, ta->expr);
 		Type *t = type_deref(ir_type(e));
 		Type *t = type_deref(ir_type(e));
 		if (is_type_union(t)) {
 		if (is_type_union(t)) {
-			Type *type = type_of_expr(proc->module->info, expr);
+			Type *type = type_of_expr(expr);
 			irValue *v = ir_add_local_generated(proc, type);
 			irValue *v = ir_add_local_generated(proc, type);
 			ir_emit_comment(proc, str_lit("cast - union_cast"));
 			ir_emit_comment(proc, str_lit("cast - union_cast"));
 			ir_emit_store(proc, v, ir_emit_union_cast(proc, ir_build_expr(proc, ta->expr), type, pos));
 			ir_emit_store(proc, v, ir_emit_union_cast(proc, ir_build_expr(proc, ta->expr), type, pos));
 			return ir_addr(v);
 			return ir_addr(v);
 		} else if (is_type_any(t)) {
 		} else if (is_type_any(t)) {
 			ir_emit_comment(proc, str_lit("cast - any_cast"));
 			ir_emit_comment(proc, str_lit("cast - any_cast"));
-			Type *type = type_of_expr(proc->module->info, expr);
+			Type *type = type_of_expr(expr);
 			return ir_emit_any_cast_addr(proc, ir_build_expr(proc, ta->expr), type, pos);
 			return ir_emit_any_cast_addr(proc, ir_build_expr(proc, ta->expr), type, pos);
 		} else {
 		} else {
 			GB_PANIC("TODO(bill): type assertion %s", type_to_string(ir_type(e)));
 			GB_PANIC("TODO(bill): type assertion %s", type_to_string(ir_type(e)));
@@ -5605,7 +5605,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 
 
 	case_ast_node(ie, IndexExpr, expr);
 	case_ast_node(ie, IndexExpr, expr);
 		ir_emit_comment(proc, str_lit("IndexExpr"));
 		ir_emit_comment(proc, str_lit("IndexExpr"));
-		Type *t = base_type(type_of_expr(proc->module->info, ie->expr));
+		Type *t = base_type(type_of_expr(ie->expr));
 		gbAllocator a = proc->module->allocator;
 		gbAllocator a = proc->module->allocator;
 
 
 		bool deref = is_type_pointer(t);
 		bool deref = is_type_pointer(t);
@@ -5621,7 +5621,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 			irValue *key = ir_build_expr(proc, ie->index);
 			irValue *key = ir_build_expr(proc, ie->index);
 			key = ir_emit_conv(proc, key, t->Map.key);
 			key = ir_emit_conv(proc, key, t->Map.key);
 
 
-			Type *result_type = type_of_expr(proc->module->info, expr);
+			Type *result_type = type_of_expr(expr);
 			return ir_addr_map(map_val, key, t, result_type);
 			return ir_addr_map(map_val, key, t, result_type);
 		}
 		}
 
 
@@ -5641,7 +5641,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 			irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
 			irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
 			irValue *elem = ir_emit_array_ep(proc, array, index);
 			irValue *elem = ir_emit_array_ep(proc, array, index);
 
 
-			auto index_tv = type_and_value_of_expr(proc->module->info, ie->index);
+			auto index_tv = type_and_value_of_expr(ie->index);
 			if (index_tv.mode != Addressing_Constant) {
 			if (index_tv.mode != Addressing_Constant) {
 				irValue *len = ir_const_int(a, t->Array.count);
 				irValue *len = ir_const_int(a, t->Array.count);
 				ir_emit_bounds_check(proc, ast_token(ie->index), index, len);
 				ir_emit_bounds_check(proc, ast_token(ie->index), index, len);
@@ -5779,8 +5779,8 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 
 
 			if (high == nullptr) high = len;
 			if (high == nullptr) high = len;
 
 
-			bool low_const  = type_and_value_of_expr(proc->module->info, se->low).mode  == Addressing_Constant;
-			bool high_const = type_and_value_of_expr(proc->module->info, se->high).mode == Addressing_Constant;
+			bool low_const  = type_and_value_of_expr(se->low).mode  == Addressing_Constant;
+			bool high_const = type_and_value_of_expr(se->high).mode == Addressing_Constant;
 
 
 			if (!low_const || !high_const) {
 			if (!low_const || !high_const) {
 				ir_emit_slice_bounds_check(proc, se->open, low, high, len, false);
 				ir_emit_slice_bounds_check(proc, se->open, low, high, len, false);
@@ -5830,7 +5830,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 
 
 	case_ast_node(cl, CompoundLit, expr);
 	case_ast_node(cl, CompoundLit, expr);
 		ir_emit_comment(proc, str_lit("CompoundLit"));
 		ir_emit_comment(proc, str_lit("CompoundLit"));
-		Type *type = type_of_expr(proc->module->info, expr);
+		Type *type = type_of_expr(expr);
 		Type *bt = base_type(type);
 		Type *bt = base_type(type);
 
 
 		irValue *v = ir_add_local_generated(proc, type, true);
 		irValue *v = ir_add_local_generated(proc, type, true);
@@ -5873,7 +5873,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 						index = sel.index[0];
 						index = sel.index[0];
 						elem = fv->value;
 						elem = fv->value;
 					} else {
 					} else {
-						TypeAndValue tav = type_and_value_of_expr(proc->module->info, elem);
+						TypeAndValue tav = type_and_value_of_expr(elem);
 						Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_src_index);
 						Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_src_index);
 						index = sel.index[0];
 						index = sel.index[0];
 					}
 					}
@@ -6033,7 +6033,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 						index = sel.index[0];
 						index = sel.index[0];
 						elem = fv->value;
 						elem = fv->value;
 					} else {
 					} else {
-						TypeAndValue tav = type_and_value_of_expr(proc->module->info, elem);
+						TypeAndValue tav = type_and_value_of_expr(elem);
 						Selection sel = lookup_field(bt, field_names[field_index], false);
 						Selection sel = lookup_field(bt, field_names[field_index], false);
 						index = sel.index[0];
 						index = sel.index[0];
 					}
 					}
@@ -6055,7 +6055,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 	case_end;
 	case_end;
 
 
 	case_ast_node(tc, TypeCast, expr);
 	case_ast_node(tc, TypeCast, expr);
-		Type *type = type_of_expr(proc->module->info, expr);
+		Type *type = type_of_expr(expr);
 		irValue *x = ir_build_expr(proc, tc->expr);
 		irValue *x = ir_build_expr(proc, tc->expr);
 		irValue *e = nullptr;
 		irValue *e = nullptr;
 		switch (tc->token.kind) {
 		switch (tc->token.kind) {
@@ -6557,7 +6557,7 @@ void ir_build_range_interval(irProcedure *proc, AstBinaryExpr *node, Type *val_t
 }
 }
 
 
 void ir_store_type_case_implicit(irProcedure *proc, Ast *clause, irValue *value) {
 void ir_store_type_case_implicit(irProcedure *proc, Ast *clause, irValue *value) {
-	Entity *e = implicit_entity_of_node(proc->module->info, clause);
+	Entity *e = implicit_entity_of_node(clause);
 	GB_ASSERT(e != nullptr);
 	GB_ASSERT(e != nullptr);
 	irValue *x = ir_add_local(proc, e, nullptr, false);
 	irValue *x = ir_add_local(proc, e, nullptr, false);
 	ir_emit_store(proc, x, value);
 	ir_emit_store(proc, x, value);
@@ -6912,10 +6912,10 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
 		Type *val0_type = nullptr;
 		Type *val0_type = nullptr;
 		Type *val1_type = nullptr;
 		Type *val1_type = nullptr;
 		if (rs->val0 != nullptr && !is_blank_ident(rs->val0)) {
 		if (rs->val0 != nullptr && !is_blank_ident(rs->val0)) {
-			val0_type = type_of_expr(proc->module->info, rs->val0);
+			val0_type = type_of_expr(rs->val0);
 		}
 		}
 		if (rs->val1 != nullptr && !is_blank_ident(rs->val1)) {
 		if (rs->val1 != nullptr && !is_blank_ident(rs->val1)) {
-			val1_type = type_of_expr(proc->module->info, rs->val1);
+			val1_type = type_of_expr(rs->val1);
 		}
 		}
 
 
 		if (val0_type != nullptr) {
 		if (val0_type != nullptr) {
@@ -6932,7 +6932,7 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
 		Ast *expr = unparen_expr(rs->expr);
 		Ast *expr = unparen_expr(rs->expr);
 		bool is_map = false;
 		bool is_map = false;
 
 
-		TypeAndValue tav = type_and_value_of_expr(proc->module->info, expr);
+		TypeAndValue tav = type_and_value_of_expr(expr);
 
 
 		if (is_ast_range(expr)) {
 		if (is_ast_range(expr)) {
 			ir_build_range_interval(proc, &expr->BinaryExpr, val0_type, &val, &key, &loop, &done);
 			ir_build_range_interval(proc, &expr->BinaryExpr, val0_type, &val, &key, &loop, &done);
@@ -6984,7 +6984,7 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
 				}
 				}
 			}
 			}
 		} else {
 		} else {
-			Type *expr_type = type_of_expr(proc->module->info, rs->expr);
+			Type *expr_type = type_of_expr(rs->expr);
 			Type *et = base_type(type_deref(expr_type));
 			Type *et = base_type(type_deref(expr_type));
 			switch (et->kind) {
 			switch (et->kind) {
 			case Type_Map: {
 			case Type_Map: {
@@ -7239,7 +7239,7 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
 			Type *case_type = nullptr;
 			Type *case_type = nullptr;
 			for_array(type_index, cc->list) {
 			for_array(type_index, cc->list) {
 				next = ir_new_block(proc, nullptr, "typeswitch.next");
 				next = ir_new_block(proc, nullptr, "typeswitch.next");
-				case_type = type_of_expr(proc->module->info, cc->list[type_index]);
+				case_type = type_of_expr(cc->list[type_index]);
 				irValue *cond = nullptr;
 				irValue *cond = nullptr;
 				if (switch_kind == TypeSwitch_Union) {
 				if (switch_kind == TypeSwitch_Union) {
 					Type *ut = base_type(type_deref(parent_type));
 					Type *ut = base_type(type_deref(parent_type));
@@ -7256,7 +7256,7 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
 				ir_start_block(proc, next);
 				ir_start_block(proc, next);
 			}
 			}
 
 
-			Entity *case_entity = implicit_entity_of_node(proc->module->info, clause);
+			Entity *case_entity = implicit_entity_of_node(clause);
 
 
 			irValue *value = parent_value;
 			irValue *value = parent_value;
 
 
@@ -8380,7 +8380,7 @@ void ir_gen_tree(irGen *s) {
 			var.decl = decl;
 			var.decl = decl;
 
 
 			if (decl->init_expr != nullptr && !is_type_any(e->type)) {
 			if (decl->init_expr != nullptr && !is_type_any(e->type)) {
-				TypeAndValue tav = type_and_value_of_expr(info, decl->init_expr);
+				TypeAndValue tav = type_and_value_of_expr(decl->init_expr);
 				if (tav.mode != Addressing_Invalid) {
 				if (tav.mode != Addressing_Invalid) {
 					if (tav.value.kind != ExactValue_Invalid) {
 					if (tav.value.kind != ExactValue_Invalid) {
 						ExactValue v = tav.value;
 						ExactValue v = tav.value;

+ 3 - 3
src/ir_print.cpp

@@ -681,7 +681,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 
 
 			for (isize i = 0; i < elem_count; i++) {
 			for (isize i = 0; i < elem_count; i++) {
 				if (i > 0) ir_write_str_lit(f, ", ");
 				if (i > 0) ir_write_str_lit(f, ", ");
-				TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems[i]);
+				TypeAndValue tav = cl->elems[i]->tav;
 				GB_ASSERT(tav.mode != Addressing_Invalid);
 				GB_ASSERT(tav.mode != Addressing_Invalid);
 				ir_print_compound_element(f, m, tav.value, elem_type);
 				ir_print_compound_element(f, m, tav.value, elem_type);
 			}
 			}
@@ -715,7 +715,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 						ast_node(fv, FieldValue, cl->elems[i]);
 						ast_node(fv, FieldValue, cl->elems[i]);
 						String name = fv->field->Ident.token.string;
 						String name = fv->field->Ident.token.string;
 
 
-						TypeAndValue tav = type_and_value_of_expr(m->info, fv->value);
+						TypeAndValue tav = fv->value->tav;
 						GB_ASSERT(tav.mode != Addressing_Invalid);
 						GB_ASSERT(tav.mode != Addressing_Invalid);
 
 
 						Selection sel = lookup_field(type, name, false);
 						Selection sel = lookup_field(type, name, false);
@@ -727,7 +727,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 				} else {
 				} else {
 					for_array(i, cl->elems) {
 					for_array(i, cl->elems) {
 						Entity *f = type->Struct.fields[i];
 						Entity *f = type->Struct.fields[i];
-						TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems[i]);
+						TypeAndValue tav = cl->elems[i]->tav;
 						ExactValue val = {};
 						ExactValue val = {};
 						if (tav.mode != Addressing_Invalid) {
 						if (tav.mode != Addressing_Invalid) {
 							val = tav.value;
 							val = tav.value;

+ 55 - 33
src/parser.hpp

@@ -6,6 +6,28 @@ struct DeclInfo;
 struct AstFile;
 struct AstFile;
 struct AstPackage;
 struct AstPackage;
 
 
+enum AddressingMode {
+	Addressing_Invalid,       // invalid addressing mode
+	Addressing_NoValue,       // no value (void in C)
+	Addressing_Value,         // computed value (rvalue)
+	Addressing_Immutable,     // immutable computed value (const rvalue)
+	Addressing_Variable,      // addressable variable (lvalue)
+	Addressing_Constant,      // constant
+	Addressing_Type,          // type
+	Addressing_Builtin,       // built-in procedure
+	Addressing_ProcGroup,     // procedure group (overloaded procedure)
+	Addressing_MapIndex,      // map index expression -
+	                          // 	lhs: acts like a Variable
+	                          // 	rhs: acts like OptionalOk
+	Addressing_OptionalOk,    // rhs: acts like a value with an optional boolean part (for existence check)
+};
+
+struct TypeAndValue {
+	AddressingMode mode;
+	Type *         type;
+	ExactValue     value;
+};
+
 
 
 enum ParseFileError {
 enum ParseFileError {
 	ParseFile_None,
 	ParseFile_None,
@@ -48,42 +70,41 @@ struct ImportedFile {
 };
 };
 
 
 struct AstFile {
 struct AstFile {
-	isize               id;
-	AstPackage *        pkg;
-	Scope *             scope;
-
-	Ast *           pkg_decl;
-	String              fullpath;
-	Tokenizer           tokenizer;
-	Array<Token>        tokens;
-	isize               curr_token_index;
-	Token               curr_token;
-	Token               prev_token; // previous non-comment
-	Token               package_token;
-	String              package_name;
+	isize        id;
+	AstPackage * pkg;
+	Scope *      scope;
+
+	Ast *        pkg_decl;
+	String       fullpath;
+	Tokenizer    tokenizer;
+	Array<Token> tokens;
+	isize        curr_token_index;
+	Token        curr_token;
+	Token        prev_token; // previous non-comment
+	Token        package_token;
+	String       package_name;
 
 
 	// >= 0: In Expression
 	// >= 0: In Expression
 	// <  0: In Control Clause
 	// <  0: In Control Clause
 	// NOTE(bill): Used to prevent type literals in control clauses
 	// NOTE(bill): Used to prevent type literals in control clauses
-	isize               expr_level;
-	bool                allow_range; // NOTE(bill): Ranges are only allowed in certain cases
-	bool                in_foreign_block;
-	bool                allow_type;
-	isize               when_level;
+	isize        expr_level;
+	bool         allow_range; // NOTE(bill): Ranges are only allowed in certain cases
+	bool         in_foreign_block;
+	bool         allow_type;
+	isize        when_level;
 
 
-	Array<Ast *>    decls;
-	Array<Ast *>    imports; // 'import' 'using import'
-	isize               directive_count;
+	Array<Ast *> decls;
+	Array<Ast *> imports; // 'import' 'using import'
+	isize        directive_count;
 
 
 
 
-	Ast *           curr_proc;
-	// DeclInfo *          decl_info;   // NOTE(bill): Created in checker
-	isize               error_count;
+	Ast *        curr_proc;
+	isize        error_count;
 
 
-	CommentGroup *        lead_comment; // Comment (block) before the decl
-	CommentGroup *        line_comment; // Comment after the semicolon
-	CommentGroup *        docs;         // current docs
-	Array<CommentGroup *> comments;     // All the comments!
+	CommentGroup *lead_comment;     // Comment (block) before the decl
+	CommentGroup *line_comment;     // Comment after the semicolon
+	CommentGroup *docs;             // current docs
+	Array<CommentGroup *> comments; // All the comments!
 
 
 
 
 #define PARSER_MAX_FIX_COUNT 6
 #define PARSER_MAX_FIX_COUNT 6
@@ -501,11 +522,12 @@ isize const ast_variant_sizes[] = {
 };
 };
 
 
 struct Ast {
 struct Ast {
-	AstKind  kind;
-	u32      stmt_state_flags;
-	AstFile *file;
-	Scope *  scope;
-	bool     been_handled;
+	AstKind      kind;
+	u32          stmt_state_flags;
+	AstFile *    file;
+	Scope *      scope;
+	bool         been_handled;
+	TypeAndValue tav;
 
 
 	union {
 	union {
 #define AST_KIND(_kind_name_, name, ...) GB_JOIN2(Ast, _kind_name_) _kind_name_;
 #define AST_KIND(_kind_name_, name, ...) GB_JOIN2(Ast, _kind_name_) _kind_name_;