Browse Source

Improve CheckerContext usage

gingerBill 4 years ago
parent
commit
4a932616fc
7 changed files with 134 additions and 115 deletions
  1. 3 3
      src/check_builtin.cpp
  2. 1 1
      src/check_decl.cpp
  3. 9 11
      src/check_expr.cpp
  4. 5 5
      src/check_stmt.cpp
  5. 15 15
      src/check_type.cpp
  6. 79 61
      src/checker.cpp
  7. 22 19
      src/checker.hpp

+ 3 - 3
src/check_builtin.cpp

@@ -1934,7 +1934,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 
 
 				Entity *new_field = alloc_entity_field(scope, token, array_type, false, cast(i32)i);
 				Entity *new_field = alloc_entity_field(scope, token, array_type, false, cast(i32)i);
 				soa_struct->Struct.fields[i] = new_field;
 				soa_struct->Struct.fields[i] = new_field;
-				add_entity(c->checker, scope, nullptr, new_field);
+				add_entity(c, scope, nullptr, new_field);
 				add_entity_use(c, nullptr, new_field);
 				add_entity_use(c, nullptr, new_field);
 			}
 			}
 
 
@@ -1959,7 +1959,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 					Type *array_type = alloc_type_array(old_field->type, count);
 					Type *array_type = alloc_type_array(old_field->type, count);
 					Entity *new_field = alloc_entity_field(scope, old_field->token, array_type, false, old_field->Variable.field_src_index);
 					Entity *new_field = alloc_entity_field(scope, old_field->token, array_type, false, old_field->Variable.field_src_index);
 					soa_struct->Struct.fields[i] = new_field;
 					soa_struct->Struct.fields[i] = new_field;
-					add_entity(c->checker, scope, nullptr, new_field);
+					add_entity(c, scope, nullptr, new_field);
 				} else {
 				} else {
 					soa_struct->Struct.fields[i] = old_field;
 					soa_struct->Struct.fields[i] = old_field;
 				}
 				}
@@ -1971,7 +1971,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 		Token token = {};
 		Token token = {};
 		token.string = str_lit("Base_Type");
 		token.string = str_lit("Base_Type");
 		Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved);
 		Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved);
-		add_entity(c->checker, scope, nullptr, base_type_entity);
+		add_entity(c, scope, nullptr, base_type_entity);
 
 
 		add_type_info_type(c, soa_struct);
 		add_type_info_type(c, soa_struct);
 
 

+ 1 - 1
src/check_decl.cpp

@@ -313,7 +313,7 @@ void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, Type *def)
 					if (is_blank_ident(name)) {
 					if (is_blank_ident(name)) {
 						continue;
 						continue;
 					}
 					}
-					add_entity(ctx->checker, parent, nullptr, f);
+					add_entity(ctx, parent, nullptr, f);
 				}
 				}
 			}
 			}
 		}
 		}

+ 9 - 11
src/check_expr.cpp

@@ -2889,8 +2889,8 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
 
 
 void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
 void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
 	GB_ASSERT(e != nullptr);
 	GB_ASSERT(e != nullptr);
-	ExprInfo *found = check_get_expr_info(&c->checker->info, e);
-	if (found == nullptr) {
+	ExprInfo *old = check_get_expr_info(&c->checker->info, e);
+	if (old == nullptr) {
 		if (type != nullptr && type != t_invalid) {
 		if (type != nullptr && type != t_invalid) {
 			if (e->tav.type == nullptr || e->tav.type == t_invalid) {
 			if (e->tav.type == nullptr || e->tav.type == t_invalid) {
 				add_type_and_value(&c->checker->info, e, e->tav.mode, type ? type : e->tav.type, e->tav.value);
 				add_type_and_value(&c->checker->info, e, e->tav.mode, type ? type : e->tav.type, e->tav.value);
@@ -2898,11 +2898,10 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
 		}
 		}
 		return;
 		return;
 	}
 	}
-	ExprInfo old = *found;
 
 
 	switch (e->kind) {
 	switch (e->kind) {
 	case_ast_node(ue, UnaryExpr, e);
 	case_ast_node(ue, UnaryExpr, e);
-		if (old.value.kind != ExactValue_Invalid) {
+		if (old->value.kind != ExactValue_Invalid) {
 			// NOTE(bill): if 'e' is constant, the operands will be constant too.
 			// NOTE(bill): if 'e' is constant, the operands will be constant too.
 			// They don't need to be updated as they will be updated later and
 			// They don't need to be updated as they will be updated later and
 			// checked at the end of general checking stage.
 			// checked at the end of general checking stage.
@@ -2912,7 +2911,7 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
 	case_end;
 	case_end;
 
 
 	case_ast_node(be, BinaryExpr, e);
 	case_ast_node(be, BinaryExpr, e);
-		if (old.value.kind != ExactValue_Invalid) {
+		if (old->value.kind != ExactValue_Invalid) {
 			// See above note in UnaryExpr case
 			// See above note in UnaryExpr case
 			break;
 			break;
 		}
 		}
@@ -2927,7 +2926,7 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
 	case_end;
 	case_end;
 
 
 	case_ast_node(te, TernaryIfExpr, e);
 	case_ast_node(te, TernaryIfExpr, e);
-		if (old.value.kind != ExactValue_Invalid) {
+		if (old->value.kind != ExactValue_Invalid) {
 			// See above note in UnaryExpr case
 			// See above note in UnaryExpr case
 			break;
 			break;
 		}
 		}
@@ -2937,7 +2936,7 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
 	case_end;
 	case_end;
 
 
 	case_ast_node(te, TernaryWhenExpr, e);
 	case_ast_node(te, TernaryWhenExpr, e);
-		if (old.value.kind != ExactValue_Invalid) {
+		if (old->value.kind != ExactValue_Invalid) {
 			// See above note in UnaryExpr case
 			// See above note in UnaryExpr case
 			break;
 			break;
 		}
 		}
@@ -2952,15 +2951,14 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
 	}
 	}
 
 
 	if (!final && is_type_untyped(type)) {
 	if (!final && is_type_untyped(type)) {
-		old.type = base_type(type);
-		check_set_expr_info(&c->checker->info, e, old);
+		old->type = base_type(type);
 		return;
 		return;
 	}
 	}
 
 
 	// We need to remove it and then give it a new one
 	// We need to remove it and then give it a new one
 	check_remove_expr_info(&c->checker->info, e);
 	check_remove_expr_info(&c->checker->info, e);
 
 
-	if (old.is_lhs && !is_type_integer(type)) {
+	if (old->is_lhs && !is_type_integer(type)) {
 		gbString expr_str = expr_to_string(e);
 		gbString expr_str = expr_to_string(e);
 		gbString type_str = type_to_string(type);
 		gbString type_str = type_to_string(type);
 		error(e, "Shifted operand %s must be an integer, got %s", expr_str, type_str);
 		error(e, "Shifted operand %s must be an integer, got %s", expr_str, type_str);
@@ -2969,7 +2967,7 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
 		return;
 		return;
 	}
 	}
 
 
-	add_type_and_value(&c->checker->info, e, old.mode, type, old.value);
+	add_type_and_value(&c->checker->info, e, old->mode, type, old->value);
 }
 }
 
 
 void update_expr_value(CheckerContext *c, Ast *e, ExactValue value) {
 void update_expr_value(CheckerContext *c, Ast *e, ExactValue value) {

+ 5 - 5
src/check_stmt.cpp

@@ -558,7 +558,7 @@ void check_label(CheckerContext *ctx, Ast *label, Ast *parent) {
 	}
 	}
 
 
 	Entity *e = alloc_entity_label(ctx->scope, l->name->Ident.token, t_invalid, label, parent);
 	Entity *e = alloc_entity_label(ctx->scope, l->name->Ident.token, t_invalid, label, parent);
-	add_entity(ctx->checker, ctx->scope, l->name, e);
+	add_entity(ctx, ctx->scope, l->name, e);
 	e->parent_proc_decl = ctx->curr_proc_decl;
 	e->parent_proc_decl = ctx->curr_proc_decl;
 
 
 	if (ok) {
 	if (ok) {
@@ -861,7 +861,7 @@ void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
 	}
 	}
 
 
 	for (isize i = 0; i < entity_count; i++) {
 	for (isize i = 0; i < entity_count; i++) {
-		add_entity(ctx->checker, ctx->scope, entities[i]->identifier, entities[i]);
+		add_entity(ctx, ctx->scope, entities[i]->identifier, entities[i]);
 	}
 	}
 
 
 
 
@@ -1344,7 +1344,7 @@ void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
 			if (!is_reference) {
 			if (!is_reference) {
 				tag_var->flags |= EntityFlag_Value;
 				tag_var->flags |= EntityFlag_Value;
 			}
 			}
-			add_entity(ctx->checker, ctx->scope, lhs, tag_var);
+			add_entity(ctx, ctx->scope, lhs, tag_var);
 			add_entity_use(ctx, lhs, tag_var);
 			add_entity_use(ctx, lhs, tag_var);
 			add_implicit_entity(ctx, stmt, tag_var);
 			add_implicit_entity(ctx, stmt, tag_var);
 		}
 		}
@@ -1966,7 +1966,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
 			Entity *e = entities[i];
 			Entity *e = entities[i];
 			DeclInfo *d = decl_info_of_entity(e);
 			DeclInfo *d = decl_info_of_entity(e);
 			GB_ASSERT(d == nullptr);
 			GB_ASSERT(d == nullptr);
-			add_entity(ctx->checker, ctx->scope, e->identifier, e);
+			add_entity(ctx, ctx->scope, e->identifier, e);
 			d = make_decl_info(ctx->scope, ctx->decl);
 			d = make_decl_info(ctx->scope, ctx->decl);
 			add_entity_and_decl_info(ctx, e->identifier, e, d);
 			add_entity_and_decl_info(ctx, e->identifier, e, d);
 		}
 		}
@@ -2286,7 +2286,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
 						}
 						}
 					}
 					}
 				}
 				}
-				add_entity(ctx->checker, ctx->scope, e->identifier, e);
+				add_entity(ctx, ctx->scope, e->identifier, e);
 			}
 			}
 
 
 			if (vd->is_using != 0) {
 			if (vd->is_using != 0) {

+ 15 - 15
src/check_type.cpp

@@ -23,7 +23,7 @@ void populate_using_array_index(CheckerContext *ctx, Ast *node, AstField *field,
 			tok.pos = ast_token(field->type).pos;
 			tok.pos = ast_token(field->type).pos;
 		}
 		}
 		Entity *f = alloc_entity_array_elem(nullptr, tok, t->Array.elem, idx);
 		Entity *f = alloc_entity_array_elem(nullptr, tok, t->Array.elem, idx);
-		add_entity(ctx->checker, ctx->scope, nullptr, f);
+		add_entity(ctx, ctx->scope, nullptr, f);
 	}
 	}
 }
 }
 
 
@@ -52,7 +52,7 @@ void populate_using_entity_scope(CheckerContext *ctx, Ast *node, AstField *field
 					error(e->token, "'%.*s' is already declared", LIT(name));
 					error(e->token, "'%.*s' is already declared", LIT(name));
 				}
 				}
 			} else {
 			} else {
-				add_entity(ctx->checker, ctx->scope, nullptr, f);
+				add_entity(ctx, ctx->scope, nullptr, f);
 				if (f->flags & EntityFlag_Using) {
 				if (f->flags & EntityFlag_Using) {
 					populate_using_entity_scope(ctx, node, field, f->type);
 					populate_using_entity_scope(ctx, node, field, f->type);
 				}
 				}
@@ -157,7 +157,7 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Array<Entity *> *fields
 			Token name_token = name->Ident.token;
 			Token name_token = name->Ident.token;
 
 
 			Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index);
 			Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index);
-			add_entity(ctx->checker, ctx->scope, name, field);
+			add_entity(ctx, ctx->scope, name, field);
 			array_add(fields, field);
 			array_add(fields, field);
 			array_add(tags, p->tag.string);
 			array_add(tags, p->tag.string);
 
 
@@ -483,7 +483,7 @@ Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *polymorphic_para
 				}
 				}
 
 
 				e->state = EntityState_Resolved;
 				e->state = EntityState_Resolved;
-				add_entity(ctx->checker, scope, name, e);
+				add_entity(ctx, scope, name, e);
 				array_add(&entities, e);
 				array_add(&entities, e);
 			}
 			}
 		}
 		}
@@ -795,7 +795,7 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast
 		if (scope_lookup_current(ctx->scope, name) != nullptr) {
 		if (scope_lookup_current(ctx->scope, name) != nullptr) {
 			error(ident, "'%.*s' is already declared in this enumeration", LIT(name));
 			error(ident, "'%.*s' is already declared in this enumeration", LIT(name));
 		} else {
 		} else {
-			add_entity(ctx->checker, ctx->scope, nullptr, e);
+			add_entity(ctx, ctx->scope, nullptr, e);
 			array_add(&fields, e);
 			array_add(&fields, e);
 			// TODO(bill): Should I add a use for the enum value?
 			// TODO(bill): Should I add a use for the enum value?
 			add_entity_use(ctx, field, e);
 			add_entity_use(ctx, field, e);
@@ -1622,7 +1622,7 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
 			}
 			}
 
 
 			param->state = EntityState_Resolved; // NOTE(bill): This should have be resolved whilst determining it
 			param->state = EntityState_Resolved; // NOTE(bill): This should have be resolved whilst determining it
-			add_entity(ctx->checker, scope, name, param);
+			add_entity(ctx, scope, name, param);
 			if (is_using) {
 			if (is_using) {
 				add_entity_use(ctx, name, param);
 				add_entity_use(ctx, name, param);
 			}
 			}
@@ -1749,7 +1749,7 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
 				param->flags |= EntityFlag_Result;
 				param->flags |= EntityFlag_Result;
 				param->Variable.param_value = param_value;
 				param->Variable.param_value = param_value;
 				array_add(&variables, param);
 				array_add(&variables, param);
-				add_entity(ctx->checker, scope, name, param);
+				add_entity(ctx, scope, name, param);
 				// NOTE(bill): Removes `declared but not used` when using -vet
 				// NOTE(bill): Removes `declared but not used` when using -vet
 				add_entity_use(ctx, name, param);
 				add_entity_use(ctx, name, param);
 			}
 			}
@@ -2243,7 +2243,7 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el
 
 
 			Entity *new_field = alloc_entity_field(scope, token, field_type, false, cast(i32)i);
 			Entity *new_field = alloc_entity_field(scope, token, field_type, false, cast(i32)i);
 			soa_struct->Struct.fields[i] = new_field;
 			soa_struct->Struct.fields[i] = new_field;
-			add_entity(ctx->checker, scope, nullptr, new_field);
+			add_entity(ctx, scope, nullptr, new_field);
 			add_entity_use(ctx, nullptr, new_field);
 			add_entity_use(ctx, nullptr, new_field);
 		}
 		}
 
 
@@ -2277,7 +2277,7 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el
 				}
 				}
 				Entity *new_field = alloc_entity_field(scope, old_field->token, field_type, false, old_field->Variable.field_src_index);
 				Entity *new_field = alloc_entity_field(scope, old_field->token, field_type, false, old_field->Variable.field_src_index);
 				soa_struct->Struct.fields[i] = new_field;
 				soa_struct->Struct.fields[i] = new_field;
-				add_entity(ctx->checker, scope, nullptr, new_field);
+				add_entity(ctx, scope, nullptr, new_field);
 				add_entity_use(ctx, nullptr, new_field);
 				add_entity_use(ctx, nullptr, new_field);
 			} else {
 			} else {
 				soa_struct->Struct.fields[i] = old_field;
 				soa_struct->Struct.fields[i] = old_field;
@@ -2290,13 +2290,13 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el
 	if (soa_kind != StructSoa_Fixed) {
 	if (soa_kind != StructSoa_Fixed) {
 		Entity *len_field = alloc_entity_field(scope, empty_token, t_int, false, cast(i32)field_count+0);
 		Entity *len_field = alloc_entity_field(scope, empty_token, t_int, false, cast(i32)field_count+0);
 		soa_struct->Struct.fields[field_count+0] = len_field;
 		soa_struct->Struct.fields[field_count+0] = len_field;
-		add_entity(ctx->checker, scope, nullptr, len_field);
+		add_entity(ctx, scope, nullptr, len_field);
 		add_entity_use(ctx, nullptr, len_field);
 		add_entity_use(ctx, nullptr, len_field);
 
 
 		if (soa_kind == StructSoa_Dynamic) {
 		if (soa_kind == StructSoa_Dynamic) {
 			Entity *cap_field = alloc_entity_field(scope, empty_token, t_int, false, cast(i32)field_count+1);
 			Entity *cap_field = alloc_entity_field(scope, empty_token, t_int, false, cast(i32)field_count+1);
 			soa_struct->Struct.fields[field_count+1] = cap_field;
 			soa_struct->Struct.fields[field_count+1] = cap_field;
-			add_entity(ctx->checker, scope, nullptr, cap_field);
+			add_entity(ctx, scope, nullptr, cap_field);
 			add_entity_use(ctx, nullptr, cap_field);
 			add_entity_use(ctx, nullptr, cap_field);
 
 
 			Token token = {};
 			Token token = {};
@@ -2304,7 +2304,7 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el
 			init_mem_allocator(ctx->checker);
 			init_mem_allocator(ctx->checker);
 			Entity *allocator_field = alloc_entity_field(scope, token, t_allocator, false, cast(i32)field_count+2);
 			Entity *allocator_field = alloc_entity_field(scope, token, t_allocator, false, cast(i32)field_count+2);
 			soa_struct->Struct.fields[field_count+2] = allocator_field;
 			soa_struct->Struct.fields[field_count+2] = allocator_field;
-			add_entity(ctx->checker, scope, nullptr, allocator_field);
+			add_entity(ctx, scope, nullptr, allocator_field);
 			add_entity_use(ctx, nullptr, allocator_field);
 			add_entity_use(ctx, nullptr, allocator_field);
 		}
 		}
 	}
 	}
@@ -2312,7 +2312,7 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el
 	Token token = {};
 	Token token = {};
 	token.string = str_lit("Base_Type");
 	token.string = str_lit("Base_Type");
 	Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved);
 	Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved);
-	add_entity(ctx->checker, scope, nullptr, base_type_entity);
+	add_entity(ctx, scope, nullptr, base_type_entity);
 
 
 	add_type_info_type(ctx, soa_struct);
 	add_type_info_type(ctx, soa_struct);
 
 
@@ -2425,8 +2425,8 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
 			t->Generic.entity = e;
 			t->Generic.entity = e;
 			e->TypeName.is_type_alias = true;
 			e->TypeName.is_type_alias = true;
 			e->state = EntityState_Resolved;
 			e->state = EntityState_Resolved;
-			add_entity(ctx->checker, ps, ident, e);
-			add_entity(ctx->checker, s, ident, e);
+			add_entity(ctx, ps, ident, e);
+			add_entity(ctx, s, ident, e);
 		} else {
 		} else {
 			error(ident, "Invalid use of a polymorphic parameter '$%.*s'", LIT(token.string));
 			error(ident, "Invalid use of a polymorphic parameter '$%.*s'", LIT(token.string));
 			*type = t_invalid;
 			*type = t_invalid;

+ 79 - 61
src/checker.cpp

@@ -242,7 +242,7 @@ Scope *create_scope(Scope *parent, isize init_elements_capacity=DEFAULT_SCOPE_CA
 	return s;
 	return s;
 }
 }
 
 
-Scope *create_scope_from_file(CheckerContext *c, AstFile *f) {
+Scope *create_scope_from_file(AstFile *f) {
 	GB_ASSERT(f != nullptr);
 	GB_ASSERT(f != nullptr);
 	GB_ASSERT(f->pkg != nullptr);
 	GB_ASSERT(f->pkg != nullptr);
 	GB_ASSERT(f->pkg->scope != nullptr);
 	GB_ASSERT(f->pkg->scope != nullptr);
@@ -870,7 +870,7 @@ void destroy_checker_info(CheckerInfo *i) {
 }
 }
 
 
 CheckerContext make_checker_context(Checker *c) {
 CheckerContext make_checker_context(Checker *c) {
-	CheckerContext ctx = c->init_ctx;
+	CheckerContext ctx = {};
 	ctx.checker   = c;
 	ctx.checker   = c;
 	ctx.info      = &c->info;
 	ctx.info      = &c->info;
 	ctx.scope     = builtin_pkg->scope;
 	ctx.scope     = builtin_pkg->scope;
@@ -883,6 +883,40 @@ CheckerContext make_checker_context(Checker *c) {
 	return ctx;
 	return ctx;
 }
 }
 
 
+void add_curr_ast_file(CheckerContext *ctx, AstFile *file) {
+	if (file != nullptr) {
+		TokenPos zero_pos = {};
+		global_error_collector.prev = zero_pos;
+		ctx->file  = file;
+		ctx->decl  = file->pkg->decl_info;
+		ctx->scope = file->scope;
+		ctx->pkg   = file->pkg;
+	}
+}
+void reset_checker_context(CheckerContext *ctx, AstFile *file) {
+	if (ctx == nullptr) {
+		return;
+	}
+	auto checker = ctx->checker;
+	auto info = ctx->info;
+	auto type_path = ctx->type_path;
+	auto poly_path = ctx->poly_path;
+	array_clear(type_path);
+	array_clear(poly_path);
+
+	gb_zero_item(ctx);
+	ctx->checker = checker;
+	ctx->info = info;
+	ctx->type_path = type_path;
+	ctx->poly_path = poly_path;
+	ctx->scope     = builtin_pkg->scope;
+	ctx->pkg       = builtin_pkg;
+
+	add_curr_ast_file(ctx, file);
+}
+
+
+
 void destroy_checker_context(CheckerContext *ctx) {
 void destroy_checker_context(CheckerContext *ctx) {
 	destroy_checker_type_path(ctx->type_path);
 	destroy_checker_type_path(ctx->type_path);
 	destroy_checker_poly_path(ctx->poly_path);
 	destroy_checker_poly_path(ctx->poly_path);
@@ -907,7 +941,7 @@ bool init_checker(Checker *c, Parser *parser) {
 	isize total_token_count = c->parser->total_token_count;
 	isize total_token_count = c->parser->total_token_count;
 	isize arena_size = 2 * item_size * total_token_count;
 	isize arena_size = 2 * item_size * total_token_count;
 
 
-	c->init_ctx = make_checker_context(c);
+	c->builtin_ctx = make_checker_context(c);
 	return true;
 	return true;
 }
 }
 
 
@@ -917,7 +951,7 @@ void destroy_checker(Checker *c) {
 	array_free(&c->procs_to_check);
 	array_free(&c->procs_to_check);
 	array_free(&c->procs_with_deferred_to_check);
 	array_free(&c->procs_with_deferred_to_check);
 
 
-	destroy_checker_context(&c->init_ctx);
+	destroy_checker_context(&c->builtin_ctx);
 }
 }
 
 
 
 
@@ -994,10 +1028,11 @@ Scope *scope_of_node(Ast *node) {
 	return node->scope;
 	return node->scope;
 }
 }
 ExprInfo *check_get_expr_info(CheckerInfo *i, Ast *expr) {
 ExprInfo *check_get_expr_info(CheckerInfo *i, Ast *expr) {
-	return map_get(&i->untyped, hash_node(expr));
-}
-void check_set_expr_info(CheckerInfo *i, Ast *expr, ExprInfo info) {
-	map_set(&i->untyped, hash_node(expr), info);
+	ExprInfo **found = map_get(&i->untyped, hash_node(expr));
+	if (found) {
+		return *found;
+	}
+	return nullptr;
 }
 }
 void check_remove_expr_info(CheckerInfo *i, Ast *expr) {
 void check_remove_expr_info(CheckerInfo *i, Ast *expr) {
 	map_remove(&i->untyped, hash_node(expr));
 	map_remove(&i->untyped, hash_node(expr));
@@ -1143,7 +1178,7 @@ bool redeclaration_error(String name, Entity *prev, Entity *found) {
 	return false;
 	return false;
 }
 }
 
 
-bool add_entity_with_name(Checker *c, Scope *scope, Ast *identifier, Entity *entity, String name) {
+bool add_entity_with_name(CheckerContext *c, Scope *scope, Ast *identifier, Entity *entity, String name) {
 	if (scope == nullptr) {
 	if (scope == nullptr) {
 		return false;
 		return false;
 	}
 	}
@@ -1155,14 +1190,13 @@ bool add_entity_with_name(Checker *c, Scope *scope, Ast *identifier, Entity *ent
 	}
 	}
 	if (identifier != nullptr) {
 	if (identifier != nullptr) {
 		if (entity->file == nullptr) {
 		if (entity->file == nullptr) {
-			GB_ASSERT(c->curr_ctx != nullptr);
-			entity->file = c->curr_ctx->file;
+			entity->file = c->file;
 		}
 		}
-		add_entity_definition(&c->info, identifier, entity);
+		add_entity_definition(c->info, identifier, entity);
 	}
 	}
 	return true;
 	return true;
 }
 }
-bool add_entity(Checker *c, Scope *scope, Ast *identifier, Entity *entity) {
+bool add_entity(CheckerContext *c, Scope *scope, Ast *identifier, Entity *entity) {
 	return add_entity_with_name(c, scope, identifier, entity, entity->token.string);
 	return add_entity_with_name(c, scope, identifier, entity, entity->token.string);
 }
 }
 
 
@@ -1213,7 +1247,7 @@ void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, Dec
 				scope = pkg->scope;
 				scope = pkg->scope;
 			}
 			}
 		}
 		}
-		add_entity(c->checker, scope, identifier, e);
+		add_entity(c, scope, identifier, e);
 	}
 	}
 
 
 	add_entity_definition(&c->checker->info, identifier, e);
 	add_entity_definition(&c->checker->info, identifier, e);
@@ -1460,17 +1494,6 @@ void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *dec
 	check_procedure_later(c, info);
 	check_procedure_later(c, info);
 }
 }
 
 
-void add_curr_ast_file(CheckerContext *ctx, AstFile *file) {
-	if (file != nullptr) {
-		TokenPos zero_pos = {};
-		global_error_collector.prev = zero_pos;
-		ctx->file  = file;
-		ctx->decl  = file->pkg->decl_info;
-		ctx->scope = file->scope;
-		ctx->pkg   = file->pkg;
-		ctx->checker->curr_ctx = ctx;
-	}
-}
 
 
 void add_min_dep_type_info(Checker *c, Type *t) {
 void add_min_dep_type_info(Checker *c, Type *t) {
 	if (t == nullptr) {
 	if (t == nullptr) {
@@ -1488,7 +1511,7 @@ void add_min_dep_type_info(Checker *c, Type *t) {
 
 
 	isize ti_index = type_info_index(&c->info, t, false);
 	isize ti_index = type_info_index(&c->info, t, false);
 	if (ti_index < 0) {
 	if (ti_index < 0) {
-		add_type_info_type(&c->init_ctx, t); // Missing the type information
+		add_type_info_type(&c->builtin_ctx, t); // Missing the type information
 		ti_index = type_info_index(&c->info, t, false);
 		ti_index = type_info_index(&c->info, t, false);
 	}
 	}
 	GB_ASSERT(ti_index >= 0);
 	GB_ASSERT(ti_index >= 0);
@@ -2282,8 +2305,7 @@ void init_core_map_type(Checker *c) {
 	if (t_map_hash == nullptr) {
 	if (t_map_hash == nullptr) {
 		Entity *e = find_core_entity(c, str_lit("Map_Hash"));
 		Entity *e = find_core_entity(c, str_lit("Map_Hash"));
 		if (e->state == EntityState_Unresolved) {
 		if (e->state == EntityState_Unresolved) {
-			auto ctx = c->init_ctx;
-			check_entity_decl(&ctx, e, nullptr, nullptr);
+			check_entity_decl(&c->builtin_ctx, e, nullptr, nullptr);
 		}
 		}
 		t_map_hash = e->type;
 		t_map_hash = e->type;
 		GB_ASSERT(t_map_hash != nullptr);
 		GB_ASSERT(t_map_hash != nullptr);
@@ -2292,8 +2314,7 @@ void init_core_map_type(Checker *c) {
 	if (t_map_header == nullptr) {
 	if (t_map_header == nullptr) {
 		Entity *e = find_core_entity(c, str_lit("Map_Header"));
 		Entity *e = find_core_entity(c, str_lit("Map_Header"));
 		if (e->state == EntityState_Unresolved) {
 		if (e->state == EntityState_Unresolved) {
-			auto ctx = c->init_ctx;
-			check_entity_decl(&ctx, e, nullptr, nullptr);
+			check_entity_decl(&c->builtin_ctx, e, nullptr, nullptr);
 		}
 		}
 		t_map_header = e->type;
 		t_map_header = e->type;
 		GB_ASSERT(t_map_header != nullptr);
 		GB_ASSERT(t_map_header != nullptr);
@@ -2887,7 +2908,7 @@ void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array<Ast *> *attr
 			}
 			}
 
 
 			if (name == "builtin") {
 			if (name == "builtin") {
-				add_entity(ctx->checker, builtin_pkg->scope, nullptr, e);
+				add_entity(ctx, builtin_pkg->scope, nullptr, e);
 				GB_ASSERT(scope_lookup(builtin_pkg->scope, e->token.string) != nullptr);
 				GB_ASSERT(scope_lookup(builtin_pkg->scope, e->token.string) != nullptr);
 				if (value != nullptr) {
 				if (value != nullptr) {
 					error(value, "'builtin' cannot have a field value");
 					error(value, "'builtin' cannot have a field value");
@@ -3236,8 +3257,8 @@ void check_collect_entities(CheckerContext *c, Slice<Ast *> const &nodes) {
 }
 }
 
 
 CheckerContext *create_checker_context(Checker *c) {
 CheckerContext *create_checker_context(Checker *c) {
-	CheckerContext *ctx = gb_alloc_item(heap_allocator(), CheckerContext);
-	*ctx = c->init_ctx;
+	CheckerContext *ctx = gb_alloc_item(permanent_allocator(), CheckerContext);
+	*ctx = make_checker_context(c);
 	return ctx;
 	return ctx;
 }
 }
 
 
@@ -3611,7 +3632,7 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) {
 		                                     id->fullpath, id->import_name.string,
 		                                     id->fullpath, id->import_name.string,
 		                                     scope);
 		                                     scope);
 
 
-		add_entity(ctx->checker, parent_scope, nullptr, e);
+		add_entity(ctx, parent_scope, nullptr, e);
 		if (force_use || id->is_using) {
 		if (force_use || id->is_using) {
 			add_entity_use(ctx, nullptr, e);
 			add_entity_use(ctx, nullptr, e);
 		}
 		}
@@ -3638,7 +3659,7 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) {
 					// file scope otherwise the error would be the wrong way around
 					// file scope otherwise the error would be the wrong way around
 					redeclaration_error(name, found, e);
 					redeclaration_error(name, found, e);
 				} else {
 				} else {
-					add_entity_with_name(ctx->checker, parent_scope, e->identifier, e, name);
+					add_entity_with_name(ctx, parent_scope, e->identifier, e, name);
 				}
 				}
 			}
 			}
 		}
 		}
@@ -3700,7 +3721,7 @@ void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
 
 
 	Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid,
 	Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid,
 	                                      fl->fullpaths, library_name);
 	                                      fl->fullpaths, library_name);
-	add_entity(ctx->checker, parent_scope, nullptr, e);
+	add_entity(ctx, parent_scope, nullptr, e);
 
 
 
 
 	AttributeContext ac = {};
 	AttributeContext ac = {};
@@ -3958,6 +3979,8 @@ void check_import_entities(Checker *c) {
 		}
 		}
 	}
 	}
 
 
+	CheckerContext ctx = make_checker_context(c);
+
 	for (isize loop_count = 0; ; loop_count++) {
 	for (isize loop_count = 0; ; loop_count++) {
 		bool new_files = false;
 		bool new_files = false;
 		for_array(i, package_order) {
 		for_array(i, package_order) {
@@ -3970,8 +3993,7 @@ void check_import_entities(Checker *c) {
 
 
 			for_array(i, pkg->files) {
 			for_array(i, pkg->files) {
 				AstFile *f = pkg->files[i];
 				AstFile *f = pkg->files[i];
-				CheckerContext ctx = c->init_ctx;
-				add_curr_ast_file(&ctx, f);
+				reset_checker_context(&ctx, f);
 				new_files |= collect_checked_packages_from_decl_list(c, f->decls);
 				new_files |= collect_checked_packages_from_decl_list(c, f->decls);
 			}
 			}
 		}
 		}
@@ -3994,9 +4016,8 @@ void check_import_entities(Checker *c) {
 		for_array(i, pkg->files) {
 		for_array(i, pkg->files) {
 			AstFile *f = pkg->files[i];
 			AstFile *f = pkg->files[i];
 
 
-			CheckerContext ctx = c->init_ctx;
+			reset_checker_context(&ctx, f);
 			ctx.collect_delayed_decls = true;
 			ctx.collect_delayed_decls = true;
-			add_curr_ast_file(&ctx, f);
 
 
 			if (collect_file_decls(&ctx, f->decls)) {
 			if (collect_file_decls(&ctx, f->decls)) {
 				new_packages = true;
 				new_packages = true;
@@ -4017,8 +4038,7 @@ void check_import_entities(Checker *c) {
 
 
 		for_array(i, pkg->files) {
 		for_array(i, pkg->files) {
 			AstFile *f = pkg->files[i];
 			AstFile *f = pkg->files[i];
-			CheckerContext ctx = c->init_ctx;
-			add_curr_ast_file(&ctx, f);
+			reset_checker_context(&ctx, f);
 
 
 			for_array(j, f->scope->delayed_imports) {
 			for_array(j, f->scope->delayed_imports) {
 				Ast *decl = f->scope->delayed_imports[j];
 				Ast *decl = f->scope->delayed_imports[j];
@@ -4027,8 +4047,7 @@ void check_import_entities(Checker *c) {
 		}
 		}
 		for_array(i, pkg->files) {
 		for_array(i, pkg->files) {
 			AstFile *f = pkg->files[i];
 			AstFile *f = pkg->files[i];
-			CheckerContext ctx = c->init_ctx;
-			add_curr_ast_file(&ctx, f);
+			reset_checker_context(&ctx, f);
 
 
 			for_array(j, f->scope->delayed_directives) {
 			for_array(j, f->scope->delayed_directives) {
 				Ast *expr = f->scope->delayed_directives[j];
 				Ast *expr = f->scope->delayed_directives[j];
@@ -4214,7 +4233,7 @@ void check_proc_info(Checker *c, ProcInfo pi) {
 
 
 	CheckerContext ctx = make_checker_context(c);
 	CheckerContext ctx = make_checker_context(c);
 	defer (destroy_checker_context(&ctx));
 	defer (destroy_checker_context(&ctx));
-	add_curr_ast_file(&ctx, pi.file);
+	reset_checker_context(&ctx, pi.file);
 	ctx.decl = pi.decl;
 	ctx.decl = pi.decl;
 
 
 	TypeProc *pt = &pi.type->Proc;
 	TypeProc *pt = &pi.type->Proc;
@@ -4332,13 +4351,13 @@ void check_parsed_files(Checker *c) {
 #define TIME_SECTION(str) do { if (build_context.show_more_timings) timings_start_section(&global_timings, str_lit(str)); } while (0)
 #define TIME_SECTION(str) do { if (build_context.show_more_timings) timings_start_section(&global_timings, str_lit(str)); } while (0)
 
 
 	TIME_SECTION("map full filepaths to scope");
 	TIME_SECTION("map full filepaths to scope");
-	add_type_info_type(&c->init_ctx, t_invalid);
+	add_type_info_type(&c->builtin_ctx, t_invalid);
 
 
 	// Map full filepaths to Scopes
 	// Map full filepaths to Scopes
 	for_array(i, c->parser->packages) {
 	for_array(i, c->parser->packages) {
 		AstPackage *p = c->parser->packages[i];
 		AstPackage *p = c->parser->packages[i];
-		Scope *scope = create_scope_from_package(&c->init_ctx, p);
-		p->decl_info = make_decl_info(scope, c->init_ctx.decl);
+		Scope *scope = create_scope_from_package(&c->builtin_ctx, p);
+		p->decl_info = make_decl_info(scope, c->builtin_ctx.decl);
 		string_map_set(&c->info.packages, p->fullpath, p);
 		string_map_set(&c->info.packages, p->fullpath, p);
 
 
 		if (scope->flags&ScopeFlag_Init) {
 		if (scope->flags&ScopeFlag_Init) {
@@ -4353,21 +4372,20 @@ void check_parsed_files(Checker *c) {
 
 
 	TIME_SECTION("collect entities");
 	TIME_SECTION("collect entities");
 	// Collect Entities
 	// Collect Entities
+	CheckerContext collect_entity_ctx = make_checker_context(c);
+	defer (destroy_checker_context(&collect_entity_ctx));
 	for_array(i, c->parser->packages) {
 	for_array(i, c->parser->packages) {
 		AstPackage *pkg = c->parser->packages[i];
 		AstPackage *pkg = c->parser->packages[i];
 
 
-		CheckerContext ctx = make_checker_context(c);
-		defer (destroy_checker_context(&ctx));
-		ctx.pkg = pkg;
-		ctx.collect_delayed_decls = false;
+		CheckerContext *ctx = &collect_entity_ctx;
 
 
 		for_array(j, pkg->files) {
 		for_array(j, pkg->files) {
 			AstFile *f = pkg->files[j];
 			AstFile *f = pkg->files[j];
-			create_scope_from_file(&ctx, f);
 			string_map_set(&c->info.files, f->fullpath, f);
 			string_map_set(&c->info.files, f->fullpath, f);
 
 
-			add_curr_ast_file(&ctx, f);
-			check_collect_entities(&ctx, f->decls);
+			create_scope_from_file(f);
+			reset_checker_context(ctx, f);
+			check_collect_entities(ctx, f->decls);
 		}
 		}
 
 
 		pkg->used = true;
 		pkg->used = true;
@@ -4382,9 +4400,9 @@ void check_parsed_files(Checker *c) {
 	TIME_SECTION("init preload");
 	TIME_SECTION("init preload");
 	init_preload(c);
 	init_preload(c);
 
 
-	CheckerContext prev_context = c->init_ctx;
-	defer (c->init_ctx = prev_context);
-	c->init_ctx.decl = make_decl_info(nullptr, nullptr);
+	CheckerContext prev_context = c->builtin_ctx;
+	defer (c->builtin_ctx = prev_context);
+	c->builtin_ctx.decl = make_decl_info(nullptr, nullptr);
 
 
 	TIME_SECTION("check procedure bodies");
 	TIME_SECTION("check procedure bodies");
 	// NOTE(bill): Nested procedures bodies will be added to this "queue"
 	// NOTE(bill): Nested procedures bodies will be added to this "queue"
@@ -4418,7 +4436,7 @@ void check_parsed_files(Checker *c) {
 		auto *entry = &c->info.untyped.entries[i];
 		auto *entry = &c->info.untyped.entries[i];
 		HashKey key = entry->key;
 		HashKey key = entry->key;
 		Ast *expr = cast(Ast *)cast(uintptr)key.key;
 		Ast *expr = cast(Ast *)cast(uintptr)key.key;
-		ExprInfo *info = &entry->value;
+		ExprInfo *info = entry->value;
 		if (info != nullptr && expr != nullptr) {
 		if (info != nullptr && expr != nullptr) {
 			if (is_type_typed(info->type)) {
 			if (is_type_typed(info->type)) {
 				compiler_error("%s (type %s) is typed!", expr_to_string(expr), type_to_string(info->type));
 				compiler_error("%s (type %s) is typed!", expr_to_string(expr), type_to_string(info->type));
@@ -4444,7 +4462,7 @@ void check_parsed_files(Checker *c) {
 		Type *t = &basic_types[i];
 		Type *t = &basic_types[i];
 		if (t->Basic.size > 0 &&
 		if (t->Basic.size > 0 &&
 		    (t->Basic.flags & BasicFlag_LLVM) == 0) {
 		    (t->Basic.flags & BasicFlag_LLVM) == 0) {
-			add_type_info_type(&c->init_ctx, t);
+			add_type_info_type(&c->builtin_ctx, t);
 		}
 		}
 	}
 	}
 
 
@@ -4456,7 +4474,7 @@ void check_parsed_files(Checker *c) {
 			// i64 size  = type_size_of(c->allocator, e->type);
 			// i64 size  = type_size_of(c->allocator, e->type);
 			i64 align = type_align_of(e->type);
 			i64 align = type_align_of(e->type);
 			if (align > 0 && ptr_set_exists(&c->info.minimum_dependency_set, e)) {
 			if (align > 0 && ptr_set_exists(&c->info.minimum_dependency_set, e)) {
-				add_type_info_type(&c->init_ctx, e->type);
+				add_type_info_type(&c->builtin_ctx, e->type);
 			}
 			}
 
 
 		} else if (e->kind == Entity_Procedure) {
 		} else if (e->kind == Entity_Procedure) {

+ 22 - 19
src/checker.hpp

@@ -20,12 +20,12 @@ struct ExprInfo {
 	bool is_lhs; // Debug info
 	bool is_lhs; // Debug info
 };
 };
 
 
-gb_inline ExprInfo make_expr_info(AddressingMode mode, Type *type, ExactValue value, bool is_lhs) {
-	ExprInfo ei = {};
-	ei.mode   = mode;
-	ei.type   = type;
-	ei.value  = value;
-	ei.is_lhs = is_lhs;
+gb_inline ExprInfo *make_expr_info(AddressingMode mode, Type *type, ExactValue const &value, bool is_lhs) {
+	ExprInfo *ei = gb_alloc_item(permanent_allocator(), ExprInfo);
+	ei->mode   = mode;
+	ei->type   = type;
+	ei->value  = value;
+	ei->is_lhs = is_lhs;
 	return ei;
 	return ei;
 }
 }
 
 
@@ -262,9 +262,6 @@ struct CheckerContext;
 struct CheckerInfo {
 struct CheckerInfo {
 	Checker *checker;
 	Checker *checker;
 
 
-	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
 	StringMap<AstFile *>    files;    // Key (full path)
 	StringMap<AstFile *>    files;    // Key (full path)
 	StringMap<AstPackage *> packages; // Key (full path)
 	StringMap<AstPackage *> packages; // Key (full path)
 	StringMap<Entity *>     foreigns;
 	StringMap<Entity *>     foreigns;
@@ -272,12 +269,6 @@ struct CheckerInfo {
 	Array<Entity *>       entities;
 	Array<Entity *>       entities;
 	Array<DeclInfo *>     variable_init_order;
 	Array<DeclInfo *>     variable_init_order;
 
 
-	Map<Array<Entity *> > gen_procs;       // Key: Ast * | Identifier -> Entity
-	Map<Array<Entity *> > gen_types;       // Key: Type *
-
-	Array<Type *>         type_info_types;
-	Map<isize>            type_info_map;   // Key: Type *
-
 
 
 	AstPackage *          builtin_package;
 	AstPackage *          builtin_package;
 	AstPackage *          runtime_package;
 	AstPackage *          runtime_package;
@@ -294,6 +285,20 @@ struct CheckerInfo {
 
 
 	bool allow_identifier_uses;
 	bool allow_identifier_uses;
 	Array<Ast *> identifier_uses; // only used by 'odin query'
 	Array<Ast *> identifier_uses; // only used by 'odin query'
+
+	// Below are accessed within procedures
+	// NOTE(bill): If the semantic checker (check_proc_body) is to ever to be multithreaded,
+	// these variables will be of contention
+
+	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<Array<Entity *> > gen_procs;       // Key: Ast * | Identifier -> Entity
+	Map<Array<Entity *> > gen_types;       // Key: Type *
+
+	Array<Type *>         type_info_types;
+	Map<isize>            type_info_map;   // Key: Type *
 };
 };
 
 
 struct CheckerContext {
 struct CheckerContext {
@@ -339,11 +344,10 @@ struct Checker {
 	Parser *    parser;
 	Parser *    parser;
 	CheckerInfo info;
 	CheckerInfo info;
 
 
+	CheckerContext builtin_ctx;
+
 	Array<ProcInfo> procs_to_check;
 	Array<ProcInfo> procs_to_check;
 	Array<Entity *> procs_with_deferred_to_check;
 	Array<Entity *> procs_with_deferred_to_check;
-
-	CheckerContext *curr_ctx;
-	CheckerContext init_ctx;
 };
 };
 
 
 
 
@@ -382,7 +386,6 @@ Entity *scope_insert (Scope *s, Entity *entity);
 
 
 
 
 ExprInfo *check_get_expr_info     (CheckerInfo *i, Ast *expr);
 ExprInfo *check_get_expr_info     (CheckerInfo *i, Ast *expr);
-void      check_set_expr_info     (CheckerInfo *i, Ast *expr, ExprInfo info);
 void      check_remove_expr_info  (CheckerInfo *i, Ast *expr);
 void      check_remove_expr_info  (CheckerInfo *i, Ast *expr);
 void      add_untyped             (CheckerInfo *i, Ast *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value);
 void      add_untyped             (CheckerInfo *i, Ast *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value);
 void      add_type_and_value      (CheckerInfo *i, Ast *expression, AddressingMode mode, Type *type, ExactValue value);
 void      add_type_and_value      (CheckerInfo *i, Ast *expression, AddressingMode mode, Type *type, ExactValue value);