aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-03-23 20:48:30 +0000
committergingerBill <bill@gingerbill.org>2018-03-23 20:48:30 +0000
commit30f5a3bb9358ded6a48e8d8ba6f5eb0b3743a807 (patch)
treeebec105ee45307ef11491c3bbb8ec31f2f61df0e /src
parent2e1e1e6034152fa83a05b7fb47e75eefe758ca62 (diff)
Move cycle checking to much earlier on in the semantic stage
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.cpp9
-rw-r--r--src/check_expr.cpp33
-rw-r--r--src/check_stmt.cpp20
-rw-r--r--src/check_type.cpp86
-rw-r--r--src/checker.cpp104
-rw-r--r--src/checker.hpp13
-rw-r--r--src/entity.cpp76
-rw-r--r--src/ir.cpp74
-rw-r--r--src/main.cpp2
-rw-r--r--src/types.cpp19
10 files changed, 259 insertions, 177 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index b16536f70..a2a7a1fb4 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -227,6 +227,8 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) {
error(decl->attributes[0], "Attributes are not allowed on type declarations");
}
+
+
bool is_distinct = is_type_distinct(type_expr);
AstNode *te = remove_type_alias_clutter(type_expr);
e->type = t_invalid;
@@ -238,7 +240,10 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) {
}
e->type = named;
- Type *bt = check_type(c, te, named);
+ check_type_path_push(c, e);
+ Type *bt = check_type_expr(c, te, named);
+ check_type_path_pop(c);
+
named->Named.base = base_type(bt);
if (!is_distinct) {
e->type = bt;
@@ -985,7 +990,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
for_array(i, scope->elements.entries) {
Entity *f = scope->elements.entries[i].value;
if (f->kind == Entity_Variable) {
- Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
+ Entity *uvar = alloc_entity_using_variable(e, f->token, f->type);
uvar->Variable.is_immutable = is_immutable;
if (is_value) uvar->flags |= EntityFlag_Value;
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 4996d7853..12aae53a1 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -55,7 +55,8 @@ void check_multi_expr (Checker *c, Operand *operand, AstNode *
void check_expr_or_type (Checker *c, Operand *operand, AstNode *expression, Type *type_hint = nullptr);
ExprKind check_expr_base (Checker *c, Operand *operand, AstNode *expression, Type *type_hint);
void check_expr_with_type_hint (Checker *c, Operand *o, AstNode *e, Type *t);
-Type * check_type (Checker *c, AstNode *expression, Type *named_type = nullptr);
+Type * check_type (Checker *c, AstNode *expression);
+Type * check_type_expr (Checker *c, AstNode *expression, Type *named_type);
Type * make_optional_ok_type (Type *value);
void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def);
Entity * check_selector (Checker *c, Operand *operand, AstNode *node, Type *type_hint);
@@ -334,7 +335,7 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ
d->proc_lit = proc_lit;
- Entity *entity = make_entity_procedure(c->allocator, nullptr, token, final_proc_type, tags);
+ Entity *entity = alloc_entity_procedure(nullptr, token, final_proc_type, tags);
entity->identifier = ident;
add_entity_and_decl_info(c, ident, entity, d);
@@ -903,6 +904,27 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
return false;
}
+bool check_cycle(Checker *c, Entity *curr, bool report) {
+ if (curr->state != EntityState_InProgress) {
+ return false;
+ }
+ for_array(i, *c->context.type_path) {
+ Entity *prev = (*c->context.type_path)[i];
+ if (prev == curr) {
+ if (report) {
+ error(curr->token, "Illegal declaration cycle of `%.*s`", LIT(curr->token.string));
+ for (isize j = i; j < c->context.type_path->count; j++) {
+ Entity *curr = (*c->context.type_path)[j];
+ error(curr->token, "\t%.*s refers to", LIT(curr->token.string));
+ }
+ error(curr->token, "\t%.*s", LIT(curr->token.string));
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint, bool allow_import_name) {
GB_ASSERT(n->kind == AstNode_Ident);
@@ -1036,6 +1058,9 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
case Entity_TypeName:
o->mode = Addressing_Type;
+ if (check_cycle(c, e, true)) {
+ type = t_invalid;
+ }
break;
case Entity_ImportName:
@@ -3152,8 +3177,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
Type *proc_type_params = alloc_type_tuple(c->allocator);
proc_type_params->Tuple.variables = gb_alloc_array(c->allocator, Entity *, 2);
proc_type_params->Tuple.variable_count = 2;
- proc_type_params->Tuple.variables[0] = make_entity_param(c->allocator, nullptr, blank_token, operand->type, false, false);
- proc_type_params->Tuple.variables[1] = make_entity_param(c->allocator, nullptr, blank_token, slice_elem, false, false);
+ proc_type_params->Tuple.variables[0] = alloc_entity_param(c->allocator, nullptr, blank_token, operand->type, false, false);
+ proc_type_params->Tuple.variables[1] = alloc_entity_param(c->allocator, nullptr, blank_token, slice_elem, false, false);
Type *proc_type = alloc_type_proc(nullptr, proc_type_params, 2, nullptr, false, true, ProcCC_Odin);
check_call_arguments(c, &prev_operand, proc_type, call);
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index ff04fed14..80e5baf37 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -431,7 +431,7 @@ void check_label(Checker *c, AstNode *label) {
}
}
- Entity *e = make_entity_label(c->allocator, c->context.scope, l->name->Ident.token, t_invalid, label);
+ Entity *e = alloc_entity_label(c->context.scope, l->name->Ident.token, t_invalid, label);
add_entity(c, c->context.scope, l->name, e);
e->parent_proc_decl = c->context.curr_proc_decl;
@@ -507,7 +507,7 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
for_array(i, found->elements.entries) {
Entity *f = found->elements.entries[i].value;
if (f->kind == Entity_Variable) {
- Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
+ Entity *uvar = alloc_entity_using_variable(e, f->token, f->type);
uvar->using_expr = expr;
Entity *prev = scope_insert_entity(c->context.scope, uvar);
if (prev != nullptr) {
@@ -1000,7 +1000,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
check_open_scope(c, stmt);
{
- Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, lhs->Ident.token, case_type, false, EntityState_Resolved);
+ Entity *tag_var = alloc_entity_variable(c->context.scope, lhs->Ident.token, case_type, false, EntityState_Resolved);
tag_var->flags |= EntityFlag_Used;
tag_var->flags |= EntityFlag_Value;
add_entity(c, c->context.scope, lhs, tag_var);
@@ -1467,7 +1467,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
if (found == nullptr) {
bool is_immutable = true;
- entity = make_entity_variable(c->allocator, c->context.scope, token, type, is_immutable, EntityState_Resolved);
+ entity = alloc_entity_variable(c->context.scope, token, type, is_immutable, EntityState_Resolved);
add_entity_definition(&c->info, name, entity);
} else {
TokenPos pos = found->token.pos;
@@ -1482,7 +1482,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
if (entity == nullptr) {
- entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name));
+ entity = alloc_entity_dummy_variable(c->global_scope, ast_node_token(name));
}
entities[entity_count++] = entity;
@@ -1700,7 +1700,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
continue;
}
- Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
+ Entity *uvar = alloc_entity_using_variable(e, f->token, f->type);
uvar->using_expr = expr;
Entity *prev = scope_insert_entity(c->context.scope, uvar);
if (prev != nullptr) {
@@ -1797,7 +1797,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
new_name_count += 1;
}
if (found == nullptr) {
- entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false);
+ entity = alloc_entity_variable(c->context.scope, token, nullptr, false);
entity->identifier = name;
AstNode *fl = c->context.foreign_context.curr_library;
@@ -1816,7 +1816,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
}
if (entity == nullptr) {
- entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name));
+ entity = alloc_entity_dummy_variable(c->global_scope, ast_node_token(name));
}
entity->parent_proc_decl = c->context.curr_proc_decl;
entities[entity_count++] = entity;
@@ -1828,7 +1828,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
Type *init_type = nullptr;
if (vd->type != nullptr) {
- init_type = check_type(c, vd->type, nullptr);
+ init_type = check_type(c, vd->type);
if (init_type == nullptr) {
init_type = t_invalid;
} else if (is_type_polymorphic(base_type(init_type))) {
@@ -1938,7 +1938,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
for_array(i, scope->elements.entries) {
Entity *f = scope->elements.entries[i].value;
if (f->kind == Entity_Variable) {
- Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
+ Entity *uvar = alloc_entity_using_variable(e, f->token, f->type);
uvar->Variable.is_immutable = is_immutable;
Entity *prev = scope_insert_entity(c->context.scope, uvar);
if (prev != nullptr) {
diff --git a/src/check_type.cpp b/src/check_type.cpp
index c96269356..c3ee0a51a 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -111,7 +111,7 @@ void check_struct_fields(Checker *c, AstNode *node, Array<Entity *> *fields, Arr
gb_printf_err("Element\n");
}
- type = check_type(c, type_expr);
+ type = check_type_expr(c, type_expr, nullptr);
if (default_value != nullptr) {
Operand o = {};
@@ -179,7 +179,7 @@ void check_struct_fields(Checker *c, AstNode *node, Array<Entity *> *fields, Arr
Token name_token = name->Ident.token;
Entity *field = nullptr;
- field = make_entity_field(c->allocator, c->context.scope, name_token, type, is_using, field_src_index);
+ field = alloc_entity_field(c->context.scope, name_token, type, is_using, field_src_index);
field->Variable.default_value = value;
field->Variable.default_is_nil = default_is_nil;
@@ -211,8 +211,7 @@ void check_struct_fields(Checker *c, AstNode *node, Array<Entity *> *fields, Arr
Entity *make_names_field_for_struct(Checker *c, Scope *scope) {
- Entity *e = make_entity_field(c->allocator, scope,
- make_token_ident(str_lit("names")), t_string_slice, false, 0);
+ Entity *e = alloc_entity_field(scope, make_token_ident(str_lit("names")), t_string_slice, false, 0);
e->Variable.is_immutable = true;
e->flags |= EntityFlag_TypeField;
return e;
@@ -311,7 +310,7 @@ void add_polymorphic_struct_entity(Checker *c, AstNode *node, Type *named_type,
node->kind = AstNode_Ident;
node->Ident.token = token;
- e = make_entity_type_name(a, s, token, named_type);
+ e = alloc_entity_type_name(s, token, named_type);
e->state = EntityState_Resolved;
add_entity_use(c, node, e);
}
@@ -454,18 +453,18 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
is_polymorphic = true;
can_check_fields = false;
}
- e = make_entity_type_name(c->allocator, scope, token, operand.type);
+ e = alloc_entity_type_name(scope, token, operand.type);
e->TypeName.is_type_alias = true;
} else {
GB_ASSERT(operand.mode == Addressing_Constant);
- e = make_entity_constant(c->allocator, scope, token, operand.type, operand.value);
+ e = alloc_entity_constant(scope, token, operand.type, operand.value);
}
} else {
if (is_type_param) {
- e = make_entity_type_name(c->allocator, scope, token, type);
+ e = alloc_entity_type_name(scope, token, type);
e->TypeName.is_type_alias = true;
} else {
- e = make_entity_constant(c->allocator, scope, token, type, empty_exact_value);
+ e = alloc_entity_constant(scope, token, type, empty_exact_value);
}
}
@@ -551,7 +550,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
for_array(i, ut->variants) {
AstNode *node = ut->variants[i];
- Type *t = check_type(c, node);
+ Type *t = check_type_expr(c, node, nullptr);
if (t != nullptr && t != t_invalid) {
bool ok = true;
t = default_type(t);
@@ -697,7 +696,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
max_value = iota;
}
- Entity *e = make_entity_constant(c->allocator, c->context.scope, ident->Ident.token, constant_type, iota);
+ Entity *e = alloc_entity_constant(c->context.scope, ident->Ident.token, constant_type, iota);
e->identifier = ident;
e->flags |= EntityFlag_Visited;
e->state = EntityState_Resolved;
@@ -732,12 +731,10 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
}
}
- enum_type->Enum.count = make_entity_constant(c->allocator, c->context.scope,
- make_token_ident(str_lit("count")), t_int, exact_value_i64(fields.count));
- enum_type->Enum.min_value = make_entity_constant(c->allocator, c->context.scope,
- make_token_ident(str_lit("min_value")), constant_type, min_value);
- enum_type->Enum.max_value = make_entity_constant(c->allocator, c->context.scope,
- make_token_ident(str_lit("max_value")), constant_type, max_value);
+ Scope *s = c->context.scope;
+ enum_type->Enum.count = alloc_entity_constant(s, make_token_ident(str_lit("count")), t_int, exact_value_i64(fields.count));
+ enum_type->Enum.min_value = alloc_entity_constant(s, make_token_ident(str_lit("min_value")), constant_type, min_value);
+ enum_type->Enum.max_value = alloc_entity_constant(s, make_token_ident(str_lit("max_value")), constant_type, max_value);
enum_type->Enum.names = make_names_field_for_struct(c, c->context.scope);
}
@@ -789,7 +786,7 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, AstNode *node) {
u32 bits = cast(u32)bits_;
Type *value_type = alloc_type_bit_field_value(bits);
- Entity *e = make_entity_variable(c->allocator, bit_field_type->BitField.scope, ident->Ident.token, value_type, false);
+ Entity *e = alloc_entity_variable(bit_field_type->BitField.scope, ident->Ident.token, value_type, false);
e->identifier = ident;
e->flags |= EntityFlag_BitFieldValue;
@@ -1184,7 +1181,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
type = t_invalid;
}
}
- param = make_entity_type_name(c->allocator, scope, name->Ident.token, type, EntityState_Resolved);
+ param = alloc_entity_type_name(scope, name->Ident.token, type, EntityState_Resolved);
param->TypeName.is_type_alias = true;
} else {
if (operands != nullptr && variables.count < operands->count) {
@@ -1207,7 +1204,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
}
}
- param = make_entity_param(c->allocator, scope, name->Ident.token, type, is_using, is_in);
+ param = alloc_entity_param(scope, name->Ident.token, type, is_using, is_in);
param->Variable.default_value = value;
param->Variable.default_is_nil = default_is_nil;
param->Variable.default_is_location = default_is_location;
@@ -1336,7 +1333,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) {
if (field->names.count == 0) {
Token token = ast_node_token(field->type);
token.string = str_lit("");
- Entity *param = make_entity_param(c->allocator, scope, token, type, false, false);
+ Entity *param = alloc_entity_param(scope, token, type, false, false);
param->Variable.default_value = value;
param->Variable.default_is_nil = default_is_nil;
array_add(&variables, param);
@@ -1359,7 +1356,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) {
error(name, "Result value cannot be a blank identifer `_`");
}
- Entity *param = make_entity_param(c->allocator, scope, token, type, false, false);
+ Entity *param = alloc_entity_param(scope, token, type, false, false);
param->flags |= EntityFlag_Result;
param->Variable.default_value = value;
param->Variable.default_is_nil = default_is_nil;
@@ -1542,7 +1539,7 @@ Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) {
if (new_type != original_type) {
Type *tuple = alloc_type_tuple();
auto variables = array_make<Entity *>(a, 0, 1);
- array_add(&variables, make_entity_param(a, original_type->Tuple.variables[0]->scope, empty_token, new_type, false, false));
+ array_add(&variables, alloc_entity_param(original_type->Tuple.variables[0]->scope, empty_token, new_type, false, false));
tuple->Tuple.variables = variables;
new_type = tuple;
}
@@ -1732,8 +1729,8 @@ Type *make_optional_ok_type(Type *value) {
bool typed = true;
Type *t = alloc_type_tuple();
array_init(&t->Tuple.variables, a, 0, 2);
- array_add (&t->Tuple.variables, make_entity_field(a, nullptr, blank_token, value, false, 0));
- array_add (&t->Tuple.variables, make_entity_field(a, nullptr, blank_token, typed ? t_bool : t_untyped_bool, false, 1));
+ array_add (&t->Tuple.variables, alloc_entity_field(nullptr, blank_token, value, false, 0));
+ array_add (&t->Tuple.variables, alloc_entity_field(nullptr, blank_token, typed ? t_bool : t_untyped_bool, false, 1));
return t;
}
@@ -1759,9 +1756,9 @@ void init_map_entry_type(Type *type) {
Scope *s = create_scope(universal_scope, a);
auto fields = array_make<Entity *>(a, 0, 3);
- array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("key")), t_map_key, false, 0, EntityState_Resolved));
- array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("next")), t_int, false, 1, EntityState_Resolved));
- array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("value")), type->Map.value, false, 2, EntityState_Resolved));
+ array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("key")), t_map_key, false, 0, EntityState_Resolved));
+ array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("next")), t_int, false, 1, EntityState_Resolved));
+ array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("value")), type->Map.value, false, 2, EntityState_Resolved));
entry_type->Struct.fields = fields;
@@ -1799,8 +1796,8 @@ void init_map_internal_types(Type *type) {
auto fields = array_make<Entity *>(a, 0, 2);
- array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("hashes")), hashes_type, false, 0, EntityState_Resolved));
- array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("entries")), entries_type, false, 1, EntityState_Resolved));
+ array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("hashes")), hashes_type, false, 0, EntityState_Resolved));
+ array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("entries")), entries_type, false, 1, EntityState_Resolved));
generated_struct_type->Struct.fields = fields;
@@ -1837,6 +1834,8 @@ void check_map_type(Checker *c, Type *type, AstNode *node) {
// error(node, "'map' types are not yet implemented");
}
+
+
bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) {
GB_ASSERT_NOT_NULL(type);
if (e == nullptr) {
@@ -1846,7 +1845,6 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
switch (e->kind) {
case_ast_node(i, Ident, e);
-
Operand o = {};
Entity *entity = check_ident(c, &o, e, named_type, nullptr, false);
@@ -1867,9 +1865,15 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
}
}
- if (c->context.type_level == 0 && entity->state == EntityState_InProgress) {
- error(e, "Illegal declaration cycle of `%.*s`", LIT(entity->token.string));
- }
+ // if (c->context.type_level == 0 && entity->state == EntityState_InProgress) {
+ // error(entity->token, "Illegal declaration cycle of `%.*s`", LIT(entity->token.string));
+ // for_array(j, *c->context.type_path) {
+ // Entity *k = (*c->context.type_path)[j];
+ // error(k->token, "\t%.*s refers to", LIT(k->token.string));
+ // }
+ // error(entity->token, "\t%.*s", LIT(entity->token.string));
+ // *type = t_invalid;
+ // }
return true;
}
@@ -1927,7 +1931,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
GB_ASSERT(is_scope_an_ancestor(ps, s) >= 0);
entity_scope = ps;
}
- Entity *e = make_entity_type_name(c->allocator, entity_scope, token, t);
+ Entity *e = alloc_entity_type_name(entity_scope, token, t);
e->TypeName.is_type_alias = true;
e->state = EntityState_Resolved;
add_entity(c, ps, ident, e);
@@ -1968,7 +1972,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
case_end;
case_ast_node(pe, ParenExpr, e);
- *type = check_type(c, pe->expr, named_type);
+ *type = check_type_expr(c, pe->expr, named_type);
set_base_type(named_type, *type);
return true;
case_end;
@@ -2000,7 +2004,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
error(at->count, "... can only be used in conjuction with compound literals");
count = 0;
}
- Type *elem = check_type(c, at->elem, nullptr);
+ Type *elem = check_type_expr(c, at->elem, nullptr);
*type = alloc_type_array(elem, count, generic_type);
} else {
Type *elem = check_type(c, at->elem);
@@ -2117,9 +2121,15 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
return false;
}
+Type *check_type(Checker *c, AstNode *e) {
+ auto prev_context = c->context; defer (c->context = prev_context);
+ c->context.type_path = new_checker_type_path();
+ defer (destroy_checker_type_path(c->context.type_path));
+ return check_type_expr(c, e, nullptr);
+}
-Type *check_type(Checker *c, AstNode *e, Type *named_type) {
+Type *check_type_expr(Checker *c, AstNode *e, Type *named_type) {
Type *type = nullptr;
bool ok = check_type_internal(c, e, &type, named_type);
diff --git a/src/checker.cpp b/src/checker.cpp
index df0db1333..70ad8e4b6 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -507,20 +507,20 @@ Entity *add_global_entity(Entity *entity) {
return entity;
}
-void add_global_constant(gbAllocator a, String name, Type *type, ExactValue value) {
- Entity *entity = alloc_entity(a, Entity_Constant, nullptr, make_token_ident(name), type);
+void add_global_constant(String name, Type *type, ExactValue value) {
+ Entity *entity = alloc_entity(Entity_Constant, nullptr, make_token_ident(name), type);
entity->Constant.value = value;
add_global_entity(entity);
}
-void add_global_string_constant(gbAllocator a, String name, String value) {
- add_global_constant(a, name, t_untyped_string, exact_value_string(value));
+void add_global_string_constant(String name, String value) {
+ add_global_constant(name, t_untyped_string, exact_value_string(value));
}
-void add_global_type_entity(gbAllocator a, String name, Type *type) {
- add_global_entity(make_entity_type_name(a, nullptr, make_token_ident(name), type));
+void add_global_type_entity(String name, Type *type) {
+ add_global_entity(alloc_entity_type_name(nullptr, make_token_ident(name), type));
}
@@ -533,27 +533,27 @@ void init_universal_scope(void) {
// Types
for (isize i = 0; i < gb_count_of(basic_types); i++) {
- add_global_type_entity(a, basic_types[i].Basic.name, &basic_types[i]);
+ add_global_type_entity(basic_types[i].Basic.name, &basic_types[i]);
}
- add_global_type_entity(a, str_lit("byte"), &basic_types[Basic_u8]);
+ add_global_type_entity(str_lit("byte"), &basic_types[Basic_u8]);
// Constants
- add_global_constant(a, str_lit("true"), t_untyped_bool, exact_value_bool(true));
- add_global_constant(a, str_lit("false"), t_untyped_bool, exact_value_bool(false));
+ add_global_constant(str_lit("true"), t_untyped_bool, exact_value_bool(true));
+ add_global_constant(str_lit("false"), t_untyped_bool, exact_value_bool(false));
- add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil));
- add_global_entity(make_entity_library_name(a, universal_scope,
- make_token_ident(str_lit("__llvm_core")), t_invalid,
- str_lit(""), str_lit("__llvm_core")));
+ add_global_entity(alloc_entity_nil(str_lit("nil"), t_untyped_nil));
+ add_global_entity(alloc_entity_library_name(universal_scope,
+ make_token_ident(str_lit("__llvm_core")), t_invalid,
+ str_lit(""), str_lit("__llvm_core")));
// TODO(bill): Set through flags in the compiler
- add_global_string_constant(a, str_lit("ODIN_OS"), bc->ODIN_OS);
- add_global_string_constant(a, str_lit("ODIN_ARCH"), bc->ODIN_ARCH);
- add_global_string_constant(a, str_lit("ODIN_ENDIAN"), bc->ODIN_ENDIAN);
- add_global_string_constant(a, str_lit("ODIN_VENDOR"), bc->ODIN_VENDOR);
- add_global_string_constant(a, str_lit("ODIN_VERSION"), bc->ODIN_VERSION);
- add_global_string_constant(a, str_lit("ODIN_ROOT"), bc->ODIN_ROOT);
- add_global_constant(a, str_lit("ODIN_DEBUG"), t_untyped_bool, exact_value_bool(bc->ODIN_DEBUG));
+ add_global_string_constant(str_lit("ODIN_OS"), bc->ODIN_OS);
+ add_global_string_constant(str_lit("ODIN_ARCH"), bc->ODIN_ARCH);
+ add_global_string_constant(str_lit("ODIN_ENDIAN"), bc->ODIN_ENDIAN);
+ add_global_string_constant(str_lit("ODIN_VENDOR"), bc->ODIN_VENDOR);
+ add_global_string_constant(str_lit("ODIN_VERSION"), bc->ODIN_VERSION);
+ add_global_string_constant(str_lit("ODIN_ROOT"), bc->ODIN_ROOT);
+ add_global_constant(str_lit("ODIN_DEBUG"), t_untyped_bool, exact_value_bool(bc->ODIN_DEBUG));
// Builtin Procedures
@@ -561,7 +561,7 @@ void init_universal_scope(void) {
BuiltinProcId id = cast(BuiltinProcId)i;
String name = builtin_procs[i].name;
if (name != "") {
- Entity *entity = alloc_entity(a, Entity_Builtin, nullptr, make_token_ident(name), t_invalid);
+ Entity *entity = alloc_entity(Entity_Builtin, nullptr, make_token_ident(name), t_invalid);
entity->Builtin.id = id;
add_global_entity(entity);
}
@@ -639,12 +639,17 @@ void init_checker(Checker *c, Parser *parser) {
c->tmp_allocator = gb_arena_allocator(&c->tmp_arena);
c->global_scope = create_scope(universal_scope, c->allocator);
- c->context.scope = c->global_scope;
map_init(&c->file_scopes, heap_allocator());
ptr_set_init(&c->checked_files, heap_allocator());
array_init(&c->file_order, heap_allocator(), 0, c->parser->files.count);
+
+ // Init context
+ c->context.scope = c->global_scope;
+
+ c->context.type_path = new_checker_type_path();
+ c->context.type_level = 0;
}
void destroy_checker(Checker *c) {
@@ -660,6 +665,8 @@ void destroy_checker(Checker *c) {
map_destroy(&c->file_scopes);
ptr_set_destroy(&c->checked_files);
array_free(&c->file_order);
+
+ destroy_checker_type_path(c->context.type_path);
}
@@ -1312,6 +1319,31 @@ Type *find_core_type(Checker *c, String name) {
return e->type;
}
+CheckerTypePath *new_checker_type_path() {
+ gbAllocator a = heap_allocator();
+ auto *tp = gb_alloc_item(a, CheckerTypePath);
+ array_init(tp, a, 0, 16);
+ return tp;
+}
+
+void destroy_checker_type_path(CheckerTypePath *tp) {
+ array_free(tp);
+ gb_free(heap_allocator(), tp);
+}
+
+
+void check_type_path_push(Checker *c, Entity *e) {
+ GB_ASSERT(c->context.type_path != nullptr);
+ GB_ASSERT(e != nullptr);
+ array_add(c->context.type_path, e);
+}
+Entity *check_type_path_pop(Checker *c) {
+ GB_ASSERT(c->context.type_path != nullptr);
+ return array_pop(c->context.type_path);
+}
+
+
+
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type);
@@ -1424,9 +1456,9 @@ void init_preload(Checker *c) {
Entity *type_info_entity = find_core_entity(c, str_lit("Type_Info"));
Scope *preload_scope = type_info_entity->scope;
- Entity *e = make_entity_import_name(c->allocator, preload_scope, make_token_ident(_global), t_invalid,
- str_lit(""), _global,
- preload_scope);
+ Entity *e = alloc_entity_import_name(preload_scope, make_token_ident(_global), t_invalid,
+ str_lit(""), _global,
+ preload_scope);
add_entity(c, universal_scope, nullptr, e);
}
@@ -1745,7 +1777,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
continue;
}
- Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident.token, nullptr, false);
+ Entity *e = alloc_entity_variable(c->context.scope, name->Ident.token, nullptr, false);
e->identifier = name;
if (vd->is_using) {
@@ -1808,7 +1840,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
if (is_ast_node_type(init) ||
(vd->type != nullptr && vd->type->kind == AstNode_TypeType)) {
- e = make_entity_type_name(c->allocator, d->scope, token, nullptr);
+ e = alloc_entity_type_name(d->scope, token, nullptr);
if (vd->type != nullptr) {
error(name, "A type declaration cannot have an type parameter");
}
@@ -1820,7 +1852,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
continue;
}
ast_node(pl, ProcLit, init);
- e = make_entity_procedure(c->allocator, d->scope, token, nullptr, pl->tags);
+ e = alloc_entity_procedure(d->scope, token, nullptr, pl->tags);
if (fl != nullptr) {
GB_ASSERT(fl->kind == AstNode_Ident);
e->Procedure.foreign_library_ident = fl;
@@ -1846,13 +1878,13 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
d->type_expr = pl->type;
} else if (init->kind == AstNode_ProcGroup) {
ast_node(pg, ProcGroup, init);
- e = make_entity_proc_group(c->allocator, d->scope, token, nullptr);
+ e = alloc_entity_proc_group(d->scope, token, nullptr);
if (fl != nullptr) {
error(name, "Procedure groups are not allowed within a foreign block");
}
d->init_expr = init;
} else {
- e = make_entity_constant(c->allocator, d->scope, token, nullptr, empty_exact_value);
+ e = alloc_entity_constant(d->scope, token, nullptr, empty_exact_value);
d->type_expr = vd->type;
d->init_expr = init;
}
@@ -2340,9 +2372,9 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) {
} else {
GB_ASSERT(id->import_name.pos.line != 0);
id->import_name.string = import_name;
- Entity *e = make_entity_import_name(c->allocator, parent_scope, id->import_name, t_invalid,
- id->fullpath, id->import_name.string,
- scope);
+ Entity *e = alloc_entity_import_name(parent_scope, id->import_name, t_invalid,
+ id->fullpath, id->import_name.string,
+ scope);
add_entity(c, parent_scope, nullptr, e);
}
@@ -2524,8 +2556,8 @@ void check_add_foreign_import_decl(Checker *c, AstNode *decl) {
GB_ASSERT(fl->library_name.pos.line != 0);
fl->library_name.string = library_name;
- Entity *e = make_entity_library_name(c->allocator, parent_scope, fl->library_name, t_invalid,
- fl->fullpath, library_name);
+ Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid,
+ fl->fullpath, library_name);
add_entity(c, parent_scope, nullptr, e);
}
diff --git a/src/checker.hpp b/src/checker.hpp
index 172768835..ff930667d 100644
--- a/src/checker.hpp
+++ b/src/checker.hpp
@@ -262,19 +262,23 @@ struct ForeignContext {
bool in_export;
};
+typedef Array<Entity *> CheckerTypePath;
+
struct CheckerContext {
Scope * file_scope;
Scope * scope;
DeclInfo * decl;
u32 stmt_state_flags;
bool in_defer; // TODO(bill): Actually handle correctly
- isize type_level; // TODO(bill): Actually handle correctly
String proc_name;
Type * type_hint;
DeclInfo * curr_proc_decl;
Type * curr_proc_sig;
ForeignContext foreign_context;
+ CheckerTypePath *type_path;
+ isize type_level; // TODO(bill): Actually handle correctly
+
bool collect_delayed_decls;
bool allow_polymorphic_types;
bool no_polymorphic_errors;
@@ -382,7 +386,6 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes);
void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws);
void check_delayed_file_import_entity(Checker *c, AstNode *decl);
-
struct AttributeContext {
String link_name;
String link_prefix;
@@ -401,3 +404,9 @@ AttributeContext make_attribute_context(String link_prefix) {
typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc);
void check_decl_attributes(Checker *c, Array<AstNode *> attributes, DeclAttributeProc *proc, AttributeContext *ac);
+
+CheckerTypePath *new_checker_type_path();
+void destroy_checker_type_path(CheckerTypePath *tp);
+
+void check_type_path_push(Checker *c, Entity *e);
+Entity *check_type_path_pop (Checker *c);
diff --git a/src/entity.cpp b/src/entity.cpp
index 5dcb3ff7b..182df8c05 100644
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -177,7 +177,8 @@ bool is_entity_exported(Entity *e) {
gb_global u64 global_entity_id = 0;
-Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, Type *type) {
+Entity *alloc_entity(EntityKind kind, Scope *scope, Token token, Type *type) {
+ gbAllocator a = heap_allocator();
Entity *entity = gb_alloc_item(a, Entity);
entity->kind = kind;
entity->state = EntityState_Unresolved;
@@ -188,17 +189,17 @@ Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token,
return entity;
}
-Entity *make_entity_variable(gbAllocator a, Scope *scope, Token token, Type *type, bool is_immutable, EntityState state = EntityState_Unresolved) {
- Entity *entity = alloc_entity(a, Entity_Variable, scope, token, type);
+Entity *alloc_entity_variable(Scope *scope, Token token, Type *type, bool is_immutable, EntityState state = EntityState_Unresolved) {
+ Entity *entity = alloc_entity(Entity_Variable, scope, token, type);
entity->Variable.is_immutable = is_immutable;
entity->state = state;
return entity;
}
-Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, Type *type) {
+Entity *alloc_entity_using_variable(Entity *parent, Token token, Type *type) {
GB_ASSERT(parent != nullptr);
token.pos = parent->token.pos;
- Entity *entity = alloc_entity(a, Entity_Variable, parent->scope, token, type);
+ Entity *entity = alloc_entity(Entity_Variable, parent->scope, token, type);
entity->using_parent = parent;
entity->parent_proc_decl = parent->parent_proc_decl;
entity->flags |= EntityFlag_Using;
@@ -208,21 +209,21 @@ Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, T
}
-Entity *make_entity_constant(gbAllocator a, Scope *scope, Token token, Type *type, ExactValue value) {
- Entity *entity = alloc_entity(a, Entity_Constant, scope, token, type);
+Entity *alloc_entity_constant(Scope *scope, Token token, Type *type, ExactValue value) {
+ Entity *entity = alloc_entity(Entity_Constant, scope, token, type);
entity->Constant.value = value;
return entity;
}
-Entity *make_entity_type_name(gbAllocator a, Scope *scope, Token token, Type *type, EntityState state = EntityState_Unresolved) {
- Entity *entity = alloc_entity(a, Entity_TypeName, scope, token, type);
+Entity *alloc_entity_type_name(Scope *scope, Token token, Type *type, EntityState state = EntityState_Unresolved) {
+ Entity *entity = alloc_entity(Entity_TypeName, scope, token, type);
entity->state = state;
return entity;
}
-Entity *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type, bool is_using, bool is_value) {
+Entity *alloc_entity_param(Scope *scope, Token token, Type *type, bool is_using, bool is_value) {
bool is_immutable = false;
- Entity *entity = make_entity_variable(a, scope, token, type, is_immutable);
+ Entity *entity = alloc_entity_variable(scope, token, type, is_immutable);
entity->flags |= EntityFlag_Used;
entity->flags |= EntityFlag_Param;
entity->state = EntityState_Resolved;
@@ -232,8 +233,8 @@ Entity *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type,
}
-Entity *make_entity_const_param(gbAllocator a, Scope *scope, Token token, Type *type, ExactValue value, bool poly_const) {
- Entity *entity = make_entity_constant(a, scope, token, type, value);
+Entity *alloc_entity_const_param(Scope *scope, Token token, Type *type, ExactValue value, bool poly_const) {
+ Entity *entity = alloc_entity_constant(scope, token, type, value);
entity->flags |= EntityFlag_Used;
if (poly_const) entity->flags |= EntityFlag_PolyConst;
entity->flags |= EntityFlag_Param;
@@ -241,8 +242,8 @@ Entity *make_entity_const_param(gbAllocator a, Scope *scope, Token token, Type *
}
-Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type, bool is_using, i32 field_src_index, EntityState state = EntityState_Unresolved) {
- Entity *entity = make_entity_variable(a, scope, token, type, false);
+Entity *alloc_entity_field(Scope *scope, Token token, Type *type, bool is_using, i32 field_src_index, EntityState state = EntityState_Unresolved) {
+ Entity *entity = alloc_entity_variable(scope, token, type, false);
entity->Variable.field_src_index = field_src_index;
entity->Variable.field_index = field_src_index;
if (is_using) entity->flags |= EntityFlag_Using;
@@ -251,8 +252,8 @@ Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type,
return entity;
}
-Entity *make_entity_array_elem(gbAllocator a, Scope *scope, Token token, Type *type, i32 field_src_index) {
- Entity *entity = make_entity_variable(a, scope, token, type, false);
+Entity *alloc_entity_array_elem(Scope *scope, Token token, Type *type, i32 field_src_index) {
+ Entity *entity = alloc_entity_variable(scope, token, type, false);
entity->Variable.field_src_index = field_src_index;
entity->Variable.field_index = field_src_index;
entity->flags |= EntityFlag_Field;
@@ -261,34 +262,34 @@ Entity *make_entity_array_elem(gbAllocator a, Scope *scope, Token token, Type *t
return entity;
}
-Entity *make_entity_procedure(gbAllocator a, Scope *scope, Token token, Type *signature_type, u64 tags) {
- Entity *entity = alloc_entity(a, Entity_Procedure, scope, token, signature_type);
+Entity *alloc_entity_procedure(Scope *scope, Token token, Type *signature_type, u64 tags) {
+ Entity *entity = alloc_entity(Entity_Procedure, scope, token, signature_type);
entity->Procedure.tags = tags;
return entity;
}
-Entity *make_entity_proc_group(gbAllocator a, Scope *scope, Token token, Type *type) {
- Entity *entity = alloc_entity(a, Entity_ProcGroup, scope, token, type);
+Entity *alloc_entity_proc_group(Scope *scope, Token token, Type *type) {
+ Entity *entity = alloc_entity(Entity_ProcGroup, scope, token, type);
return entity;
}
-Entity *make_entity_builtin(gbAllocator a, Scope *scope, Token token, Type *type, i32 id) {
- Entity *entity = alloc_entity(a, Entity_Builtin, scope, token, type);
+Entity *alloc_entity_builtin(Scope *scope, Token token, Type *type, i32 id) {
+ Entity *entity = alloc_entity(Entity_Builtin, scope, token, type);
entity->Builtin.id = id;
entity->state = EntityState_Resolved;
return entity;
}
-Entity *make_entity_alias(gbAllocator a, Scope *scope, Token token, Type *type, Entity *base) {
- Entity *entity = alloc_entity(a, Entity_Alias, scope, token, type);
+Entity *alloc_entity_alias(Scope *scope, Token token, Type *type, Entity *base) {
+ Entity *entity = alloc_entity(Entity_Alias, scope, token, type);
entity->Alias.base = base;
return entity;
}
-Entity *make_entity_import_name(gbAllocator a, Scope *scope, Token token, Type *type,
- String path, String name, Scope *import_scope) {
- Entity *entity = alloc_entity(a, Entity_ImportName, scope, token, type);
+Entity *alloc_entity_import_name(Scope *scope, Token token, Type *type,
+ String path, String name, Scope *import_scope) {
+ Entity *entity = alloc_entity(Entity_ImportName, scope, token, type);
entity->ImportName.path = path;
entity->ImportName.name = name;
entity->ImportName.scope = import_scope;
@@ -296,9 +297,9 @@ Entity *make_entity_import_name(gbAllocator a, Scope *scope, Token token, Type *
return entity;
}
-Entity *make_entity_library_name(gbAllocator a, Scope *scope, Token token, Type *type,
- String path, String name) {
- Entity *entity = alloc_entity(a, Entity_LibraryName, scope, token, type);
+Entity *alloc_entity_library_name(Scope *scope, Token token, Type *type,
+ String path, String name) {
+ Entity *entity = alloc_entity(Entity_LibraryName, scope, token, type);
entity->LibraryName.path = path;
entity->LibraryName.name = name;
entity->state = EntityState_Resolved; // TODO(bill): Is this correct?
@@ -309,21 +310,20 @@ Entity *make_entity_library_name(gbAllocator a, Scope *scope, Token token, Type
-Entity *make_entity_nil(gbAllocator a, String name, Type *type) {
- Entity *entity = alloc_entity(a, Entity_Nil, nullptr, make_token_ident(name), type);
+Entity *alloc_entity_nil(String name, Type *type) {
+ Entity *entity = alloc_entity(Entity_Nil, nullptr, make_token_ident(name), type);
return entity;
}
-Entity *make_entity_label(gbAllocator a, Scope *scope, Token token, Type *type,
- AstNode *node) {
- Entity *entity = alloc_entity(a, Entity_Label, scope, token, type);
+Entity *alloc_entity_label(Scope *scope, Token token, Type *type, AstNode *node) {
+ Entity *entity = alloc_entity(Entity_Label, scope, token, type);
entity->Label.node = node;
entity->state = EntityState_Resolved;
return entity;
}
-Entity *make_entity_dummy_variable(gbAllocator a, Scope *scope, Token token) {
+Entity *alloc_entity_dummy_variable(Scope *scope, Token token) {
token.string = str_lit("_");
- return make_entity_variable(a, scope, token, nullptr, false);
+ return alloc_entity_variable(scope, token, nullptr, false);
}
diff --git a/src/ir.cpp b/src/ir.cpp
index ed61da4af..9ed06a617 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1206,10 +1206,7 @@ irValue *ir_generate_array(irModule *m, Type *elem_type, i64 count, String prefi
String s = make_string_c(text);
- Entity *e = make_entity_variable(a, nullptr,
- make_token_ident(s),
- alloc_type_array(elem_type, count),
- false);
+ Entity *e = alloc_entity_variable(nullptr, make_token_ident(s), alloc_type_array(elem_type, count), false);
irValue *value = ir_value_global(a, e, nullptr);
value->Global.is_private = true;
ir_module_add_value(m, e, value);
@@ -1308,7 +1305,7 @@ irValue *ir_add_module_constant(irModule *m, Type *type, ExactValue value) {
String name = make_string(str, len-1);
- Entity *e = make_entity_constant(a, nullptr, make_token_ident(name), t, value);
+ Entity *e = alloc_entity_constant(nullptr, make_token_ident(name), t, value);
irValue *g = ir_value_global(a, e, backing_array);
ir_module_add_value(m, e, g);
map_set(&m->members, hash_string(name), g);
@@ -1335,7 +1332,7 @@ irValue *ir_add_global_string_array(irModule *m, String string) {
token.string = name;
Type *type = alloc_type_array(t_u8, string.len+1);
ExactValue ev = exact_value_string(string);
- Entity *entity = make_entity_constant(a, nullptr, token, type, ev);
+ Entity *entity = alloc_entity_constant(nullptr, token, type, ev);
irValue *g = ir_value_global(a, entity, ir_add_module_constant(m, type, ev));
g->Global.is_private = true;
g->Global.is_unnamed_addr = true;
@@ -1429,10 +1426,7 @@ irValue *ir_add_local_generated(irProcedure *proc, Type *type, bool zero_initial
if (proc->curr_block) {
scope = proc->curr_block->scope;
}
- Entity *e = make_entity_variable(proc->module->allocator,
- scope,
- empty_token,
- type, false);
+ Entity *e = alloc_entity_variable(scope, empty_token, type, false);
return ir_add_local(proc, e, nullptr, zero_initialized);
}
@@ -1450,11 +1444,7 @@ irValue *ir_add_global_generated(irModule *m, Type *type, irValue *value) {
String name = make_string(str, len-1);
Scope *scope = nullptr;
- Entity *e = make_entity_variable(a,
- scope,
- make_token_ident(name),
- type, false);
-
+ Entity *e = alloc_entity_variable(scope, make_token_ident(name), type, false);
irValue *g = ir_value_global(a, e, value);
ir_module_add_value(m, e, g);
map_set(&m->members, hash_string(name), g);
@@ -7389,7 +7379,7 @@ void ir_begin_procedure_body(irProcedure *proc) {
if (proc->type->Proc.return_by_pointer) {
// NOTE(bill): this must be the first parameter stored
Type *ptr_type = alloc_type_pointer(reduce_tuple_to_single_type(proc->type->Proc.results));
- Entity *e = make_entity_param(a, nullptr, make_token_ident(str_lit("agg.result")), ptr_type, false, false);
+ Entity *e = alloc_entity_param(nullptr, make_token_ident(str_lit("agg.result")), ptr_type, false, false);
e->flags |= EntityFlag_Sret | EntityFlag_NoAlias;
irValue *param = ir_value_param(a, proc, e, ptr_type);
@@ -7472,7 +7462,7 @@ void ir_begin_procedure_body(irProcedure *proc) {
if (proc->type->Proc.calling_convention == ProcCC_Odin) {
- Entity *e = make_entity_param(a, nullptr, make_token_ident(str_lit("__.context_ptr")), t_context_ptr, false, false);
+ Entity *e = alloc_entity_param(nullptr, make_token_ident(str_lit("__.context_ptr")), t_context_ptr, false, false);
e->flags |= EntityFlag_NoAlias;
irValue *param = ir_value_param(a, proc, e, e->type);
ir_module_add_value(proc->module, e, param);
@@ -7633,7 +7623,7 @@ void ir_init_module(irModule *m, Checker *c) {
isize max_type_info_count = m->info->type_info_types.count;
String name = str_lit(IR_TYPE_INFO_DATA_NAME);
- Entity *e = make_entity_variable(m->allocator, nullptr, make_token_ident(name), alloc_type_array(t_type_info, max_type_info_count), false);
+ Entity *e = alloc_entity_variable(nullptr, make_token_ident(name), alloc_type_array(t_type_info, max_type_info_count), false);
irValue *g = ir_value_global(m->allocator, e, nullptr);
g->Global.is_private = true;
ir_module_add_value(m, e, g);
@@ -7664,8 +7654,8 @@ void ir_init_module(irModule *m, Checker *c) {
{
String name = str_lit(IR_TYPE_INFO_TYPES_NAME);
- Entity *e = make_entity_variable(m->allocator, nullptr, make_token_ident(name),
- alloc_type_array(t_type_info_ptr, count), false);
+ Entity *e = alloc_entity_variable(nullptr, make_token_ident(name),
+ alloc_type_array(t_type_info_ptr, count), false);
irValue *g = ir_value_global(m->allocator, e, nullptr);
ir_module_add_value(m, e, g);
map_set(&m->members, hash_string(name), g);
@@ -7673,8 +7663,8 @@ void ir_init_module(irModule *m, Checker *c) {
}
{
String name = str_lit(IR_TYPE_INFO_NAMES_NAME);
- Entity *e = make_entity_variable(m->allocator, nullptr, make_token_ident(name),
- alloc_type_array(t_string, count), false);
+ Entity *e = alloc_entity_variable(nullptr, make_token_ident(name),
+ alloc_type_array(t_string, count), false);
irValue *g = ir_value_global(m->allocator, e, nullptr);
ir_module_add_value(m, e, g);
map_set(&m->members, hash_string(name), g);
@@ -7682,8 +7672,8 @@ void ir_init_module(irModule *m, Checker *c) {
}
{
String name = str_lit(IR_TYPE_INFO_OFFSETS_NAME);
- Entity *e = make_entity_variable(m->allocator, nullptr, make_token_ident(name),
- alloc_type_array(t_uintptr, count), false);
+ Entity *e = alloc_entity_variable(nullptr, make_token_ident(name),
+ alloc_type_array(t_uintptr, count), false);
irValue *g = ir_value_global(m->allocator, e, nullptr);
ir_module_add_value(m, e, g);
map_set(&m->members, hash_string(name), g);
@@ -7692,8 +7682,8 @@ void ir_init_module(irModule *m, Checker *c) {
{
String name = str_lit(IR_TYPE_INFO_USINGS_NAME);
- Entity *e = make_entity_variable(m->allocator, nullptr, make_token_ident(name),
- alloc_type_array(t_bool, count), false);
+ Entity *e = alloc_entity_variable(nullptr, make_token_ident(name),
+ alloc_type_array(t_bool, count), false);
irValue *g = ir_value_global(m->allocator, e, nullptr);
ir_module_add_value(m, e, g);
map_set(&m->members, hash_string(name), g);
@@ -8487,12 +8477,12 @@ void ir_gen_tree(irGen *s) {
array_init(&proc_params->Tuple.variables, a, 3);
array_init(&proc_results->Tuple.variables, a, 1);
- proc_params->Tuple.variables[0] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false, false);
- proc_params->Tuple.variables[1] = make_entity_param(a, proc_scope, make_token_ident(str_lit("reason")), t_i32, false, false);
- proc_params->Tuple.variables[2] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false, false);
+ proc_params->Tuple.variables[0] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false, false);
+ proc_params->Tuple.variables[1] = alloc_entity_param(proc_scope, make_token_ident(str_lit("reason")), t_i32, false, false);
+ proc_params->Tuple.variables[2] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false, false);
- proc_results->Tuple.variables[0] = make_entity_param(a, proc_scope, empty_token, t_i32, false, false);
+ proc_results->Tuple.variables[0] = alloc_entity_param(proc_scope, empty_token, t_i32, false, false);
Type *proc_type = alloc_type_proc(proc_scope,
@@ -8507,7 +8497,7 @@ void ir_gen_tree(irGen *s) {
proc_type->Proc.abi_compat_result_type = proc_results->Tuple.variables[0]->type;
AstNode *body = gb_alloc_item(a, AstNode);
- Entity *e = make_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0);
+ Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0);
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
map_set(&m->values, hash_entity(e), p);
@@ -8566,11 +8556,11 @@ void ir_gen_tree(irGen *s) {
array_init(&proc_results->Tuple.variables, a, 1);
Type *cstring_ptr = alloc_type_pointer(t_cstring);
- proc_params->Tuple.variables[0] = make_entity_param(a, proc_scope, make_token_ident(str_lit("argc")), t_i32, false, false);
- proc_params->Tuple.variables[1] = make_entity_param(a, proc_scope, make_token_ident(str_lit("argv")), cstring_ptr, false, false);
+ proc_params->Tuple.variables[0] = alloc_entity_param(proc_scope, make_token_ident(str_lit("argc")), t_i32, false, false);
+ proc_params->Tuple.variables[1] = alloc_entity_param(proc_scope, make_token_ident(str_lit("argv")), cstring_ptr, false, false);
- proc_results->Tuple.variables[0] = make_entity_param(a, proc_scope, empty_token, t_i32, false, false);
+ proc_results->Tuple.variables[0] = alloc_entity_param(proc_scope, empty_token, t_i32, false, false);
Type *proc_type = alloc_type_proc(proc_scope,
@@ -8585,7 +8575,7 @@ void ir_gen_tree(irGen *s) {
proc_type->Proc.abi_compat_result_type = proc_results->Tuple.variables[0]->type;
AstNode *body = gb_alloc_item(a, AstNode);
- Entity *e = make_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0);
+ Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0);
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
map_set(&m->values, hash_entity(e), p);
@@ -8636,12 +8626,12 @@ void ir_gen_tree(irGen *s) {
proc_results->Tuple.variables = gb_alloc_array(a, Entity *, 1);
proc_results->Tuple.variable_count = 1;
- proc_params->Tuple.variables[0] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false);
- proc_params->Tuple.variables[1] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false);
- proc_params->Tuple.variables[2] = make_entity_param(a, proc_scope, blank_token, t_u8_ptr, false);
- proc_params->Tuple.variables[3] = make_entity_param(a, proc_scope, blank_token, t_i32, false);
+ proc_params->Tuple.variables[0] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false);
+ proc_params->Tuple.variables[1] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false);
+ proc_params->Tuple.variables[2] = alloc_entity_param(proc_scope, blank_token, t_u8_ptr, false);
+ proc_params->Tuple.variables[3] = alloc_entity_param(proc_scope, blank_token, t_i32, false);
- proc_results->Tuple.variables[0] = make_entity_param(a, proc_scope, empty_token, t_i32, false);
+ proc_results->Tuple.variables[0] = alloc_entity_param(proc_scope, empty_token, t_i32, false);
Type *proc_type = alloc_type_proc(a, proc_scope,
@@ -8649,7 +8639,7 @@ void ir_gen_tree(irGen *s) {
proc_results, 1, false, ProcCC_Std);
AstNode *body = gb_alloc_item(a, AstNode);
- Entity *e = make_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0);
+ Entity *e = alloc_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0);
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
m->entry_point_entity = e;
@@ -8675,7 +8665,7 @@ void ir_gen_tree(irGen *s) {
nullptr, 0, false,
ProcCC_Contextless);
AstNode *body = gb_alloc_item(a, AstNode);
- Entity *e = make_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0);
+ Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0);
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
map_set(&m->values, hash_entity(e), p);
diff --git a/src/main.cpp b/src/main.cpp
index c1999e766..bf4d19d30 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -685,6 +685,8 @@ i32 exec_llvm_llc(String output_base) {
#endif
}
+
+
int main(int arg_count, char **arg_ptr) {
if (arg_count < 2) {
usage(make_string_c(arg_ptr[0]));
diff --git a/src/types.cpp b/src/types.cpp
index 7ff1517be..d3029cd6c 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -435,8 +435,12 @@ HashKey hash_cache_type_array(Type *elem, i64 count) {
return hash_ptr_and_id(elem, cast(u64)count);
}
HashKey hash_cache_type_map(Type *key, Type *value) {
- u64 v = cast(u64)cast(uintptr)value;
- return hash_ptr_and_id(key, v);
+ HashKey hkey = {};
+ if ((key != nullptr) == (value != nullptr)) {
+ u64 v = cast(u64)cast(uintptr)value;
+ hkey = hash_ptr_and_id(key, v);
+ }
+ return hkey;
}
@@ -453,6 +457,7 @@ void init_cached_type_maps() {
CachedType *find_cached_type(CachedTypeKind kind, HashKey key) {
GB_ASSERT(key.kind == HashKey_PtrAndId);
if (key.ptr_and_id.ptr == nullptr) {
+ // NOTE(bill): uncachable types
return nullptr;
}
auto *m = &cached_type_maps[kind];
@@ -462,6 +467,7 @@ CachedType *find_cached_type(CachedTypeKind kind, HashKey key) {
void add_cached_type(CachedTypeKind kind, HashKey key, Type *type) {
GB_ASSERT(key.kind == HashKey_PtrAndId);
if (key.ptr_and_id.ptr == nullptr) {
+ // NOTE(bill): uncachable types
return;
}
CachedType ct = {};
@@ -1694,10 +1700,10 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
String data_str = str_lit("data");
String type_info_str = str_lit("type_info");
if (entity__any_data == nullptr) {
- entity__any_data = make_entity_field(a, nullptr, make_token_ident(data_str), t_rawptr, false, 0);
+ entity__any_data = alloc_entity_field(nullptr, make_token_ident(data_str), t_rawptr, false, 0);
}
if (entity__any_type_info == nullptr) {
- entity__any_type_info = make_entity_field(a, nullptr, make_token_ident(type_info_str), t_type_info_ptr, false, 1);
+ entity__any_type_info = alloc_entity_field(nullptr, make_token_ident(type_info_str), t_type_info_ptr, false, 1);
}
if (field_name == data_str) {
@@ -1722,7 +1728,7 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
case (_length): \
if (field_name == _name) { \
selection_add_index(&sel, (_length)-1); \
- sel.entity = make_entity_array_elem(a, nullptr, make_token_ident(str_lit(_name)), type->Array.elem, (_length)-1); \
+ sel.entity = alloc_entity_array_elem(nullptr, make_token_ident(str_lit(_name)), type->Array.elem, (_length)-1); \
return sel; \
} \
/*fallthrough*/
@@ -1853,11 +1859,14 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
}
+// IMPORTANT TODO(bill): SHould this TypePath code be removed since type cycle checking is handled much earlier on?
+
struct TypePath {
Array<Entity *> path; // Entity_TypeName;
bool failure;
};
+
void type_path_init(TypePath *tp) {
// TODO(bill): Use an allocator that uses a backing array if it can and then use alternative allocator when exhausted
array_init(&tp->path, heap_allocator());