mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-30 11:20:08 +00:00
:: style procedure declarations; remove old parsing code
This commit is contained in:
+35
-35
@@ -311,9 +311,9 @@ void init_entity_foreign_library(Checker *c, Entity *e) {
|
||||
|
||||
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
GB_ASSERT(e->type == NULL);
|
||||
if (d->proc_decl->kind != AstNode_ProcDecl) {
|
||||
if (d->proc_lit->kind != AstNode_ProcLit) {
|
||||
// TOOD(bill): Better error message
|
||||
error(d->proc_decl, "Expected a procedure to check");
|
||||
error(d->proc_lit, "Expected a procedure to check");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -324,19 +324,19 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false, ProcCC_Odin);
|
||||
}
|
||||
e->type = proc_type;
|
||||
ast_node(pd, ProcDecl, d->proc_decl);
|
||||
ast_node(pl, ProcLit, d->proc_lit);
|
||||
|
||||
check_open_scope(c, pd->type);
|
||||
check_open_scope(c, pl->type);
|
||||
defer (check_close_scope(c));
|
||||
|
||||
check_procedure_type(c, proc_type, pd->type);
|
||||
check_procedure_type(c, proc_type, pl->type);
|
||||
|
||||
bool is_foreign = (pd->tags & ProcTag_foreign) != 0;
|
||||
bool is_link_name = (pd->tags & ProcTag_link_name) != 0;
|
||||
bool is_export = (pd->tags & ProcTag_export) != 0;
|
||||
bool is_inline = (pd->tags & ProcTag_inline) != 0;
|
||||
bool is_no_inline = (pd->tags & ProcTag_no_inline) != 0;
|
||||
bool is_require_results = (pd->tags & ProcTag_require_results) != 0;
|
||||
bool is_foreign = (pl->tags & ProcTag_foreign) != 0;
|
||||
bool is_link_name = (pl->tags & ProcTag_link_name) != 0;
|
||||
bool is_export = (pl->tags & ProcTag_export) != 0;
|
||||
bool is_inline = (pl->tags & ProcTag_inline) != 0;
|
||||
bool is_no_inline = (pl->tags & ProcTag_no_inline) != 0;
|
||||
bool is_require_results = (pl->tags & ProcTag_require_results) != 0;
|
||||
|
||||
|
||||
TypeProc *pt = &proc_type->Proc;
|
||||
@@ -356,16 +356,16 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
}
|
||||
|
||||
if (is_inline && is_no_inline) {
|
||||
error(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure");
|
||||
error(pl->type, "You cannot apply both `inline` and `no_inline` to a procedure");
|
||||
}
|
||||
|
||||
if (is_foreign && is_export) {
|
||||
error(pd->type, "A foreign procedure cannot have an `export` tag");
|
||||
error(pl->type, "A foreign procedure cannot have an `export` tag");
|
||||
}
|
||||
|
||||
|
||||
if (pt->is_generic) {
|
||||
if (pd->body == NULL) {
|
||||
if (pl->body == NULL) {
|
||||
error(e->token, "Polymorphic procedures must have a body");
|
||||
}
|
||||
|
||||
@@ -375,24 +375,24 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
}
|
||||
}
|
||||
|
||||
if (pd->body != NULL) {
|
||||
if (pl->body != NULL) {
|
||||
if (is_foreign) {
|
||||
error(pd->body, "A foreign procedure cannot have a body");
|
||||
error(pl->body, "A foreign procedure cannot have a body");
|
||||
}
|
||||
if (proc_type->Proc.c_vararg) {
|
||||
error(pd->body, "A procedure with a `#c_vararg` field cannot have a body");
|
||||
error(pl->body, "A procedure with a `#c_vararg` field cannot have a body");
|
||||
}
|
||||
|
||||
d->scope = c->context.scope;
|
||||
|
||||
GB_ASSERT(pd->body->kind == AstNode_BlockStmt);
|
||||
check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pd->body, pd->tags);
|
||||
GB_ASSERT(pl->body->kind == AstNode_BlockStmt);
|
||||
check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pl->body, pl->tags);
|
||||
} else if (!is_foreign) {
|
||||
error(e->token, "Only a foreign procedure cannot have a body");
|
||||
}
|
||||
|
||||
if (pt->result_count == 0 && is_require_results) {
|
||||
error(pd->type, "`#require_results` is not needed on a procedure with no results");
|
||||
error(pl->type, "`#require_results` is not needed on a procedure with no results");
|
||||
} else {
|
||||
pt->require_results = is_require_results;
|
||||
}
|
||||
@@ -401,8 +401,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
|
||||
if (is_foreign) {
|
||||
String name = e->token.string;
|
||||
if (pd->link_name.len > 0) {
|
||||
name = pd->link_name;
|
||||
if (pl->link_name.len > 0) {
|
||||
name = pl->link_name;
|
||||
}
|
||||
e->Procedure.is_foreign = true;
|
||||
e->Procedure.link_name = name;
|
||||
@@ -420,16 +420,16 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
Type *other_type = base_type(f->type);
|
||||
if (is_type_proc(this_type) && is_type_proc(other_type)) {
|
||||
if (!are_signatures_similar_enough(this_type, other_type)) {
|
||||
error(d->proc_decl,
|
||||
"Redeclaration of foreign procedure `%.*s` with different type signatures\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
error(d->proc_lit,
|
||||
"Redeclaration of foreign procedure `%.*s` with different type signatures\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
}
|
||||
} else if (!are_types_identical(this_type, other_type)) {
|
||||
error(d->proc_decl,
|
||||
"Foreign entity `%.*s` previously declared elsewhere with a different type\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
error(d->proc_lit,
|
||||
"Foreign entity `%.*s` previously declared elsewhere with a different type\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
}
|
||||
} else {
|
||||
map_set(fp, key, e);
|
||||
@@ -437,7 +437,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
} else {
|
||||
String name = e->token.string;
|
||||
if (is_link_name) {
|
||||
name = pd->link_name;
|
||||
name = pl->link_name;
|
||||
}
|
||||
|
||||
if (is_link_name || is_export) {
|
||||
@@ -451,10 +451,10 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
Entity *f = *found;
|
||||
TokenPos pos = f->token.pos;
|
||||
// TODO(bill): Better error message?
|
||||
error(d->proc_decl,
|
||||
"Non unique linking name for procedure `%.*s`\n"
|
||||
"\tother at %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
error(d->proc_lit,
|
||||
"Non unique linking name for procedure `%.*s`\n"
|
||||
"\tother at %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
} else {
|
||||
map_set(fp, key, e);
|
||||
}
|
||||
|
||||
+7
-7
@@ -5034,10 +5034,10 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
|
||||
}
|
||||
|
||||
|
||||
AstNode *proc_decl = clone_ast_node(a, old_decl->proc_decl);
|
||||
ast_node(pd, ProcDecl, proc_decl);
|
||||
AstNode *proc_lit = clone_ast_node(a, old_decl->proc_lit);
|
||||
ast_node(pl, ProcLit, proc_lit);
|
||||
// NOTE(bill): Associate the scope declared above with this procedure declaration's type
|
||||
add_scope(c, pd->type, final_proc_type->Proc.scope);
|
||||
add_scope(c, pl->type, final_proc_type->Proc.scope);
|
||||
final_proc_type->Proc.is_generic_specialized = true;
|
||||
|
||||
u64 tags = base_entity->Procedure.tags;
|
||||
@@ -5045,8 +5045,8 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
|
||||
Token token = ident->Ident;
|
||||
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, old_decl->parent);
|
||||
d->gen_proc_type = final_proc_type;
|
||||
d->type_expr = pd->type;
|
||||
d->proc_decl = proc_decl;
|
||||
d->type_expr = pl->type;
|
||||
d->proc_lit = proc_lit;
|
||||
|
||||
|
||||
Entity *entity = make_entity_procedure(c->allocator, NULL, token, final_proc_type, tags);
|
||||
@@ -5061,7 +5061,7 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
|
||||
proc_info.token = token;
|
||||
proc_info.decl = d;
|
||||
proc_info.type = final_proc_type;
|
||||
proc_info.body = pd->body;
|
||||
proc_info.body = pl->body;
|
||||
proc_info.tags = tags;
|
||||
}
|
||||
|
||||
@@ -5926,7 +5926,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
check_open_scope(c, pl->type);
|
||||
{
|
||||
decl = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
|
||||
decl->proc_decl = node;
|
||||
decl->proc_lit = node;
|
||||
c->context.decl = decl;
|
||||
|
||||
if (pl->tags != 0) {
|
||||
|
||||
@@ -1812,161 +1812,5 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
|
||||
|
||||
case_ast_node(gd, GenDecl, node);
|
||||
GB_ASSERT(!c->context.scope->is_file);
|
||||
for_array(i, gd->specs) {
|
||||
AstNode *spec = gd->specs[i];
|
||||
switch (gd->token.kind) {
|
||||
case Token_var: {
|
||||
ast_node(vd, ValueSpec, spec);
|
||||
|
||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count);
|
||||
isize entity_count = 0;
|
||||
|
||||
if (gd->flags & VarDeclFlag_thread_local) {
|
||||
gd->flags &= ~VarDeclFlag_thread_local;
|
||||
error(node, "`thread_local` may only be applied to a variable declaration");
|
||||
}
|
||||
|
||||
for_array(i, vd->names) {
|
||||
AstNode *name = vd->names[i];
|
||||
Entity *entity = NULL;
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error(name, "A variable declaration must be an identifier");
|
||||
} else {
|
||||
Token token = name->Ident;
|
||||
String str = token.string;
|
||||
Entity *found = NULL;
|
||||
// NOTE(bill): Ignore assignments to `_`
|
||||
if (str != "_") {
|
||||
found = current_scope_lookup_entity(c->context.scope, str);
|
||||
}
|
||||
if (found == NULL) {
|
||||
entity = make_entity_variable(c->allocator, c->context.scope, token, NULL, false);
|
||||
entity->identifier = name;
|
||||
|
||||
AstNode *fl = c->context.curr_foreign_library;
|
||||
if (fl != NULL) {
|
||||
GB_ASSERT(fl->kind == AstNode_Ident);
|
||||
entity->Variable.is_foreign = true;
|
||||
entity->Variable.foreign_library_ident = fl;
|
||||
}
|
||||
} else {
|
||||
TokenPos pos = found->token.pos;
|
||||
error(token,
|
||||
"Redeclaration of `%.*s` in this scope\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(str), LIT(pos.file), pos.line, pos.column);
|
||||
entity = found;
|
||||
}
|
||||
}
|
||||
if (entity == NULL) {
|
||||
entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name));
|
||||
}
|
||||
entity->parent_proc_decl = c->context.curr_proc_decl;
|
||||
entities[entity_count++] = entity;
|
||||
}
|
||||
|
||||
Type *init_type = NULL;
|
||||
if (vd->type) {
|
||||
init_type = check_type(c, vd->type, NULL);
|
||||
if (init_type == NULL) {
|
||||
init_type = t_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
for (isize i = 0; i < entity_count; i++) {
|
||||
Entity *e = entities[i];
|
||||
GB_ASSERT(e != NULL);
|
||||
if (e->flags & EntityFlag_Visited) {
|
||||
e->type = t_invalid;
|
||||
continue;
|
||||
}
|
||||
e->flags |= EntityFlag_Visited;
|
||||
|
||||
if (e->type == NULL) {
|
||||
e->type = init_type;
|
||||
}
|
||||
}
|
||||
|
||||
check_arity_match(c, vd);
|
||||
check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration"));
|
||||
|
||||
for (isize i = 0; i < entity_count; i++) {
|
||||
Entity *e = entities[i];
|
||||
if (e->Variable.is_foreign) {
|
||||
if (vd->values.count > 0) {
|
||||
error(e->token, "A foreign variable declaration cannot have a default value");
|
||||
}
|
||||
init_entity_foreign_library(c, e);
|
||||
|
||||
String name = e->token.string;
|
||||
auto *fp = &c->info.foreigns;
|
||||
HashKey key = hash_string(name);
|
||||
Entity **found = map_get(fp, key);
|
||||
if (found) {
|
||||
Entity *f = *found;
|
||||
TokenPos pos = f->token.pos;
|
||||
Type *this_type = base_type(e->type);
|
||||
Type *other_type = base_type(f->type);
|
||||
if (!are_types_identical(this_type, other_type)) {
|
||||
error(e->token,
|
||||
"Foreign entity `%.*s` previously declared elsewhere with a different type\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
}
|
||||
} else {
|
||||
map_set(fp, key, e);
|
||||
}
|
||||
}
|
||||
add_entity(c, c->context.scope, e->identifier, e);
|
||||
}
|
||||
|
||||
if ((gd->flags & VarDeclFlag_using) != 0) {
|
||||
Token token = ast_node_token(node);
|
||||
if (vd->type != NULL && entity_count > 1) {
|
||||
error(token, "`using` can only be applied to one variable of the same type");
|
||||
// TODO(bill): Should a `continue` happen here?
|
||||
}
|
||||
|
||||
for (isize entity_index = 0; entity_index < entity_count; entity_index++) {
|
||||
Entity *e = entities[entity_index];
|
||||
if (e == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (e->kind != Entity_Variable) {
|
||||
continue;
|
||||
}
|
||||
bool is_immutable = e->Variable.is_immutable;
|
||||
String name = e->token.string;
|
||||
Type *t = base_type(type_deref(e->type));
|
||||
|
||||
if (is_type_struct(t) || is_type_raw_union(t)) {
|
||||
Scope *scope = scope_of_node(&c->info, t->Record.node);
|
||||
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);
|
||||
uvar->Variable.is_immutable = is_immutable;
|
||||
Entity *prev = scope_insert_entity(c->context.scope, uvar);
|
||||
if (prev != NULL) {
|
||||
error(token, "Namespace collision while `using` `%.*s` of: %.*s", LIT(name), LIT(prev->token.string));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// NOTE(bill): skip the rest to remove extra errors
|
||||
error(token, "`using` can only be applied to variables of type struct or raw_union");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
}
|
||||
}
|
||||
|
||||
+31
-189
@@ -187,7 +187,7 @@ struct DeclInfo {
|
||||
|
||||
AstNode * type_expr;
|
||||
AstNode * init_expr;
|
||||
AstNode * proc_decl; // AstNode_ProcDecl
|
||||
AstNode * proc_lit; // AstNode_ProcLit
|
||||
Type * gen_proc_type; // Precalculated
|
||||
|
||||
Map<bool> deps; // Key: Entity *
|
||||
@@ -366,10 +366,10 @@ bool decl_info_has_init(DeclInfo *d) {
|
||||
if (d->init_expr != NULL) {
|
||||
return true;
|
||||
}
|
||||
if (d->proc_decl != NULL) {
|
||||
switch (d->proc_decl->kind) {
|
||||
case_ast_node(pd, ProcDecl, d->proc_decl);
|
||||
if (pd->body != NULL) {
|
||||
if (d->proc_lit != NULL) {
|
||||
switch (d->proc_lit->kind) {
|
||||
case_ast_node(pl, ProcLit, d->proc_lit);
|
||||
if (pl->body != NULL) {
|
||||
return true;
|
||||
}
|
||||
case_end;
|
||||
@@ -1386,7 +1386,6 @@ void init_preload(Checker *c) {
|
||||
|
||||
|
||||
|
||||
bool check_arity_match(Checker *c, AstNodeValueSpec *s);
|
||||
bool check_arity_match(Checker *c, AstNodeValueDecl *vd);
|
||||
void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_scope);
|
||||
void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws, bool is_file_scope);
|
||||
@@ -1507,38 +1506,6 @@ void check_procedure_overloading(Checker *c, Entity *e) {
|
||||
|
||||
|
||||
|
||||
|
||||
bool check_arity_match(Checker *c, AstNodeValueSpec *spec) {
|
||||
isize lhs = spec->names.count;
|
||||
isize rhs = spec->values.count;
|
||||
|
||||
if (rhs == 0) {
|
||||
if (spec->type == NULL) {
|
||||
error(spec->names[0], "Missing type or initial expression");
|
||||
return false;
|
||||
}
|
||||
} else if (lhs < rhs) {
|
||||
if (lhs < spec->values.count) {
|
||||
AstNode *n = spec->values[lhs];
|
||||
gbString str = expr_to_string(n);
|
||||
error(n, "Extra initial expression `%s`", str);
|
||||
gb_string_free(str);
|
||||
} else {
|
||||
error(spec->names[0], "Extra initial expression");
|
||||
}
|
||||
return false;
|
||||
} else if (lhs > rhs && rhs != 1) {
|
||||
AstNode *n = spec->names[rhs];
|
||||
gbString str = expr_to_string(n);
|
||||
error(n, "Missing expression for `%s`", str);
|
||||
gb_string_free(str);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool check_arity_match(Checker *c, AstNodeValueDecl *vd) {
|
||||
isize lhs = vd->names.count;
|
||||
isize rhs = vd->values.count;
|
||||
@@ -1705,6 +1672,10 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
||||
}
|
||||
|
||||
AstNode *init = unparen_expr(vd->values[i]);
|
||||
if (init == NULL) {
|
||||
error(name, "Expected a value for this constant value declaration");
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *fl = c->context.curr_foreign_library;
|
||||
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
|
||||
@@ -1722,8 +1693,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
||||
e->Procedure.foreign_library_ident = fl;
|
||||
pl->tags |= ProcTag_foreign;
|
||||
}
|
||||
GB_PANIC("TODO(bill): Constant procedure literals");
|
||||
d->proc_decl = init;
|
||||
d->proc_lit = init;
|
||||
d->type_expr = pl->type;
|
||||
} else {
|
||||
e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, empty_exact_value);
|
||||
@@ -1733,7 +1703,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
||||
e->identifier = name;
|
||||
|
||||
if (fl != NULL && e->kind != Entity_Procedure) {
|
||||
error(name, "Only procedures and variables are allowed to be in a foreign block");
|
||||
error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_node_strings[init->kind]));
|
||||
// continue;
|
||||
}
|
||||
|
||||
@@ -1746,137 +1716,9 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
||||
case_end;
|
||||
|
||||
case_ast_node(gd, GenDecl, decl);
|
||||
AstNodeValueSpec empty_spec = {};
|
||||
AstNodeValueSpec *last_spec = NULL;
|
||||
for_array(i, gd->specs) {
|
||||
AstNode *spec = gd->specs[i];
|
||||
switch (gd->token.kind) {
|
||||
case Token_const: {
|
||||
ast_node(vs, ValueSpec, spec);
|
||||
|
||||
if (vs->type != NULL || vs->values.count > 0) {
|
||||
last_spec = vs;
|
||||
} else if (last_spec == NULL) {
|
||||
last_spec = &empty_spec;
|
||||
}
|
||||
|
||||
for_array(i, vs->names) {
|
||||
AstNode *name = vs->names[i];
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *init = NULL;
|
||||
if (i < vs->values.count) {
|
||||
init = vs->values[i];
|
||||
}
|
||||
|
||||
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
|
||||
Entity *e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, empty_exact_value);
|
||||
d->type_expr = last_spec->type;
|
||||
d->init_expr = init;
|
||||
e->identifier = name;
|
||||
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
}
|
||||
|
||||
check_arity_match(c, vs);
|
||||
} break;
|
||||
|
||||
case Token_var: {
|
||||
if (!c->context.scope->is_file) {
|
||||
// NOTE(bill): local scope -> handle later and in order
|
||||
break;
|
||||
}
|
||||
ast_node(vs, ValueSpec, spec);
|
||||
|
||||
// NOTE(bill): You need to store the entity information here unline a constant declaration
|
||||
isize entity_cap = vs->names.count;
|
||||
isize entity_count = 0;
|
||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_cap);
|
||||
DeclInfo *di = NULL;
|
||||
if (vs->values.count > 0) {
|
||||
di = make_declaration_info(heap_allocator(), c->context.scope, c->context.decl);
|
||||
di->entities = entities;
|
||||
di->type_expr = vs->type;
|
||||
di->init_expr = vs->values[0];
|
||||
|
||||
|
||||
if (gd->flags & VarDeclFlag_thread_local) {
|
||||
error(decl, "#thread_local variable declarations cannot have initialization values");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for_array(i, vs->names) {
|
||||
AstNode *name = vs->names[i];
|
||||
AstNode *value = NULL;
|
||||
if (i < vs->values.count) {
|
||||
value = vs->values[i];
|
||||
}
|
||||
if (name->kind != AstNode_Ident) {
|
||||
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, NULL, false);
|
||||
e->Variable.is_thread_local = (gd->flags & VarDeclFlag_thread_local) != 0;
|
||||
e->identifier = name;
|
||||
|
||||
if (gd->flags & VarDeclFlag_using) {
|
||||
gd->flags &= ~VarDeclFlag_using; // NOTE(bill): This error will be only caught once
|
||||
error(name, "`using` is not allowed at the file scope");
|
||||
}
|
||||
|
||||
AstNode *fl = c->context.curr_foreign_library;
|
||||
if (fl != NULL) {
|
||||
GB_ASSERT(fl->kind == AstNode_Ident);
|
||||
e->Variable.is_foreign = true;
|
||||
e->Variable.foreign_library_ident = fl;
|
||||
}
|
||||
|
||||
entities[entity_count++] = e;
|
||||
|
||||
DeclInfo *d = di;
|
||||
if (d == NULL) {
|
||||
AstNode *init_expr = value;
|
||||
d = make_declaration_info(heap_allocator(), e->scope, c->context.decl);
|
||||
d->type_expr = vs->type;
|
||||
d->init_expr = init_expr;
|
||||
}
|
||||
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
}
|
||||
|
||||
if (di != NULL) {
|
||||
di->entity_count = entity_count;
|
||||
}
|
||||
|
||||
check_arity_match(c, vs);
|
||||
} break;
|
||||
|
||||
case Token_type: {
|
||||
ast_node(ts, TypeSpec, spec);
|
||||
|
||||
AstNode *name = ts->name;
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
|
||||
Entity *e = NULL;
|
||||
|
||||
AstNode *type = unparen_expr(ts->type);
|
||||
e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
|
||||
d->type_expr = type;
|
||||
d->init_expr = type;
|
||||
|
||||
e->identifier = name;
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
} break;
|
||||
|
||||
case Token_import:
|
||||
case Token_import_load: {
|
||||
ast_node(ts, ImportSpec, spec);
|
||||
@@ -1941,29 +1783,29 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
||||
c->context = prev_context;
|
||||
case_end;
|
||||
|
||||
case_ast_node(pd, ProcDecl, decl);
|
||||
AstNode *name = pd->name;
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
||||
break;
|
||||
}
|
||||
// case_ast_node(pd, ProcDecl, decl);
|
||||
// AstNode *name = pd->name;
|
||||
// if (name->kind != AstNode_Ident) {
|
||||
// error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
||||
// break;
|
||||
// }
|
||||
|
||||
|
||||
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
|
||||
Entity *e = NULL;
|
||||
// DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
|
||||
// Entity *e = NULL;
|
||||
|
||||
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, pd->tags);
|
||||
AstNode *fl = c->context.curr_foreign_library;
|
||||
if (fl != NULL) {
|
||||
GB_ASSERT(fl->kind == AstNode_Ident);
|
||||
e->Procedure.foreign_library_ident = fl;
|
||||
pd->tags |= ProcTag_foreign;
|
||||
}
|
||||
d->proc_decl = decl;
|
||||
d->type_expr = pd->type;
|
||||
e->identifier = name;
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
case_end;
|
||||
// e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, pd->tags);
|
||||
// AstNode *fl = c->context.curr_foreign_library;
|
||||
// if (fl != NULL) {
|
||||
// GB_ASSERT(fl->kind == AstNode_Ident);
|
||||
// e->Procedure.foreign_library_ident = fl;
|
||||
// pd->tags |= ProcTag_foreign;
|
||||
// }
|
||||
// d->proc_decl = decl;
|
||||
// d->type_expr = pd->type;
|
||||
// e->identifier = name;
|
||||
// add_entity_and_decl_info(c, name, e, d);
|
||||
// case_end;
|
||||
|
||||
default:
|
||||
if (c->context.scope->is_file) {
|
||||
|
||||
+5
-11
@@ -32,6 +32,7 @@ String alloc_comment_group_string(gbAllocator a, CommentGroup g) {
|
||||
return make_string(text, len);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void print_type_spec(AstNode *spec) {
|
||||
ast_node(ts, TypeSpec, spec);
|
||||
GB_ASSERT(ts->name->kind == AstNode_Ident);
|
||||
@@ -87,20 +88,13 @@ void print_proc_decl(AstNodeProcDecl *pd) {
|
||||
}
|
||||
gb_printf("\n\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
void print_declaration(AstNode *decl) {
|
||||
switch (decl->kind) {
|
||||
case_ast_node(gd, GenDecl, decl);
|
||||
for_array(spec_index, gd->specs) {
|
||||
AstNode *spec = gd->specs[spec_index];
|
||||
switch(gd->token.kind) {
|
||||
case Token_var:
|
||||
break;
|
||||
case Token_const:
|
||||
break;
|
||||
case Token_type:
|
||||
// print_type_spec(spec);
|
||||
break;
|
||||
case Token_import:
|
||||
case Token_import_load:
|
||||
break;
|
||||
@@ -111,9 +105,9 @@ void print_declaration(AstNode *decl) {
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(pd, ProcDecl, decl);
|
||||
print_proc_decl(pd);
|
||||
case_end;
|
||||
// case_ast_node(pd, ProcDecl, decl);
|
||||
// print_proc_decl(pd);
|
||||
// case_end;
|
||||
|
||||
case_ast_node(fb, ForeignBlockDecl, decl);
|
||||
// TODO(bill)
|
||||
|
||||
+45
-135
@@ -5881,7 +5881,7 @@ void ir_type_case_body(irProcedure *proc, AstNode *label, AstNode *clause, irBlo
|
||||
}
|
||||
|
||||
|
||||
void ir_build_poly_proc(irProcedure *proc, AstNodeProcDecl *pd, Entity *e) {
|
||||
void ir_build_poly_proc(irProcedure *proc, AstNodeProcLit *pd, Entity *e) {
|
||||
GB_ASSERT(pd->body != NULL);
|
||||
|
||||
if (is_entity_in_dependency_map(&proc->module->min_dep_map, e) == false) {
|
||||
@@ -6020,139 +6020,49 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
map_set(&proc->module->entity_names, hash_entity(e), name);
|
||||
ir_gen_global_type_name(proc->module, e, name);
|
||||
} else if (e->kind == Entity_Procedure) {
|
||||
GB_PANIC("TODO(bill): Procedure values");
|
||||
}
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(gd, GenDecl, node);
|
||||
for_array(i, gd->specs) {
|
||||
AstNode *spec = gd->specs[i];
|
||||
switch (gd->token.kind) {
|
||||
case Token_var: {
|
||||
ast_node(vd, ValueSpec, spec);
|
||||
|
||||
irModule *m = proc->module;
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
|
||||
if (vd->values.count == 0) { // declared and zero-initialized
|
||||
for_array(i, vd->names) {
|
||||
AstNode *name = vd->names[i];
|
||||
if (!ir_is_blank_ident(name)) {
|
||||
ir_add_local_for_identifier(proc, name, true);
|
||||
}
|
||||
}
|
||||
} else { // Tuple(s)
|
||||
Array<irAddr> lvals = {};
|
||||
Array<irValue *> inits = {};
|
||||
array_init(&lvals, m->tmp_allocator, vd->names.count);
|
||||
array_init(&inits, m->tmp_allocator, vd->names.count);
|
||||
|
||||
for_array(i, vd->names) {
|
||||
AstNode *name = vd->names[i];
|
||||
irAddr lval = ir_addr(NULL);
|
||||
if (!ir_is_blank_ident(name)) {
|
||||
ir_add_local_for_identifier(proc, name, false);
|
||||
lval = ir_build_addr(proc, name);
|
||||
}
|
||||
|
||||
array_add(&lvals, lval);
|
||||
}
|
||||
|
||||
for_array(i, vd->values) {
|
||||
irValue *init = ir_build_expr(proc, vd->values[i]);
|
||||
Type *t = ir_type(init);
|
||||
if (t->kind == Type_Tuple) {
|
||||
for (isize i = 0; i < t->Tuple.variable_count; i++) {
|
||||
Entity *e = t->Tuple.variables[i];
|
||||
irValue *v = ir_emit_struct_ev(proc, init, i);
|
||||
array_add(&inits, v);
|
||||
CheckerInfo *info = proc->module->info;
|
||||
DeclInfo *decl = decl_info_of_entity(info, e);
|
||||
ast_node(pl, ProcLit, decl->proc_lit);
|
||||
if (pl->body != NULL) {
|
||||
if (is_type_gen_proc(e->type)) {
|
||||
auto found = *map_get(&info->gen_procs, hash_pointer(ident));
|
||||
for_array(i, found) {
|
||||
Entity *e = found[i];
|
||||
DeclInfo *d = decl_info_of_entity(info, e);
|
||||
ir_build_poly_proc(proc, &d->proc_lit->ProcLit, e);
|
||||
}
|
||||
} else {
|
||||
array_add(&inits, init);
|
||||
ir_build_poly_proc(proc, pl, e);
|
||||
}
|
||||
} else {
|
||||
|
||||
// FFI - Foreign function interace
|
||||
String original_name = e->token.string;
|
||||
String name = original_name;
|
||||
if (pl->link_name.len > 0) {
|
||||
name = pl->link_name;
|
||||
}
|
||||
|
||||
irValue *value = ir_value_procedure(proc->module->allocator,
|
||||
proc->module, e, e->type, pl->type, pl->body, name);
|
||||
|
||||
value->Proc.tags = pl->tags;
|
||||
|
||||
ir_module_add_value(proc->module, e, value);
|
||||
ir_build_proc(value, proc);
|
||||
|
||||
if (value->Proc.tags & ProcTag_foreign) {
|
||||
HashKey key = hash_string(name);
|
||||
irValue **prev_value = map_get(&proc->module->members, key);
|
||||
if (prev_value == NULL) {
|
||||
// NOTE(bill): Don't do mutliple declarations in the IR
|
||||
map_set(&proc->module->members, key, value);
|
||||
}
|
||||
} else {
|
||||
array_add(&proc->children, &value->Proc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for_array(i, inits) {
|
||||
ir_addr_store(proc, lvals[i], inits[i]);
|
||||
}
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
} break;
|
||||
|
||||
case Token_type: {
|
||||
ast_node(td, TypeSpec, spec);
|
||||
|
||||
AstNode *ident = td->name;
|
||||
GB_ASSERT(ident->kind == AstNode_Ident);
|
||||
Entity *e = entity_of_ident(proc->module->info, ident);
|
||||
GB_ASSERT(e != NULL);
|
||||
if (e->kind == Entity_TypeName) {
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent_proc.name-guid
|
||||
String ts_name = e->token.string;
|
||||
isize name_len = proc->name.len + 1 + ts_name.len + 1 + 10 + 1;
|
||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||
i32 guid = cast(i32)proc->module->members.entries.count;
|
||||
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(ts_name), guid);
|
||||
String name = make_string(name_text, name_len-1);
|
||||
|
||||
irValue *value = ir_value_type_name(proc->module->allocator,
|
||||
name, e->type);
|
||||
map_set(&proc->module->entity_names, hash_entity(e), name);
|
||||
ir_gen_global_type_name(proc->module, e, name);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(pd, ProcDecl, node);
|
||||
AstNode *ident = pd->name;
|
||||
GB_ASSERT(ident->kind == AstNode_Ident);
|
||||
CheckerInfo *info = proc->module->info;
|
||||
Entity *e = entity_of_ident(info, ident);
|
||||
|
||||
if (pd->body != NULL) {
|
||||
if (is_type_gen_proc(e->type)) {
|
||||
auto found = *map_get(&info->gen_procs, hash_pointer(ident));
|
||||
for_array(i, found) {
|
||||
Entity *e = found[i];
|
||||
DeclInfo *d = decl_info_of_entity(info, e);
|
||||
ir_build_poly_proc(proc, &d->proc_decl->ProcDecl, e);
|
||||
}
|
||||
} else {
|
||||
ir_build_poly_proc(proc, pd, e);
|
||||
}
|
||||
} else {
|
||||
|
||||
// FFI - Foreign function interace
|
||||
String original_name = e->token.string;
|
||||
String name = original_name;
|
||||
if (pd->link_name.len > 0) {
|
||||
name = pd->link_name;
|
||||
}
|
||||
|
||||
irValue *value = ir_value_procedure(proc->module->allocator,
|
||||
proc->module, e, e->type, pd->type, pd->body, name);
|
||||
|
||||
value->Proc.tags = pd->tags;
|
||||
|
||||
ir_module_add_value(proc->module, e, value);
|
||||
ir_build_proc(value, proc);
|
||||
|
||||
if (value->Proc.tags & ProcTag_foreign) {
|
||||
HashKey key = hash_string(name);
|
||||
irValue **prev_value = map_get(&proc->module->members, key);
|
||||
if (prev_value == NULL) {
|
||||
// NOTE(bill): Don't do mutliple declarations in the IR
|
||||
map_set(&proc->module->members, key, value);
|
||||
}
|
||||
} else {
|
||||
array_add(&proc->children, &value->Proc);
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
@@ -7514,22 +7424,22 @@ void ir_gen_tree(irGen *s) {
|
||||
} break;
|
||||
|
||||
case Entity_Procedure: {
|
||||
ast_node(pd, ProcDecl, decl->proc_decl);
|
||||
ast_node(pl, ProcLit, decl->proc_lit);
|
||||
String original_name = name;
|
||||
AstNode *body = pd->body;
|
||||
AstNode *body = pl->body;
|
||||
|
||||
if (e->Procedure.is_foreign) {
|
||||
name = e->token.string; // NOTE(bill): Don't use the mangled name
|
||||
ir_add_foreign_library_path(m, e->Procedure.foreign_library);
|
||||
}
|
||||
if (pd->link_name.len > 0) {
|
||||
name = pd->link_name;
|
||||
if (pl->link_name.len > 0) {
|
||||
name = pl->link_name;
|
||||
}
|
||||
|
||||
AstNode *type_expr = pd->type;
|
||||
AstNode *type_expr = pl->type;
|
||||
|
||||
irValue *p = ir_value_procedure(a, m, e, e->type, type_expr, body, name);
|
||||
p->Proc.tags = pd->tags;
|
||||
p->Proc.tags = pl->tags;
|
||||
|
||||
ir_module_add_value(m, e, p);
|
||||
HashKey hash_name = hash_string(name);
|
||||
|
||||
+3
-193
@@ -34,7 +34,6 @@ struct AstFile {
|
||||
// NOTE(bill): Used to prevent type literals in control clauses
|
||||
isize expr_level;
|
||||
bool allow_range; // NOTE(bill): Ranges are only allowed in certain cases
|
||||
bool allow_gen_proc_type;
|
||||
bool in_foreign_block;
|
||||
|
||||
Array<AstNode *> decls;
|
||||
@@ -309,15 +308,6 @@ AST_NODE_KIND(_ComplexStmtEnd, "", i32) \
|
||||
AST_NODE_KIND(_StmtEnd, "", i32) \
|
||||
AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||
AST_NODE_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \
|
||||
AST_NODE_KIND(ProcDecl, "procedure declaration", struct { \
|
||||
Token token; \
|
||||
AstNode *name; \
|
||||
AstNode *type; \
|
||||
AstNode *body; \
|
||||
u64 tags; \
|
||||
String link_name; \
|
||||
CommentGroup docs; \
|
||||
}) \
|
||||
AST_NODE_KIND(ForeignBlockDecl, "foreign block declaration", struct { \
|
||||
Token token; \
|
||||
AstNode * foreign_library; \
|
||||
@@ -346,19 +336,6 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||
CommentGroup docs; \
|
||||
CommentGroup comment; \
|
||||
}) \
|
||||
AST_NODE_KIND(ValueSpec, "value specification", struct { \
|
||||
Array<AstNode *> names; \
|
||||
AstNode * type; \
|
||||
Array<AstNode *> values; \
|
||||
CommentGroup docs; \
|
||||
CommentGroup comment; \
|
||||
}) \
|
||||
AST_NODE_KIND(TypeSpec, "type specification", struct { \
|
||||
AstNode *name; \
|
||||
AstNode *type; \
|
||||
CommentGroup docs; \
|
||||
CommentGroup comment; \
|
||||
}) \
|
||||
AST_NODE_KIND(ImportSpec, "import specification", struct { \
|
||||
bool is_import; \
|
||||
Token relpath; \
|
||||
@@ -581,15 +558,12 @@ Token ast_node_token(AstNode *node) {
|
||||
case AstNode_PushContext: return node->PushContext.token;
|
||||
|
||||
case AstNode_BadDecl: return node->BadDecl.begin;
|
||||
case AstNode_ProcDecl: return node->ProcDecl.token;
|
||||
case AstNode_ForeignLibrarySpec: return node->ForeignLibrarySpec.filepath;
|
||||
case AstNode_Label: return node->Label.token;
|
||||
|
||||
case AstNode_GenDecl: return node->GenDecl.token;
|
||||
case AstNode_ValueDecl: return ast_node_token(node->ValueDecl.names[0]);
|
||||
case AstNode_ValueSpec: return ast_node_token(node->ValueSpec.names[0]);
|
||||
case AstNode_ImportSpec: return node->ImportSpec.import_name;
|
||||
case AstNode_TypeSpec: return ast_node_token(node->TypeSpec.name);
|
||||
|
||||
case AstNode_ForeignBlockDecl: return node->ForeignBlockDecl.token;
|
||||
|
||||
@@ -811,12 +785,7 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
|
||||
break;
|
||||
|
||||
case AstNode_BadDecl: break;
|
||||
case AstNode_ProcDecl:
|
||||
n->ProcDecl.name = clone_ast_node(a, n->ProcDecl.name);
|
||||
n->ProcDecl.type = clone_ast_node(a, n->ProcDecl.type);
|
||||
n->ProcDecl.body = clone_ast_node(a, n->ProcDecl.body);
|
||||
// TODO(bill): Clone the comment group too?
|
||||
break;
|
||||
|
||||
case AstNode_ForeignBlockDecl:
|
||||
n->ForeignBlockDecl.foreign_library = clone_ast_node(a, n->ForeignBlockDecl.foreign_library);
|
||||
n->ForeignBlockDecl.decls = clone_ast_node_array(a, n->ForeignBlockDecl.decls);
|
||||
@@ -832,15 +801,6 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
|
||||
n->ValueDecl.type = clone_ast_node(a, n->ValueDecl.type);
|
||||
n->ValueDecl.values = clone_ast_node_array(a, n->ValueDecl.values);
|
||||
break;
|
||||
case AstNode_ValueSpec:
|
||||
n->ValueSpec.names = clone_ast_node_array(a, n->ValueSpec.names);
|
||||
n->ValueSpec.type = clone_ast_node(a, n->ValueSpec.type);
|
||||
n->ValueSpec.values = clone_ast_node_array(a, n->ValueSpec.values);
|
||||
break;
|
||||
case AstNode_TypeSpec:
|
||||
n->TypeSpec.name = clone_ast_node(a, n->TypeSpec.name);
|
||||
n->TypeSpec.type = clone_ast_node(a, n->TypeSpec.type);
|
||||
break;
|
||||
case AstNode_ForeignLibrarySpec:
|
||||
n->ForeignLibrarySpec.cond = clone_ast_node(a, n->ForeignLibrarySpec.cond);
|
||||
break;
|
||||
@@ -1504,19 +1464,6 @@ AstNode *ast_map_type(AstFile *f, Token token, AstNode *count, AstNode *key, Ast
|
||||
}
|
||||
|
||||
|
||||
AstNode *ast_proc_decl(AstFile *f, Token token, AstNode *name, AstNode *type, AstNode *body,
|
||||
u64 tags, String link_name, CommentGroup docs) {
|
||||
AstNode *result = make_ast_node(f, AstNode_ProcDecl);
|
||||
result->ProcDecl.token = token;
|
||||
result->ProcDecl.name = name;
|
||||
result->ProcDecl.type = type;
|
||||
result->ProcDecl.body = body;
|
||||
result->ProcDecl.tags = tags;
|
||||
result->ProcDecl.link_name = link_name;
|
||||
result->ProcDecl.docs = docs;
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *ast_foreign_block_decl(AstFile *f, Token token, AstNode *foreign_library, Token open, Token close, Array<AstNode *> decls,
|
||||
CommentGroup docs) {
|
||||
AstNode *result = make_ast_node(f, AstNode_ForeignBlockDecl);
|
||||
@@ -1558,27 +1505,6 @@ AstNode *ast_value_decl(AstFile *f, Array<AstNode *> names, AstNode *type, Array
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *ast_value_spec(AstFile *f, Array<AstNode *> names, AstNode *type, Array<AstNode *> values,
|
||||
CommentGroup docs, CommentGroup comment) {
|
||||
AstNode *result = make_ast_node(f, AstNode_ValueSpec);
|
||||
result->ValueSpec.names = names;
|
||||
result->ValueSpec.type = type;
|
||||
result->ValueSpec.values = values;
|
||||
result->ValueSpec.docs = docs;
|
||||
result->ValueSpec.comment = comment;
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *ast_type_spec(AstFile *f, AstNode *name, AstNode *type,
|
||||
CommentGroup docs, CommentGroup comment) {
|
||||
AstNode *result = make_ast_node(f, AstNode_TypeSpec);
|
||||
result->TypeSpec.name = name;
|
||||
result->TypeSpec.type = type;
|
||||
result->TypeSpec.docs = docs;
|
||||
result->TypeSpec.comment = comment;
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *ast_import_spec(AstFile *f, bool is_import, Token relpath, Token import_name, AstNode *cond,
|
||||
CommentGroup docs, CommentGroup comment) {
|
||||
AstNode *result = make_ast_node(f, AstNode_ImportSpec);
|
||||
@@ -1868,8 +1794,6 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
return true;
|
||||
case AstNode_ProcLit:
|
||||
return s->ProcLit.body != NULL;
|
||||
case AstNode_ProcDecl:
|
||||
return s->ProcDecl.body != NULL;
|
||||
|
||||
case AstNode_ValueDecl:
|
||||
if (s->ValueDecl.is_mutable) {
|
||||
@@ -1897,9 +1821,6 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
return is_semicolon_optional_for_node(f, s->ForeignBlockDecl.decls[0]);
|
||||
}
|
||||
break;
|
||||
|
||||
case AstNode_TypeSpec:
|
||||
return is_semicolon_optional_for_node(f, s->TypeSpec.type);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -2764,45 +2685,6 @@ AstNode *parse_type(AstFile *f) {
|
||||
return type;
|
||||
}
|
||||
|
||||
AstNode *parse_proc_decl(AstFile *f) {
|
||||
CommentGroup docs = f->lead_comment;
|
||||
|
||||
TokenKind look_ahead = look_ahead_token_kind(f, 1);
|
||||
if (look_ahead != Token_Ident) {
|
||||
return ast_expr_stmt(f, parse_expr(f, true));
|
||||
}
|
||||
|
||||
Token token = expect_token(f, Token_proc);
|
||||
AstNode *body = NULL;
|
||||
String link_name = {};
|
||||
|
||||
|
||||
bool prev_allow_gen_proc_type = f->allow_gen_proc_type;
|
||||
f->allow_gen_proc_type = true;
|
||||
AstNode *name = parse_ident(f);
|
||||
AstNode *type = parse_proc_type(f, token, &link_name);
|
||||
u64 tags = type->ProcType.tags;
|
||||
f->allow_gen_proc_type = prev_allow_gen_proc_type;
|
||||
|
||||
|
||||
if (allow_token(f, Token_Undef)) {
|
||||
body = NULL;
|
||||
} else if (f->curr_token.kind == Token_OpenBrace) {
|
||||
if ((tags & ProcTag_foreign) != 0) {
|
||||
syntax_error(token, "A procedure tagged as `#foreign` cannot have a body");
|
||||
}
|
||||
AstNode *curr_proc = f->curr_proc;
|
||||
f->curr_proc = type;
|
||||
body = parse_body(f);
|
||||
f->curr_proc = curr_proc;
|
||||
}
|
||||
|
||||
AstNode *decl = ast_proc_decl(f, token, name, type, body, tags, link_name, docs);
|
||||
expect_semicolon(f, decl);
|
||||
return decl;
|
||||
}
|
||||
|
||||
|
||||
#define PARSE_SPEC_FUNC(name) AstNode *name(AstFile *f, CommentGroup docs, Token token)
|
||||
typedef PARSE_SPEC_FUNC(ParseSpecFunc);
|
||||
|
||||
@@ -2841,62 +2723,6 @@ AstNode *parse_gen_decl(AstFile *f, Token token, ParseSpecFunc *func) {
|
||||
return ast_gen_decl(f, token, open, close, specs, docs);
|
||||
}
|
||||
|
||||
PARSE_SPEC_FUNC(parse_value_spec) {
|
||||
bool is_mutable = token.kind != Token_const;
|
||||
|
||||
Array<AstNode *> names = parse_ident_list(f);
|
||||
AstNode *type = NULL;
|
||||
Array<AstNode *> values = {};
|
||||
|
||||
if (allow_token(f, Token_Colon)) {
|
||||
type = parse_type(f);
|
||||
} else if (f->curr_token.kind != Token_Eq &&
|
||||
f->curr_token.kind != Token_Semicolon) {
|
||||
syntax_error(f->curr_token, "Expected separator `:` or `=`");
|
||||
}
|
||||
|
||||
if (allow_token(f, Token_Eq)) {
|
||||
values = parse_rhs_expr_list(f);
|
||||
if (values.count > names.count) {
|
||||
syntax_error(f->curr_token, "Too many values on the right hand side of the declaration");
|
||||
} else if (values.count < names.count && !is_mutable) {
|
||||
syntax_error(f->curr_token, "All constant declarations must be defined");
|
||||
} else if (values.count == 0) {
|
||||
syntax_error(f->curr_token, "Expected an expression for this declaration");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (is_mutable) {
|
||||
if (type == NULL && values.count == 0) {
|
||||
syntax_error(f->curr_token, "Missing variable type or initialization");
|
||||
return ast_bad_decl(f, f->curr_token, f->curr_token);
|
||||
}
|
||||
} else {
|
||||
if (type == NULL && values.count == 0 && names.count > 0) {
|
||||
syntax_error(f->curr_token, "Missing constant value");
|
||||
return ast_bad_decl(f, f->curr_token, f->curr_token);
|
||||
}
|
||||
}
|
||||
|
||||
if (values.data == NULL) {
|
||||
values = make_ast_node_array(f);
|
||||
}
|
||||
|
||||
if (f->expr_level >= 0) {
|
||||
expect_semicolon(f, NULL);
|
||||
}
|
||||
|
||||
return ast_value_spec(f, names, type, values, docs, f->line_comment);
|
||||
}
|
||||
|
||||
PARSE_SPEC_FUNC(parse_type_spec) {
|
||||
AstNode *name = parse_ident(f);
|
||||
AstNode *type = parse_type(f);
|
||||
expect_semicolon(f, type);
|
||||
return ast_type_spec(f, name, type, docs, f->line_comment);
|
||||
}
|
||||
|
||||
PARSE_SPEC_FUNC(parse_import_spec) {
|
||||
AstNode *spec = NULL;
|
||||
if (token.kind == Token_import) {
|
||||
@@ -3034,7 +2860,6 @@ void parse_foreign_block_decl(AstFile *f, Array<AstNode *> *decls) {
|
||||
return;
|
||||
|
||||
case AstNode_ValueDecl:
|
||||
case AstNode_ProcDecl:
|
||||
array_add(decls, decl);
|
||||
return;
|
||||
|
||||
@@ -3056,15 +2881,6 @@ void parse_foreign_block_decl(AstFile *f, Array<AstNode *> *decls) {
|
||||
AstNode *parse_decl(AstFile *f) {
|
||||
ParseSpecFunc *func = NULL;
|
||||
switch (f->curr_token.kind) {
|
||||
case Token_var:
|
||||
case Token_const:
|
||||
func = parse_value_spec;
|
||||
break;
|
||||
|
||||
case Token_type:
|
||||
func = parse_type_spec;
|
||||
break;
|
||||
|
||||
case Token_import:
|
||||
case Token_import_load:
|
||||
func = parse_import_spec;
|
||||
@@ -3103,9 +2919,6 @@ AstNode *parse_decl(AstFile *f) {
|
||||
return ast_foreign_block_decl(f, token, foreign_library, open, close, decls, docs);
|
||||
} break;
|
||||
|
||||
case Token_proc:
|
||||
return parse_proc_decl(f);
|
||||
|
||||
default: {
|
||||
Token tok = f->curr_token;
|
||||
fix_advance_to_next_stmt(f);
|
||||
@@ -3501,7 +3314,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
|
||||
|
||||
isize total_name_count = 0;
|
||||
bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis;
|
||||
bool allow_type_token = f->allow_gen_proc_type && allow_default_parameters;
|
||||
bool allow_type_token = allow_default_parameters;
|
||||
|
||||
while (f->curr_token.kind != follow &&
|
||||
f->curr_token.kind != Token_Colon &&
|
||||
@@ -3886,10 +3699,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
||||
|
||||
case Token_proc: {
|
||||
Token token = f->curr_token; next_token(f);
|
||||
bool prev_allow_gen_proc_type = f->allow_gen_proc_type;
|
||||
f->allow_gen_proc_type = false;
|
||||
AstNode *pt = parse_proc_type(f, token, NULL);
|
||||
f->allow_gen_proc_type = prev_allow_gen_proc_type;
|
||||
if (pt->ProcType.tags != 0) {
|
||||
syntax_error(token, "A procedure type cannot have tags");
|
||||
}
|
||||
@@ -4328,7 +4138,7 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
|
||||
// case Token_var:
|
||||
// case Token_const:
|
||||
case Token_proc:
|
||||
// case Token_proc:
|
||||
// case Token_type:
|
||||
case Token_import:
|
||||
case Token_import_load:
|
||||
|
||||
+8
-8
@@ -2377,12 +2377,12 @@ void ssa_build_proc(ssaModule *m, ssaProc *p) {
|
||||
p->module = m;
|
||||
m->proc = p;
|
||||
|
||||
if (p->decl_info->proc_decl == NULL ||
|
||||
p->decl_info->proc_decl->kind != AstNode_ProcDecl) {
|
||||
if (p->decl_info->proc_lit == NULL ||
|
||||
p->decl_info->proc_lit->kind != AstNode_ProcLit) {
|
||||
return;
|
||||
}
|
||||
|
||||
ast_node(pl, ProcLit, p->decl_info->proc_decl);
|
||||
ast_node(pl, ProcLit, p->decl_info->proc_lit);
|
||||
if (pl->body == NULL) {
|
||||
return;
|
||||
}
|
||||
@@ -2495,14 +2495,14 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
|
||||
} break;
|
||||
|
||||
case Entity_Procedure: {
|
||||
ast_node(pd, ProcDecl, decl->proc_decl);
|
||||
ast_node(pl, ProcLit, decl->proc_lit);
|
||||
String original_name = name;
|
||||
AstNode *body = pd->body;
|
||||
AstNode *body = pl->body;
|
||||
if (e->Procedure.is_foreign) {
|
||||
name = e->token.string; // NOTE(bill): Don't use the mangled name
|
||||
}
|
||||
if (pd->link_name.len > 0) {
|
||||
name = pd->link_name;
|
||||
if (pl->link_name.len > 0) {
|
||||
name = pl->link_name;
|
||||
}
|
||||
|
||||
if (e == entry_point) {
|
||||
@@ -2511,7 +2511,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
|
||||
}
|
||||
|
||||
// ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name);
|
||||
// p->Proc.tags = pd->tags;
|
||||
// p->Proc.tags = pl->tags;
|
||||
|
||||
// ssa_module_add_value(m, e, p);
|
||||
// HashKey hash_name = hash_string(name);
|
||||
|
||||
Reference in New Issue
Block a user