From 4e7150b470fe9a0b0794fa9bdbac49ffc2c113be Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sun, 25 Jun 2017 22:29:23 +0100 Subject: [PATCH] Allow nested para-poly procedures --- code/demo.odin | 7 ++-- src/check_expr.cpp | 21 ++++++++++++ src/checker.cpp | 40 +++++++++++------------ src/ir.cpp | 81 +++++++++++++++++++++++++++------------------- 4 files changed, 92 insertions(+), 57 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index 4639588e1..cda53e35b 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -2,11 +2,12 @@ import ( "fmt.odin"; ) -proc new_type(T: type) -> ^T { - return ^T(alloc(size_of(T), align_of(T))); -} proc main() { + proc new_type(T: type) -> ^T { + return ^T(alloc(size_of(T), align_of(T))); + } + var ptr = new_type(int); ptr^ = 123; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index f61809078..460c449da 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5075,6 +5075,27 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { add_entity_use(c, ce->proc, gen_entity); check_procedure_later(c, c->curr_ast_file, token, d, final_proc_type, pd->body, tags); + + + auto *found = map_get(&c->info.gen_procs, hash_pointer(entity->identifier)); + if (found) { + bool ok = true; + for_array(i, *found) { + Entity *other = (*found)[i]; + if (are_types_identical(other->type, gen_entity->type)) { + ok = false; + break; + } + } + if (ok) { + array_add(found, gen_entity); + } + } else { + Array array = {}; + array_init(&array, heap_allocator()); + array_add(&array, gen_entity); + map_set(&c->info.gen_procs, hash_pointer(entity->identifier), array); + } } diff --git a/src/checker.cpp b/src/checker.cpp index 10afa06fd..8eb3a3900 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -270,17 +270,18 @@ struct CheckerContext { // CheckerInfo stores all the symbol information for a type-checked program struct CheckerInfo { - Map types; // Key: AstNode * | Expression -> Type (and value) - Map definitions; // Key: AstNode * | Identifier -> Entity - Map uses; // Key: AstNode * | Identifier -> Entity - Map scopes; // Key: AstNode * | Node -> Scope - Map untyped; // Key: AstNode * | Expression -> ExprInfo - Map implicits; // Key: AstNode * - Map entities; // Key: Entity * - Map foreigns; // Key: String - Map files; // Key: String (full path) - Map type_info_map; // Key: Type * - isize type_info_count; + Map types; // Key: AstNode * | Expression -> Type (and value) + Map definitions; // Key: AstNode * | Identifier -> Entity + Map uses; // Key: AstNode * | Identifier -> Entity + Map scopes; // Key: AstNode * | Node -> Scope + Map untyped; // Key: AstNode * | Expression -> ExprInfo + Map implicits; // Key: AstNode * + Map > gen_procs; // Key: AstNode * | Identifier -> Entity + Map entities; // Key: Entity * + Map foreigns; // Key: String + Map files; // Key: String (full path) + Map type_info_map; // Key: Type * + isize type_info_count; }; struct Checker { @@ -291,7 +292,6 @@ struct Checker { Scope * global_scope; // NOTE(bill): Procedures to check Map procs; // Key: DeclInfo * - Map > gen_procs; Array delayed_imports; Array delayed_foreign_libraries; Array file_nodes; @@ -702,16 +702,17 @@ void init_universal_scope(void) { void init_checker_info(CheckerInfo *i) { gbAllocator a = heap_allocator(); - map_init(&i->types, a); + map_init(&i->types, a); map_init(&i->definitions, a); map_init(&i->uses, a); - map_init(&i->scopes, a); - map_init(&i->entities, a); - map_init(&i->untyped, a); + map_init(&i->scopes, a); + map_init(&i->entities, a); + map_init(&i->untyped, a); map_init(&i->foreigns, a); map_init(&i->implicits, a); - map_init(&i->type_info_map, a); - map_init(&i->files, a); + map_init(&i->gen_procs, a); + map_init(&i->type_info_map, a); + map_init(&i->files, a); i->type_info_count = 0; } @@ -725,6 +726,7 @@ void destroy_checker_info(CheckerInfo *i) { map_destroy(&i->untyped); map_destroy(&i->foreigns); map_destroy(&i->implicits); + map_destroy(&i->gen_procs); map_destroy(&i->type_info_map); map_destroy(&i->files); } @@ -743,7 +745,6 @@ void init_checker(Checker *c, Parser *parser) { array_init(&c->proc_stack, a); map_init(&c->procs, a); - map_init(&c->gen_procs, a); array_init(&c->delayed_imports, a); array_init(&c->delayed_foreign_libraries, a); array_init(&c->file_nodes, a); @@ -781,7 +782,6 @@ void destroy_checker(Checker *c) { destroy_scope(c->global_scope); array_free(&c->proc_stack); map_destroy(&c->procs); - map_destroy(&c->gen_procs); array_free(&c->delayed_imports); array_free(&c->delayed_foreign_libraries); array_free(&c->file_nodes); diff --git a/src/ir.cpp b/src/ir.cpp index 313cb2a3c..1698645a4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -5851,6 +5851,41 @@ void ir_type_case_body(irProcedure *proc, AstNode *label, AstNode *clause, irBlo } +void ir_build_nested_proc(irProcedure *proc, AstNodeProcDecl *pd, Entity *e) { + GB_ASSERT(pd->body != NULL); + + if (is_entity_in_dependency_map(&proc->module->min_dep_map, e) == false) { + // NOTE(bill): Nothing depends upon it so doesn't need to be built + return; + } + + // 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); +} + + void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { switch (node->kind) { case_ast_node(bs, EmptyStmt, node); @@ -5972,43 +6007,21 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { 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 *dl = decl_info_of_entity(proc->module->info, e); + CheckerInfo *info = proc->module->info; + Entity *e = entity_of_ident(info, ident); if (pd->body != NULL) { - CheckerInfo *info = proc->module->info; - - if (is_entity_in_dependency_map(&proc->module->min_dep_map, e) == false) { - // NOTE(bill): Nothing depends upon it so doesn't need to be built - break; + if (is_type_gen_proc(e->type)) { + auto found = *map_get(&info->gen_procs, hash_pointer(ident)); + for_array(i, found) { + Entity *e = found[i]; + DeclInfo *d = decl_info_of_entity(info, e); + ir_build_nested_proc(proc, &d->proc_decl->ProcDecl, e); + } + } else { + ir_build_nested_proc(proc, pd, e); } - - // 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; @@ -6018,7 +6031,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { } irValue *value = ir_value_procedure(proc->module->allocator, - proc->module, e, e->type, pd->type, pd->body, name); + proc->module, e, e->type, pd->type, pd->body, name); value->Proc.tags = pd->tags;