aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-01-01 20:41:10 +0000
committerGinger Bill <bill@gingerbill.org>2017-01-01 20:41:10 +0000
commit9202bd1b0640737ce9d843f8d308debe45fc9a90 (patch)
treef3153718034b50a3e2bcdd2d3608f30df7622958 /src
parenta48e0c7179cfe78f3163a3e471f7401502d8c437 (diff)
Nearly finished Jai-like declarations
Diffstat (limited to 'src')
-rw-r--r--src/checker/checker.c36
-rw-r--r--src/checker/decl.c267
-rw-r--r--src/checker/expr.c49
-rw-r--r--src/checker/stmt.c25
-rw-r--r--src/parser.c137
-rw-r--r--src/ssa.c221
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) {
diff --git a/src/ssa.c b/src/ssa.c
index ca77c385c..6a2b4f8f4 100644
--- a/src/ssa.c
+++ b/src/ssa.c
@@ -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;
}