aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-01-01 18:18:43 +0000
committerGinger Bill <bill@gingerbill.org>2017-01-01 18:18:43 +0000
commit3f1195cd03ac009eee508b7d0e086807507a0ef4 (patch)
tree28d6b4c7af854adfe336b06cea7167b8a7e8abab /src
parent311b5cb6e211aa49d8dc0e081173204d7271964f (diff)
More declaration differentiation in semantic stage e.g. make only variables and constants
Diffstat (limited to 'src')
-rw-r--r--src/checker/checker.c42
-rw-r--r--src/checker/decl.c274
-rw-r--r--src/checker/expr.c36
-rw-r--r--src/parser.c34
-rw-r--r--src/ssa.c57
5 files changed, 312 insertions, 131 deletions
diff --git a/src/checker/checker.c b/src/checker/checker.c
index 98107c9d0..4d4c8f30e 100644
--- a/src/checker/checker.c
+++ b/src/checker/checker.c
@@ -883,6 +883,9 @@ void add_type_info_type(Checker *c, Type *t) {
case Type_Record: {
switch (bt->Record.kind) {
+ case TypeRecord_Enum:
+ add_type_info_type(c, bt->Record.enum_base_type);
+ break;
case TypeRecord_Union:
add_type_info_type(c, t_int);
/* fallthrough */
@@ -1072,13 +1075,13 @@ void init_preload(Checker *c) {
c->done_preload = true;
}
-void check_arity_match(Checker *c, AstNodeValueSpec *s, AstNodeValueSpec *init);
+bool check_arity_match(Checker *c, AstNodeValueSpec *s, AstNodeValueSpec *init);
#include "expr.c"
#include "decl.c"
#include "stmt.c"
-void check_arity_match(Checker *c, AstNodeValueSpec *s, AstNodeValueSpec *init) {
+bool check_arity_match(Checker *c, AstNodeValueSpec *s, AstNodeValueSpec *init) {
isize lhs = s->names.count;
isize rhs = s->values.count;
if (init != NULL) {
@@ -1088,6 +1091,7 @@ void check_arity_match(Checker *c, AstNodeValueSpec *s, AstNodeValueSpec *init)
if (init == NULL && rhs == 0) {
if (s->type == NULL) {
error_node(s->names.e[0], "Missing type or initial expression");
+ return false;
}
} else if (lhs < rhs) {
if (lhs < s->values.count) {
@@ -1098,12 +1102,16 @@ void check_arity_match(Checker *c, AstNodeValueSpec *s, AstNodeValueSpec *init)
} else {
error_node(s->names.e[0], "Extra initial expression");
}
+ return false;
} else if (lhs > rhs && (init != NULL || rhs != 1)) {
AstNode *n = s->names.e[rhs];
gbString str = expr_to_string(n);
error_node(n, "Missing expression for `%s`", str);
gb_string_free(str);
+ return false;
}
+
+ return true;
}
@@ -1234,19 +1242,34 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
continue;
}
- ExactValue v = make_exact_value_integer(iota);
- Entity *e = make_entity_constant(c->allocator, parent_scope, name->Ident, NULL, v);
- e->identifier = name;
AstNode *init = NULL;
if (i < prev_spec->values.count) {
init = prev_spec->values.e[i];
}
- DeclInfo *di = make_declaration_info(c->allocator, e->scope);
- di->type_expr = prev_spec->type;
- di->init_expr = init;
- add_entity_and_decl_info(c, name, e, di);
+ DeclInfo *d = make_declaration_info(c->allocator, parent_scope);
+ Entity *e = NULL;
+
+ ExactValue v_iota = make_exact_value_integer(iota);
+
+ AstNode *up_init = unparen_expr(init);
+ if (init != NULL && is_ast_node_type(up_init)) {
+ e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
+ d->type_expr = init;
+ d->init_expr = init;
+ } 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_decl = init;
+ } else {
+ e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, v_iota);
+ d->type_expr = prev_spec->type;
+ d->init_expr = init;
+ }
+ GB_ASSERT(e != NULL);
+ e->identifier = name;
+
+ add_entity_and_decl_info(c, name, e, d);
}
check_arity_match(c, vs, prev_spec);
@@ -1263,6 +1286,7 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
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;
diff --git a/src/checker/decl.c b/src/checker/decl.c
index d73c79e35..818a31dd0 100644
--- a/src/checker/decl.c
+++ b/src/checker/decl.c
@@ -248,7 +248,6 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
}
e->flags |= EntityFlag_Visited;
- GB_ASSERT(c->context.iota.kind == ExactValue_Invalid);
c->context.iota = e->Constant.value;
e->Constant.value = (ExactValue){0};
@@ -267,7 +266,18 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
Operand operand = {0};
if (init != NULL) {
- check_expr(c, &operand, init);
+ check_expr_or_type(c, &operand, init);
+ }
+ if (operand.mode == Addressing_Type) {
+ c->context.iota = (ExactValue){0};
+
+ e->Constant.value = (ExactValue){0};
+ e->kind = Entity_TypeName;
+
+ DeclInfo *d = c->context.decl;
+ d->type_expr = d->init_expr;
+ check_type_decl(c, e, d->type_expr, named_type);
+ return;
}
check_init_constant(c, e, &operand);
@@ -319,113 +329,221 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false, ProcCC_Odin);
e->type = proc_type;
- ast_node(pd, ProcDecl, d->proc_decl);
-
- 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 (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);
+ }
}
}
- }
- if (is_inline && is_no_inline) {
- error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure");
- }
+ 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 (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 (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;
+ }
+
+ 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 (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_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);
+ }
+ }
}
- d->scope = c->context.scope;
+ 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);
+ }
+ }
+ }
- 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_inline && is_no_inline) {
+ error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure");
+ }
- 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;
+ 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");
}
- 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);
+ if (pd->body != NULL) {
+ if (is_foreign) {
+ error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body");
}
- } 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 (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;
+ }
+
+ 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_link_name || is_export) {
+ 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.link_name = 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;
- // 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);
+ 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) {
+ 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 d0116e8b2..bf15d22dc 100644
--- a/src/checker/expr.c
+++ b/src/checker/expr.c
@@ -113,21 +113,35 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
continue;
}
- ExactValue v = make_exact_value_integer(iota);
- Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v);
- e->identifier = name;
-
AstNode *init = NULL;
- if (i < last->values.count) {
- init = last->values.e[i];
+ if (i < vs->values.count) {
+ init = vs->values.e[i];
+ }
+
+ DeclInfo *d = make_declaration_info(c->allocator, c->context.scope);
+ Entity *e = NULL;
+
+ ExactValue v_iota = make_exact_value_integer(iota);
+
+ AstNode *up_init = unparen_expr(init);
+ if (init != NULL && is_ast_node_type(up_init)) {
+ e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
+ d->type_expr = init;
+ d->init_expr = init;
+ } 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_decl = init;
+ } else {
+ e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, v_iota);
+ d->type_expr = vs->type;
+ d->init_expr = init;
}
+ GB_ASSERT(e != NULL);
+ e->identifier = name;
- DeclInfo *di = make_declaration_info(c->allocator, e->scope);
- di->type_expr = last->type;
- di->init_expr = init;
- add_entity_and_decl_info(c, name, e, di);
+ add_entity_and_decl_info(c, name, e, d);
- DelayedEntity delay = {name, e, di};
+ DelayedEntity delay = {name, e, d};
array_add(delayed_entities, delay);
}
diff --git a/src/parser.c b/src/parser.c
index 2d61c9e92..12144462c 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1740,31 +1740,25 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
// Parse Procedure Type or Literal
case Token_proc: {
+ Token token = f->curr_token;
String foreign_name = {0};
String link_name = {0};
- AstNode *curr_proc = f->curr_proc;
AstNode *type = parse_proc_type(f, &foreign_name, &link_name);
- f->curr_proc = type;
-
- if (type->ProcType.tags & ProcTag_foreign) {
- syntax_error(f->curr_token, "#foreign cannot be applied to procedure literals");
- }
- if (type->ProcType.tags & ProcTag_export) {
- syntax_error(f->curr_token, "#export cannot be applied to procedure literals");
- }
if (f->curr_token.kind == Token_OpenBrace) {
- AstNode *body;
+ u64 tags = type->ProcType.tags;
- if ((type->ProcType.tags & ProcTag_foreign) != 0) {
- syntax_error(f->curr_token, "A procedure tagged as `#foreign` cannot have a body");
+ 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;
+ AstNode *body = parse_body(f);
+ f->curr_proc = curr_proc;
- body = parse_body(f);
- type = make_proc_lit(f, type, body, type->ProcType.tags, foreign_name, link_name);
+ return make_proc_lit(f, type, body, tags, foreign_name, link_name);
}
- f->curr_proc = curr_proc;
return type;
}
@@ -1941,7 +1935,15 @@ AstNode *parse_type(AstFile *f);
AstNode *parse_unary_expr(AstFile *f, bool lhs) {
switch (f->curr_token.kind) {
- case Token_Pointer:
+ case Token_Pointer: {
+ Token op = f->curr_token;
+ next_token(f);
+ AstNode *expr = parse_unary_expr(f, lhs);
+ if (is_ast_node_type(expr)) {
+ return make_pointer_type(f, op, expr);
+ }
+ return make_unary_expr(f, op, expr);
+ } break;
case Token_Maybe:
case Token_Add:
case Token_Sub:
diff --git a/src/ssa.c b/src/ssa.c
index 10a54bf40..7eeb2131a 100644
--- a/src/ssa.c
+++ b/src/ssa.c
@@ -5038,25 +5038,48 @@ void ssa_gen_tree(ssaGen *s) {
} break;
case Entity_Procedure: {
- 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;
- }
+ 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;
+ 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);
+ }
+ } 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;
+ }
+
+ 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);
+ }
}
} break;
}