mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-29 10:50:05 +00:00
Prefix proc syntax
This commit is contained in:
+11
-8
@@ -251,17 +251,17 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
|
||||
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
GB_ASSERT(e->type == NULL);
|
||||
if (d->proc_lit->kind != AstNode_ProcLit) {
|
||||
if (d->proc_decl->kind != AstNode_ProcDecl) {
|
||||
// TOOD(bill): Better error message
|
||||
error_node(d->proc_lit, "Expected a procedure to check");
|
||||
error_node(d->proc_decl, "Expected a procedure to check");
|
||||
return;
|
||||
}
|
||||
|
||||
Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false, ProcCC_Odin);
|
||||
e->type = proc_type;
|
||||
ast_node(pd, ProcLit, d->proc_lit);
|
||||
ast_node(pd, ProcDecl, d->proc_decl);
|
||||
|
||||
check_open_scope(c, pd->type);
|
||||
check_procedure_type(c, proc_type, pd->type);
|
||||
@@ -325,7 +325,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
|
||||
name = pd->foreign_name;
|
||||
}
|
||||
|
||||
AstNode *foreign_library = d->proc_lit->ProcLit.foreign_library;
|
||||
AstNode *foreign_library = d->proc_decl->ProcDecl.foreign_library;
|
||||
if (foreign_library == NULL) {
|
||||
error(e->token, "#foreign procedures must declare which library they are from");
|
||||
} else if (foreign_library->kind != AstNode_Ident) {
|
||||
@@ -359,7 +359,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
|
||||
Type *this_type = base_type(e->type);
|
||||
Type *other_type = base_type(f->type);
|
||||
if (!are_signatures_similar_enough(this_type, other_type)) {
|
||||
error_node(d->proc_lit,
|
||||
error_node(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);
|
||||
@@ -384,7 +384,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
|
||||
Entity *f = *found;
|
||||
TokenPos pos = f->token.pos;
|
||||
// TODO(bill): Better error message?
|
||||
error_node(d->proc_lit,
|
||||
error_node(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);
|
||||
@@ -472,7 +472,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
||||
check_type_decl(c, e, d->type_expr, named_type);
|
||||
break;
|
||||
case Entity_Procedure:
|
||||
check_proc_lit(c, e, d);
|
||||
check_proc_decl(c, e, d);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -482,6 +482,9 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
||||
|
||||
|
||||
void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body) {
|
||||
if (body == NULL) {
|
||||
return;
|
||||
}
|
||||
GB_ASSERT(body->kind == AstNode_BlockStmt);
|
||||
|
||||
String proc_name = {};
|
||||
|
||||
+1
-1
@@ -5510,7 +5510,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_lit = pl->type;
|
||||
decl->proc_decl = pl->type;
|
||||
c->context.decl = decl;
|
||||
|
||||
if (pl->tags != 0) {
|
||||
|
||||
+26
-8
@@ -193,7 +193,7 @@ struct DeclInfo {
|
||||
|
||||
AstNode * type_expr;
|
||||
AstNode * init_expr;
|
||||
AstNode * proc_lit; // AstNode_ProcLit
|
||||
AstNode * proc_decl; // AstNode_ProcDecl
|
||||
|
||||
Map<bool> deps; // Key: Entity *
|
||||
Array<BlockLabel> labels;
|
||||
@@ -340,9 +340,9 @@ bool decl_info_has_init(DeclInfo *d) {
|
||||
if (d->init_expr != NULL) {
|
||||
return true;
|
||||
}
|
||||
if (d->proc_lit != NULL) {
|
||||
switch (d->proc_lit->kind) {
|
||||
case_ast_node(pd, ProcLit, d->proc_lit);
|
||||
if (d->proc_decl != NULL) {
|
||||
switch (d->proc_decl->kind) {
|
||||
case_ast_node(pd, ProcDecl, d->proc_decl);
|
||||
if (pd->body != NULL) {
|
||||
return true;
|
||||
}
|
||||
@@ -1542,10 +1542,10 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
||||
d->type_expr = vd->type;
|
||||
d->init_expr = up_init->Alias.expr;
|
||||
#endif
|
||||
} else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
|
||||
d->proc_lit = up_init;
|
||||
d->type_expr = vd->type;
|
||||
// } else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
// e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
|
||||
// d->proc_lit = up_init;
|
||||
// d->type_expr = vd->type;
|
||||
} else {
|
||||
e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, empty_exact_value);
|
||||
d->type_expr = vd->type;
|
||||
@@ -1561,6 +1561,24 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(pd, ProcDecl, decl);
|
||||
AstNode *name = pd->name;
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error_node(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;
|
||||
|
||||
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, pd->tags);
|
||||
d->proc_decl = decl;
|
||||
d->type_expr = pd->type;
|
||||
e->identifier = name;
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
case_end;
|
||||
|
||||
case_ast_node(id, ImportDecl, decl);
|
||||
if (!c->context.scope->is_file) {
|
||||
if (id->is_import) {
|
||||
|
||||
+73
-69
@@ -5884,78 +5884,82 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
map_set(&proc->module->entity_names, hash_pointer(e), name);
|
||||
ir_gen_global_type_name(proc->module, e, name);
|
||||
} break;
|
||||
case Entity_Procedure: {
|
||||
DeclInfo **decl_info = map_get(&proc->module->info->entities, hash_pointer(e));
|
||||
GB_ASSERT(decl_info != NULL);
|
||||
DeclInfo *dl = *decl_info;
|
||||
ast_node(pd, ProcLit, dl->proc_lit);
|
||||
if (pd->body != NULL) {
|
||||
CheckerInfo *info = proc->module->info;
|
||||
|
||||
if (map_get(&proc->module->min_dep_map, hash_pointer(e)) == NULL) {
|
||||
// NOTE(bill): Nothing depends upon it so doesn't need to be built
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent.name-guid
|
||||
String original_name = e->token.string;
|
||||
String pd_name = original_name;
|
||||
if (pd->link_name.len > 0) {
|
||||
pd_name = pd->link_name;
|
||||
}
|
||||
|
||||
isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1;
|
||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||
i32 guid = cast(i32)proc->children.count;
|
||||
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(pd_name), guid);
|
||||
String name = make_string(name_text, name_len-1);
|
||||
|
||||
|
||||
irValue *value = ir_value_procedure(proc->module->allocator,
|
||||
proc->module, e, e->type, pd->type, pd->body, name);
|
||||
|
||||
value->Proc.tags = pd->tags;
|
||||
value->Proc.parent = proc;
|
||||
|
||||
ir_module_add_value(proc->module, e, value);
|
||||
array_add(&proc->children, &value->Proc);
|
||||
array_add(&proc->module->procs_to_generate, value);
|
||||
} else {
|
||||
CheckerInfo *info = proc->module->info;
|
||||
|
||||
// FFI - Foreign function interace
|
||||
String original_name = e->token.string;
|
||||
String name = original_name;
|
||||
if (pd->foreign_name.len > 0) {
|
||||
name = pd->foreign_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);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(pd, ProcDecl, node);
|
||||
AstNode *ident = pd->name;
|
||||
GB_ASSERT(ident->kind == AstNode_Ident);
|
||||
Entity *e = entity_of_ident(proc->module->info, ident);
|
||||
DeclInfo **decl_info = map_get(&proc->module->info->entities, hash_pointer(e));
|
||||
GB_ASSERT(decl_info != NULL);
|
||||
DeclInfo *dl = *decl_info;
|
||||
|
||||
if (pd->body != NULL) {
|
||||
CheckerInfo *info = proc->module->info;
|
||||
|
||||
if (map_get(&proc->module->min_dep_map, hash_pointer(e)) == NULL) {
|
||||
// NOTE(bill): Nothing depends upon it so doesn't need to be built
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent.name-guid
|
||||
String original_name = e->token.string;
|
||||
String pd_name = original_name;
|
||||
if (pd->link_name.len > 0) {
|
||||
pd_name = pd->link_name;
|
||||
}
|
||||
|
||||
isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1;
|
||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||
i32 guid = cast(i32)proc->children.count;
|
||||
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(pd_name), guid);
|
||||
String name = make_string(name_text, name_len-1);
|
||||
|
||||
|
||||
irValue *value = ir_value_procedure(proc->module->allocator,
|
||||
proc->module, e, e->type, pd->type, pd->body, name);
|
||||
|
||||
value->Proc.tags = pd->tags;
|
||||
value->Proc.parent = proc;
|
||||
|
||||
ir_module_add_value(proc->module, e, value);
|
||||
array_add(&proc->children, &value->Proc);
|
||||
array_add(&proc->module->procs_to_generate, value);
|
||||
} else {
|
||||
CheckerInfo *info = proc->module->info;
|
||||
|
||||
// FFI - Foreign function interace
|
||||
String original_name = e->token.string;
|
||||
String name = original_name;
|
||||
if (pd->foreign_name.len > 0) {
|
||||
name = pd->foreign_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;
|
||||
|
||||
case_ast_node(as, AssignStmt, node);
|
||||
ir_emit_comment(proc, str_lit("AssignStmt"));
|
||||
|
||||
@@ -7232,7 +7236,7 @@ void ir_gen_tree(irGen *s) {
|
||||
} break;
|
||||
|
||||
case Entity_Procedure: {
|
||||
ast_node(pd, ProcLit, decl->proc_lit);
|
||||
ast_node(pd, ProcDecl, decl->proc_decl);
|
||||
String original_name = name;
|
||||
AstNode *body = pd->body;
|
||||
if (e->Procedure.is_foreign) {
|
||||
@@ -7245,7 +7249,7 @@ void ir_gen_tree(irGen *s) {
|
||||
name = pd->link_name;
|
||||
}
|
||||
|
||||
AstNode *type_expr = decl->proc_lit->ProcLit.type;
|
||||
AstNode *type_expr = pd->type;
|
||||
|
||||
irValue *p = ir_value_procedure(a, m, e, e->type, type_expr, body, name);
|
||||
p->Proc.tags = pd->tags;
|
||||
|
||||
+62
-7
@@ -304,6 +304,16 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||
Array<AstNode *> values; \
|
||||
u32 flags; \
|
||||
}) \
|
||||
AST_NODE_KIND(ProcDecl, "procedure declaration", struct { \
|
||||
Token token; \
|
||||
AstNode *name; \
|
||||
AstNode *type; \
|
||||
AstNode *body; \
|
||||
u64 tags; \
|
||||
AstNode *foreign_library; \
|
||||
String foreign_name; \
|
||||
String link_name; \
|
||||
}) \
|
||||
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
||||
Token token; \
|
||||
bool is_import; \
|
||||
@@ -526,6 +536,7 @@ Token ast_node_token(AstNode *node) {
|
||||
|
||||
case AstNode_BadDecl: return node->BadDecl.begin;
|
||||
case AstNode_ValueDecl: return node->ValueDecl.token;
|
||||
case AstNode_ProcDecl: return node->ProcDecl.token;
|
||||
case AstNode_ImportDecl: return node->ImportDecl.token;
|
||||
case AstNode_ForeignLibrary: return node->ForeignLibrary.token;
|
||||
case AstNode_Label: return node->Label.token;
|
||||
@@ -1421,6 +1432,20 @@ AstNode *ast_value_decl(AstFile *f, Token token, Array<AstNode *> names, AstNode
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *ast_proc_decl(AstFile *f, Token token, AstNode *name, AstNode *type, AstNode *body,
|
||||
u64 tags, AstNode *foreign_library, String foreign_name, String link_name) {
|
||||
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.foreign_library = foreign_library;
|
||||
result->ProcDecl.foreign_name = foreign_name;
|
||||
result->ProcDecl.link_name = link_name;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AstNode *ast_import_decl(AstFile *f, Token token, bool is_import, Token relpath, Token import_name, AstNode *cond) {
|
||||
AstNode *result = make_ast_node(f, AstNode_ImportDecl);
|
||||
@@ -1644,6 +1669,8 @@ 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.token.kind != Token_var) {
|
||||
@@ -1693,7 +1720,7 @@ void expect_semicolon(AstFile *f, AstNode *s) {
|
||||
|
||||
|
||||
AstNode * parse_expr(AstFile *f, bool lhs);
|
||||
AstNode * parse_proc_type(AstFile *f, AstNode **foreign_library, String *foreign_name, String *link_name);
|
||||
AstNode * parse_proc_type(AstFile *f, Token proc_token, AstNode **foreign_library, String *foreign_name, String *link_name);
|
||||
Array<AstNode *> parse_stmt_list(AstFile *f);
|
||||
AstNode * parse_stmt(AstFile *f);
|
||||
AstNode * parse_body(AstFile *f);
|
||||
@@ -2051,11 +2078,11 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
|
||||
// Parse Procedure Type or Literal
|
||||
case Token_proc: {
|
||||
Token token = f->curr_token;
|
||||
Token token = f->curr_token; next_token(f);
|
||||
AstNode *foreign_library = NULL;
|
||||
String foreign_name = {};
|
||||
String link_name = {};
|
||||
AstNode *type = parse_proc_type(f, &foreign_library, &foreign_name, &link_name);
|
||||
AstNode *type = parse_proc_type(f, token, &foreign_library, &foreign_name, &link_name);
|
||||
u64 tags = type->ProcType.tags;
|
||||
|
||||
if (f->curr_token.kind == Token_OpenBrace) {
|
||||
@@ -2532,6 +2559,30 @@ AstNode *parse_value_decl(AstFile *f, Token token) {
|
||||
return ast_value_decl(f, token, lhs, type, values);
|
||||
}
|
||||
|
||||
AstNode *parse_proc_decl(AstFile *f) {
|
||||
Token token = expect_token(f, Token_proc);
|
||||
AstNode *body = NULL;
|
||||
AstNode *foreign_library = NULL;
|
||||
String foreign_name = {};
|
||||
String link_name = {};
|
||||
|
||||
AstNode *name = parse_ident(f);
|
||||
AstNode *type = parse_proc_type(f, token, &foreign_library, &foreign_name, &link_name);
|
||||
u64 tags = type->ProcType.tags;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return ast_proc_decl(f, token, name, type, body, tags, foreign_library, foreign_name, link_name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) {
|
||||
@@ -2671,11 +2722,10 @@ AstNode *parse_results(AstFile *f) {
|
||||
return list;
|
||||
}
|
||||
|
||||
AstNode *parse_proc_type(AstFile *f, AstNode **foreign_library_, String *foreign_name_, String *link_name_) {
|
||||
AstNode *parse_proc_type(AstFile *f, Token proc_token, AstNode **foreign_library_, String *foreign_name_, String *link_name_) {
|
||||
AstNode *params = {};
|
||||
AstNode *results = {};
|
||||
|
||||
Token proc_token = expect_token(f, Token_proc);
|
||||
expect_token(f, Token_OpenParen);
|
||||
params = parse_field_list(f, NULL, FieldFlag_Signature, Token_CloseParen);
|
||||
expect_token_after(f, Token_CloseParen, "parameter list");
|
||||
@@ -3243,8 +3293,8 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
||||
}
|
||||
|
||||
case Token_proc: {
|
||||
Token token = f->curr_token;
|
||||
AstNode *pt = parse_proc_type(f, NULL, NULL, NULL);
|
||||
Token token = f->curr_token; next_token(f);
|
||||
AstNode *pt = parse_proc_type(f, token, NULL, NULL, NULL);
|
||||
if (pt->ProcType.tags != 0) {
|
||||
syntax_error(token, "A procedure type cannot have tags");
|
||||
}
|
||||
@@ -3640,6 +3690,11 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
|
||||
case Token_proc:
|
||||
s = parse_proc_decl(f);
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
|
||||
|
||||
case Token_if: return parse_if_stmt(f);
|
||||
case Token_when: return parse_when_stmt(f);
|
||||
|
||||
+4
-4
@@ -2435,12 +2435,12 @@ void ssa_build_proc(ssaModule *m, ssaProc *p) {
|
||||
p->module = m;
|
||||
m->proc = p;
|
||||
|
||||
if (p->decl_info->proc_lit == NULL ||
|
||||
p->decl_info->proc_lit->kind != AstNode_ProcLit) {
|
||||
if (p->decl_info->proc_decl == NULL ||
|
||||
p->decl_info->proc_decl->kind != AstNode_ProcDecl) {
|
||||
return;
|
||||
}
|
||||
|
||||
ast_node(pl, ProcLit, p->decl_info->proc_lit);
|
||||
ast_node(pl, ProcLit, p->decl_info->proc_decl);
|
||||
if (pl->body == NULL) {
|
||||
return;
|
||||
}
|
||||
@@ -2553,7 +2553,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
|
||||
} break;
|
||||
|
||||
case Entity_Procedure: {
|
||||
ast_node(pd, ProcLit, decl->proc_lit);
|
||||
ast_node(pd, ProcDecl, decl->proc_decl);
|
||||
String original_name = name;
|
||||
AstNode *body = pd->body;
|
||||
if (e->Procedure.is_foreign) {
|
||||
|
||||
Reference in New Issue
Block a user