Prefix proc syntax

This commit is contained in:
Ginger Bill
2017-06-12 12:34:55 +01:00
parent 8fafdb185c
commit 33eeb58521
29 changed files with 956 additions and 873 deletions
+11 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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) {