diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-01-01 20:41:10 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-01-01 20:41:10 +0000 |
| commit | 9202bd1b0640737ce9d843f8d308debe45fc9a90 (patch) | |
| tree | f3153718034b50a3e2bcdd2d3608f30df7622958 /src | |
| parent | a48e0c7179cfe78f3163a3e471f7401502d8c437 (diff) | |
Nearly finished Jai-like declarations
Diffstat (limited to 'src')
| -rw-r--r-- | src/checker/checker.c | 36 | ||||
| -rw-r--r-- | src/checker/decl.c | 267 | ||||
| -rw-r--r-- | src/checker/expr.c | 49 | ||||
| -rw-r--r-- | src/checker/stmt.c | 25 | ||||
| -rw-r--r-- | src/parser.c | 137 | ||||
| -rw-r--r-- | src/ssa.c | 221 |
6 files changed, 270 insertions, 465 deletions
diff --git a/src/checker/checker.c b/src/checker/checker.c index 64bccbd14..ace13dcab 100644 --- a/src/checker/checker.c +++ b/src/checker/checker.c @@ -308,11 +308,6 @@ bool decl_info_has_init(DeclInfo *d) { } if (d->proc_decl != NULL) { switch (d->proc_decl->kind) { - case_ast_node(pd, ProcDecl, d->proc_decl); - if (pd->body != NULL) { - return true; - } - case_end; case_ast_node(pd, ProcLit, d->proc_decl); if (pd->body != NULL) { return true; @@ -1260,23 +1255,6 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As DelayedDecl di = {parent_scope, spec}; array_add(&c->delayed_imports, di); case_end; - - case_ast_node(ts, TypeSpec, spec); - if (ts->name->kind != AstNode_Ident) { - error_node(ts->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[ts->name->kind])); - continue; - } - ast_node(n, Ident, ts->name); - - Entity *e = make_entity_type_name(c->allocator, parent_scope, *n, NULL); - e->identifier = ts->name; - - DeclInfo *d = make_declaration_info(c->allocator, e->scope); - d->type_expr = ts->type; - d->init_expr = ts->type; - add_entity_and_decl_info(c, ts->name, e, d); - case_end; - default: error(ast_node_token(spec), "Invalid specification in declaration: `%.*s`", LIT(ast_node_strings[spec->kind])); break; @@ -1293,20 +1271,6 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As DelayedDecl di = {parent_scope, decl}; array_add(&c->delayed_foreign_libraries, di); case_end; - case_ast_node(pd, ProcDecl, decl); - if (pd->name->kind != AstNode_Ident) { - error_node(pd->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[pd->name->kind])); - continue; - } - ast_node(n, Ident, pd->name); - Token token = *n; - Entity *e = make_entity_procedure(c->allocator, parent_scope, token, NULL, pd->tags); - e->identifier = pd->name; - DeclInfo *d = make_declaration_info(c->allocator, e->scope); - d->proc_decl = decl; - add_entity_and_decl_info(c, pd->name, e, d); - case_end; - default: if (parent_scope->is_file) { error_node(decl, "Only declarations are allowed at file scope"); diff --git a/src/checker/decl.c b/src/checker/decl.c index 179e6f67c..ec236ef2f 100644 --- a/src/checker/decl.c +++ b/src/checker/decl.c @@ -282,6 +282,10 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, check_init_constant(c, e, &operand); c->context.iota = (ExactValue){0}; + + if (e->type == t_invalid) { + error(e->token, "Illegal cyclic declaration"); + } } @@ -326,224 +330,119 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) { void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { GB_ASSERT(e->type == NULL); + if (d->proc_decl->kind != AstNode_ProcLit) { + // TOOD(bill): Better error message + 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; - if (d->proc_decl->kind == AstNode_ProcDecl) { - ast_node(pd, ProcDecl, d->proc_decl); - - check_open_scope(c, pd->type); - check_procedure_type(c, proc_type, pd->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; - - if ((d->scope->is_file || d->scope->is_global) && - str_eq(e->token.string, str_lit("main"))) { - if (proc_type != NULL) { - TypeProc *pt = &proc_type->Proc; - if (pt->param_count != 0 || - pt->result_count != 0) { - gbString str = type_to_string(proc_type); - error(e->token, "Procedure type of `main` was expected to be `proc()`, got %s", str); - gb_string_free(str); - } + ast_node(pd, ProcLit, d->proc_decl); + + check_open_scope(c, pd->type); + check_procedure_type(c, proc_type, pd->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; + + if ((d->scope->is_file || d->scope->is_global) && + str_eq(e->token.string, str_lit("main"))) { + if (proc_type != NULL) { + TypeProc *pt = &proc_type->Proc; + if (pt->param_count != 0 || + pt->result_count != 0) { + gbString str = type_to_string(proc_type); + error(e->token, "Procedure type of `main` was expected to be `proc()`, got %s", str); + gb_string_free(str); } } + } - if (is_inline && is_no_inline) { - error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure"); - } - - if (is_foreign && is_link_name) { - error_node(pd->type, "You cannot apply both `foreign` and `link_name` to a procedure"); - } else if (is_foreign && is_export) { - error_node(pd->type, "You cannot apply both `foreign` and `export` to a procedure"); - } - - - if (pd->body != NULL) { - if (is_foreign) { - error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body"); - } - - if (proc_type->Proc.calling_convention != ProcCC_Odin) { - error_node(d->proc_decl, "An internal procedure may only have the Odin calling convention"); - proc_type->Proc.calling_convention = ProcCC_Odin; - } + if (is_inline && is_no_inline) { + error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure"); + } - d->scope = c->context.scope; + if (is_foreign && is_link_name) { + error_node(pd->type, "You cannot apply both `foreign` and `link_name` to a procedure"); + } else if (is_foreign && is_export) { + error_node(pd->type, "You cannot apply both `foreign` and `export` to a procedure"); + } - GB_ASSERT(pd->body->kind == AstNode_BlockStmt); - check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pd->body, pd->tags); - } + if (pd->body != NULL) { if (is_foreign) { - MapEntity *fp = &c->info.foreign_procs; - AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl; - String name = proc_decl->name->Ident.string; - if (proc_decl->foreign_name.len > 0) { - name = proc_decl->foreign_name; - } - - e->Procedure.is_foreign = true; - e->Procedure.foreign_name = name; - - HashKey key = hash_string(name); - Entity **found = map_entity_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_signatures_similar_enough(this_type, other_type)) { - 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); - } - } else { - map_entity_set(fp, key, e); - } - } else { - String name = e->token.string; - if (is_link_name) { - AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl; - name = proc_decl->link_name; - } - - if (is_link_name || is_export) { - MapEntity *fp = &c->info.foreign_procs; - - e->Procedure.link_name = name; - - HashKey key = hash_string(name); - Entity **found = map_entity_get(fp, key); - if (found) { - Entity *f = *found; - TokenPos pos = f->token.pos; - // TODO(bill): Better error message? - 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); - } else { - map_entity_set(fp, key, e); - } - } + error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body"); } - check_close_scope(c); - } else if (d->proc_decl->kind == AstNode_ProcLit) { - ast_node(pd, ProcLit, d->proc_decl); - - check_open_scope(c, pd->type); - check_procedure_type(c, proc_type, pd->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; - - if ((d->scope->is_file || d->scope->is_global) && - str_eq(e->token.string, str_lit("main"))) { - if (proc_type != NULL) { - TypeProc *pt = &proc_type->Proc; - if (pt->param_count != 0 || - pt->result_count != 0) { - gbString str = type_to_string(proc_type); - error(e->token, "Procedure type of `main` was expected to be `proc()`, got %s", str); - gb_string_free(str); - } - } + if (proc_type->Proc.calling_convention != ProcCC_Odin) { + error_node(d->proc_decl, "An internal procedure may only have the Odin calling convention"); + proc_type->Proc.calling_convention = ProcCC_Odin; } - if (is_inline && is_no_inline) { - error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure"); - } + 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); + } - if (is_foreign && is_link_name) { - error_node(pd->type, "You cannot apply both `foreign` and `link_name` to a procedure"); - } else if (is_foreign && is_export) { - error_node(pd->type, "You cannot apply both `foreign` and `export` to a procedure"); + if (is_foreign) { + MapEntity *fp = &c->info.foreign_procs; + String name = e->token.string; + if (pd->foreign_name.len > 0) { + name = pd->foreign_name; } + e->Procedure.is_foreign = true; + e->Procedure.foreign_name = name; - if (pd->body != NULL) { - if (is_foreign) { - error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body"); - } - - if (proc_type->Proc.calling_convention != ProcCC_Odin) { - error_node(d->proc_decl, "An internal procedure may only have the Odin calling convention"); - proc_type->Proc.calling_convention = ProcCC_Odin; + HashKey key = hash_string(name); + Entity **found = map_entity_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_signatures_similar_enough(this_type, other_type)) { + 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); } - - 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); + } else { + map_entity_set(fp, key, e); + } + } else { + String name = e->token.string; + if (is_link_name) { + name = pd->link_name; } - if (is_foreign) { + if (is_link_name || is_export) { MapEntity *fp = &c->info.foreign_procs; - String name = e->token.string; - if (pd->foreign_name.len > 0) { - name = pd->foreign_name; - } - e->Procedure.is_foreign = true; - e->Procedure.foreign_name = name; + e->Procedure.link_name = name; HashKey key = hash_string(name); Entity **found = map_entity_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_signatures_similar_enough(this_type, other_type)) { - 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); - } + // TODO(bill): Better error message? + 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); } else { map_entity_set(fp, key, e); } - } else { - String name = e->token.string; - if (is_link_name) { - name = pd->link_name; - } - - if (is_link_name || is_export) { - MapEntity *fp = &c->info.foreign_procs; - - e->Procedure.link_name = name; - - HashKey key = hash_string(name); - Entity **found = map_entity_get(fp, key); - if (found) { - Entity *f = *found; - TokenPos pos = f->token.pos; - // TODO(bill): Better error message? - 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); - } else { - map_entity_set(fp, key, e); - } - } } - - check_close_scope(c); } + + check_close_scope(c); } void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count, AstNode *type_expr, AstNode *init_expr) { diff --git a/src/checker/expr.c b/src/checker/expr.c index 08f919827..33dfa9e44 100644 --- a/src/checker/expr.c +++ b/src/checker/expr.c @@ -137,43 +137,6 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie switch (spec->kind) { case_ast_node(bd, BadDecl, spec); case_end; - case_ast_node(ts, TypeSpec, spec); - if (ts->name->kind != AstNode_Ident) { - error_node(ts->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[ts->name->kind])); - break; - } - - Token name_token = ts->name->Ident; - - Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, NULL); - e->identifier = ts->name; - - DeclInfo *d = make_declaration_info(c->allocator, e->scope); - d->type_expr = ts->type; - - add_entity_and_decl_info(c, ts->name, e, d); - - DelayedEntity delay = {ts->name, e, d}; - array_add(delayed_entities, delay); - - - if (dof != NULL) { - if (str_eq(name_token.string, str_lit("_"))) { - dof->other_fields[dof->other_field_index++] = e; - } else { - HashKey key = hash_string(name_token.string); - if (map_entity_get(dof->entity_map, key) != NULL) { - // TODO(bill): Scope checking already checks the declaration - error(name_token, "`%.*s` is already declared in this record", LIT(name_token.string)); - } else { - map_entity_set(dof->entity_map, key, e); - dof->other_fields[dof->other_field_index++] = e; - } - add_entity(c, c->context.scope, ts->name, e); - add_entity_use(c, ts->name, e); - } - } - case_end; } } case_end; @@ -975,7 +938,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) { } if (e == e_iota) { if (c->context.iota.kind == ExactValue_Invalid) { - error(e->token, "Use of `iota` outside a constant declaration is not allowed"); + error(e->token, "Use of `iota` outside a enumeration is not allowed"); return; } o->value = c->context.iota; @@ -1141,6 +1104,11 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { } case_end; + case_ast_node(ht, HelperType, e); + type = check_type(c, ht->type); + goto end; + case_end; + case_ast_node(pt, PointerType, e); Type *elem = check_type(c, pt->type); type = make_type_pointer(c->allocator, elem); @@ -4825,6 +4793,11 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = gb_string_appendc(str, "{"); str = gb_string_appendc(str, "}"); case_end; + + case_ast_node(ht, HelperType, node); + str = gb_string_appendc(str, "type "); + str = write_expr_to_string(str, ht->type); + case_end; } return str; diff --git a/src/checker/stmt.c b/src/checker/stmt.c index d5848a2b2..c4c7cf3f2 100644 --- a/src/checker/stmt.c +++ b/src/checker/stmt.c @@ -1170,36 +1170,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { switch (spec->kind) { case_ast_node(bd, BadDecl, spec); case_end; - case_ast_node(ts, TypeSpec, spec); - // NOTE(bill): Handled elsewhere - case_end; - default: error(ast_node_token(spec), "Invalid specification in declaration: `%.*s`", LIT(ast_node_strings[spec->kind])); break; } } case_end; - - case_ast_node(pd, ProcDecl, node); - // NOTE(bill): Handled elsewhere - #if 1 - // NOTE(bill): This must be handled here so it has access to the parent scope stuff - // e.g. using - if (pd->name->kind != AstNode_Ident) { - error_node(pd->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[pd->name->kind])); - break; - } - - Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->Ident, NULL, pd->tags); - e->identifier = pd->name; - - DeclInfo *d = make_declaration_info(c->allocator, e->scope); - d->proc_decl = node; - - add_entity_and_decl_info(c, pd->name, e, d); - check_entity_decl(c, e, d, NULL); - #endif - case_end; } } diff --git a/src/parser.c b/src/parser.c index 1a659da7a..8546e692a 100644 --- a/src/parser.c +++ b/src/parser.c @@ -281,15 +281,6 @@ AST_NODE_KIND(_DeclBegin, "", i32) \ AstNodeArray values; \ u64 tags; \ }) \ - AST_NODE_KIND(ProcDecl, "procedure declaration", struct { \ - AstNode *name; \ - AstNode *type; \ - AstNode *body; \ - u64 tags; \ - String foreign_name; \ - String link_name; \ - AstNode *note; \ - }) \ AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \ Token token, filepath; \ String base_dir; \ @@ -303,6 +294,10 @@ AST_NODE_KIND(_DeclEnd, "", i32) \ bool is_using; \ }) \ AST_NODE_KIND(_TypeBegin, "", i32) \ + AST_NODE_KIND(HelperType, "type", struct { \ + Token token; \ + AstNode *type; \ + }) \ AST_NODE_KIND(ProcType, "procedure type", struct { \ Token token; \ AstNodeArray params; \ @@ -501,8 +496,6 @@ Token ast_node_token(AstNode *node) { return node->GenericDecl.token; case AstNode_ValueDecl: return ast_node_token(node->ValueDecl.names.e[0]); - case AstNode_ProcDecl: - return ast_node_token(node->ProcDecl.name); case AstNode_ForeignLibrary: return node->ForeignLibrary.token; @@ -519,6 +512,10 @@ Token ast_node_token(AstNode *node) { return ast_node_token(node->Field.type); } } + + + case AstNode_HelperType: + return node->HelperType.token; case AstNode_ProcType: return node->ProcType.token; case AstNode_PointerType: @@ -969,6 +966,15 @@ AstNode *make_field(AstFile *f, AstNodeArray names, AstNode *type, bool is_using return result; } + +AstNode *make_helper_type(AstFile *f, Token token, AstNode *type) { + AstNode *result = make_node(f, AstNode_HelperType); + result->HelperType.token = token; + result->HelperType.type = type; + return result; +} + + AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArray results, u64 tags, ProcCallingConvention calling_convention) { AstNode *result = make_node(f, AstNode_ProcType); result->ProcType.token = token; @@ -979,17 +985,6 @@ AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArr return result; } -AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String link_name) { - AstNode *result = make_node(f, AstNode_ProcDecl); - result->ProcDecl.name = name; - result->ProcDecl.type = proc_type; - result->ProcDecl.body = body; - result->ProcDecl.tags = tags; - result->ProcDecl.foreign_name = foreign_name; - result->ProcDecl.link_name = link_name; - return result; -} - AstNode *make_pointer_type(AstFile *f, Token token, AstNode *type) { AstNode *result = make_node(f, AstNode_PointerType); result->PointerType.token = token; @@ -1264,6 +1259,52 @@ Token expect_closing(AstFile *f, TokenKind kind, String context) { return expect_token(f, kind); } +bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) { + if (s == NULL) { + return false; + } + + switch (s->kind) { + case AstNode_HelperType: + return is_semicolon_optional_for_node(f, s->HelperType.type); + + case AstNode_StructType: + case AstNode_UnionType: + case AstNode_RawUnionType: + case AstNode_EnumType: + return true; + case AstNode_ProcLit: + return true; + + case AstNode_ValueDecl: + if (!s->ValueDecl.is_var) { + if (s->ValueDecl.values.count > 0) { + AstNode *last = s->ValueDecl.values.e[s->ValueDecl.values.count-1]; + return is_semicolon_optional_for_node(f, last); + } + } + break; + + case AstNode_GenericDecl: + if (s->GenericDecl.close.kind == Token_CloseBrace) { + return true; + } else if (s->GenericDecl.token.kind == Token_type) { + if (f->prev_token.kind == Token_CloseBrace) { + return true; + } + } + break; + + case AstNode_TypeSpec: + if (f->prev_token.kind == Token_CloseBrace) { + return true; + } + break; + } + + return false; +} + void expect_semicolon(AstFile *f, AstNode *s) { if (allow_token(f, Token_Semicolon)) { return; @@ -1277,24 +1318,8 @@ void expect_semicolon(AstFile *f, AstNode *s) { if (s != NULL) { if (prev_token.pos.line != f->curr_token.pos.line) { - switch (s->kind) { - case AstNode_ProcDecl: + if (is_semicolon_optional_for_node(f, s)) { return; - case AstNode_GenericDecl: - if (s->GenericDecl.close.kind == Token_CloseBrace) { - return; - } else if (s->GenericDecl.token.kind == Token_type) { - if (f->prev_token.kind == Token_CloseBrace) { - return; - } - } - break; - - case AstNode_TypeSpec: - if (f->prev_token.kind == Token_CloseBrace) { - return; - } - break; } } else { switch (s->kind) { @@ -1319,7 +1344,6 @@ AstNode * parse_proc_type(AstFile *f, String *foreign_name_, String *link_nam AstNodeArray parse_stmt_list(AstFile *f); AstNode * parse_stmt(AstFile *f); AstNode * parse_body(AstFile *f); -AstNode * parse_proc_decl(AstFile *f); void parse_proc_signature(AstFile *f, AstNodeArray *params, AstNodeArray *results); @@ -1571,6 +1595,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n AstNodeArray parse_lhs_expr_list(AstFile *f); AstNodeArray parse_rhs_expr_list(AstFile *f); AstNode * parse_simple_stmt (AstFile *f); +AstNode * parse_type (AstFile *f); AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) { if (statement == NULL) { @@ -1745,10 +1770,9 @@ AstNode *parse_operand(AstFile *f, bool lhs) { String foreign_name = {0}; String link_name = {0}; AstNode *type = parse_proc_type(f, &foreign_name, &link_name); + u64 tags = type->ProcType.tags; if (f->curr_token.kind == Token_OpenBrace) { - u64 tags = type->ProcType.tags; - if ((tags & ProcTag_foreign) != 0) { syntax_error(token, "A procedure tagged as `#foreign` cannot have a body"); } @@ -1760,6 +1784,13 @@ AstNode *parse_operand(AstFile *f, bool lhs) { return make_proc_lit(f, type, body, tags, foreign_name, link_name); } + if ((tags & ProcTag_foreign) != 0) { + return make_proc_lit(f, type, NULL, tags, foreign_name, link_name); + } + if ((tags & ProcTag_link_name) != 0) { + syntax_error(token, "A procedure typed cannot be tagged with `#link_name`"); + } + return type; } @@ -1932,7 +1963,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { return operand; } -AstNode *parse_type(AstFile *f); AstNode *parse_unary_expr(AstFile *f, bool lhs) { switch (f->curr_token.kind) { @@ -2240,17 +2270,6 @@ PARSE_SPEC_PROC(parse_include_spec) { AstNode *parse_decl(AstFile *f) { switch (f->curr_token.kind) { - // case Token_var: - // case Token_const: - // return parse_generic_decl(f, f->curr_token.kind, parse_value_spec); - - case Token_type: - return parse_generic_decl(f, f->curr_token.kind, parse_type_spec); - - case Token_proc: - // TODO(bill): Should I allow procedures to use the generic declaration syntax? - return parse_proc_decl(f); - case Token_import: return parse_generic_decl(f, f->curr_token.kind, parse_import_spec); case Token_include: @@ -2504,6 +2523,12 @@ AstNode *parse_identifier_or_type(AstFile *f) { return e; } + case Token_type: { + Token token = expect_token(f, Token_type); + AstNode *type = parse_type(f); + return make_helper_type(f, token, type); + } + case Token_Pointer: { Token token = expect_token(f, Token_Pointer); AstNode *elem = parse_type(f); @@ -2681,7 +2706,7 @@ AstNode *parse_body(AstFile *f) { } - +/* AstNode *parse_proc_decl(AstFile *f) { if (look_ahead_token_kind(f, 1) == Token_OpenParen) { // NOTE(bill): It's an anonymous procedure @@ -2720,7 +2745,7 @@ AstNode *parse_proc_decl(AstFile *f) { } return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name); -} +} */ AstNode *parse_if_stmt(AstFile *f) { if (f->curr_proc == NULL) { @@ -3978,104 +3978,96 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) { } gb_temp_arena_memory_end(tmp); - } - case_end; - - case_ast_node(gd, GenericDecl, node); - for_array(spec_index, gd->specs) { - AstNode *spec = gd->specs.e[spec_index]; - switch (spec->kind) { - case_ast_node(ts, TypeSpec, spec); - // NOTE(bill): Generate a new name - // parent_proc.name-guid - String ts_name = ts->name->Ident.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); - - Entity **found = map_entity_get(&proc->module->info->definitions, hash_pointer(ts->name)); - GB_ASSERT(found != NULL); - Entity *e = *found; - ssaValue *value = ssa_make_value_type_name(proc->module->allocator, - name, e->type); - map_string_set(&proc->module->type_names, hash_pointer(e->type), name); - ssa_gen_global_type_name(proc->module, e, name); - case_end; - } - } - case_end; - - case_ast_node(pd, ProcDecl, node); - if (pd->body != NULL) { - CheckerInfo *info = proc->module->info; - - Entity **found = map_entity_get(&info->definitions, hash_pointer(pd->name)); - GB_ASSERT_MSG(found != NULL, "Unable to find: %.*s", LIT(pd->name->Ident.string)); - Entity *e = *found; - - - if (map_entity_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 = pd->name->Ident.string; - String pd_name = original_name; - if (pd->link_name.len > 0) { - pd_name = pd->link_name; - } + } else { + for_array(i, vd->names) { + AstNode *ident = vd->names.e[i]; + GB_ASSERT(ident->kind == AstNode_Ident); + Entity *e = entity_of_ident(proc->module->info, ident); + GB_ASSERT(e != NULL); + switch (e->kind) { + case 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); + + ssaValue *value = ssa_make_value_type_name(proc->module->allocator, + name, e->type); + map_string_set(&proc->module->type_names, hash_pointer(e->type), name); + ssa_gen_global_type_name(proc->module, e, name); + } break; + case Entity_Procedure: { + DeclInfo **decl_info = map_decl_info_get(&proc->module->info->entities, hash_pointer(e)); + GB_ASSERT(decl_info != NULL); + DeclInfo *dl = *decl_info; + ast_node(pd, ProcLit, dl->proc_decl); + if (pd->body != NULL) { + CheckerInfo *info = proc->module->info; + + if (map_entity_get(&proc->module->min_dep_map, hash_pointer(e)) == NULL) { + // NOTE(bill): Nothing depends upon it so doesn't need to be built + break; + } - 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); + // 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); - ssaValue *value = ssa_make_value_procedure(proc->module->allocator, - proc->module, e, e->type, pd->type, pd->body, name); - value->Proc.tags = pd->tags; - value->Proc.parent = proc; + ssaValue *value = ssa_make_value_procedure(proc->module->allocator, + proc->module, e, e->type, pd->type, pd->body, name); - ssa_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; + value->Proc.tags = pd->tags; + value->Proc.parent = proc; - Entity **found = map_entity_get(&info->definitions, hash_pointer(pd->name)); - GB_ASSERT_MSG(found != NULL, "Unable to find: %.*s", LIT(pd->name->Ident.string)); - Entity *e = *found; + ssa_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 = pd->name->Ident.string; - String name = original_name; - if (pd->foreign_name.len > 0) { - name = pd->foreign_name; - } + // FFI - Foreign function interace + String original_name = e->token.string; + String name = original_name; + if (pd->foreign_name.len > 0) { + name = pd->foreign_name; + } - ssaValue *value = ssa_make_value_procedure(proc->module->allocator, - proc->module, e, e->type, pd->type, pd->body, name); + ssaValue *value = ssa_make_value_procedure(proc->module->allocator, + proc->module, e, e->type, pd->type, pd->body, name); - value->Proc.tags = pd->tags; + value->Proc.tags = pd->tags; - ssa_module_add_value(proc->module, e, value); - ssa_build_proc(value, proc); + ssa_module_add_value(proc->module, e, value); + ssa_build_proc(value, proc); - if (value->Proc.tags & ProcTag_foreign) { - HashKey key = hash_string(name); - ssaValue **prev_value = map_ssa_value_get(&proc->module->members, key); - if (prev_value == NULL) { - // NOTE(bill): Don't do mutliple declarations in the IR - map_ssa_value_set(&proc->module->members, key, value); + if (value->Proc.tags & ProcTag_foreign) { + HashKey key = hash_string(name); + ssaValue **prev_value = map_ssa_value_get(&proc->module->members, key); + if (prev_value == NULL) { + // NOTE(bill): Don't do mutliple declarations in the IR + map_ssa_value_set(&proc->module->members, key, value); + } + } else { + array_add(&proc->children, &value->Proc); + } + } + } break; } - } else { - array_add(&proc->children, &value->Proc); } } case_end; @@ -5034,48 +5026,25 @@ void ssa_gen_tree(ssaGen *s) { } break; case Entity_Procedure: { - if (decl->proc_decl->kind == AstNode_ProcDecl) { - AstNodeProcDecl *pd = &decl->proc_decl->ProcDecl; - String original_name = name; - AstNode *body = pd->body; - if (e->Procedure.is_foreign) { - name = e->token.string; // NOTE(bill): Don't use the mangled name - } - if (pd->foreign_name.len > 0) { - name = pd->foreign_name; - } else if (pd->link_name.len > 0) { - name = pd->link_name; - } - - ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); - p->Proc.tags = pd->tags; - - ssa_module_add_value(m, e, p); - HashKey hash_name = hash_string(name); - if (map_ssa_value_get(&m->members, hash_name) == NULL) { - map_ssa_value_set(&m->members, hash_name, p); - } - } else if (decl->proc_decl->kind == AstNode_ProcLit) { - AstNodeProcLit *pd = &decl->proc_decl->ProcLit; - String original_name = name; - AstNode *body = pd->body; - if (e->Procedure.is_foreign) { - name = e->token.string; // NOTE(bill): Don't use the mangled name - } - if (pd->foreign_name.len > 0) { - name = pd->foreign_name; - } else if (pd->link_name.len > 0) { - name = pd->link_name; - } + ast_node(pd, ProcLit, decl->proc_decl); + String original_name = name; + AstNode *body = pd->body; + if (e->Procedure.is_foreign) { + name = e->token.string; // NOTE(bill): Don't use the mangled name + } + if (pd->foreign_name.len > 0) { + name = pd->foreign_name; + } else if (pd->link_name.len > 0) { + name = pd->link_name; + } - ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); - p->Proc.tags = pd->tags; + ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); + p->Proc.tags = pd->tags; - ssa_module_add_value(m, e, p); - HashKey hash_name = hash_string(name); - if (map_ssa_value_get(&m->members, hash_name) == NULL) { - map_ssa_value_set(&m->members, hash_name, p); - } + ssa_module_add_value(m, e, p); + HashKey hash_name = hash_string(name); + if (map_ssa_value_get(&m->members, hash_name) == NULL) { + map_ssa_value_set(&m->members, hash_name, p); } } break; } |