Browse Source

Allow nested para-poly procedures

Ginger Bill 8 years ago
parent
commit
4e7150b470
4 changed files with 92 additions and 57 deletions
  1. 4 3
      code/demo.odin
  2. 21 0
      src/check_expr.cpp
  3. 20 20
      src/checker.cpp
  4. 47 34
      src/ir.cpp

+ 4 - 3
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;
 

+ 21 - 0
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<Entity *> array = {};
+					array_init(&array, heap_allocator());
+					array_add(&array, gen_entity);
+					map_set(&c->info.gen_procs, hash_pointer(entity->identifier), array);
+				}
 			}
 
 

+ 20 - 20
src/checker.cpp

@@ -270,17 +270,18 @@ struct CheckerContext {
 
 // CheckerInfo stores all the symbol information for a type-checked program
 struct CheckerInfo {
-	Map<TypeAndValue>    types;           // Key: AstNode * | Expression -> Type (and value)
-	Map<Entity *>        definitions;     // Key: AstNode * | Identifier -> Entity
-	Map<Entity *>        uses;            // Key: AstNode * | Identifier -> Entity
-	Map<Scope *>         scopes;          // Key: AstNode * | Node       -> Scope
-	Map<ExprInfo>        untyped;         // Key: AstNode * | Expression -> ExprInfo
-	Map<Entity *>        implicits;       // Key: AstNode *
-	Map<DeclInfo *>      entities;        // Key: Entity *
-	Map<Entity *>        foreigns;        // Key: String
-	Map<AstFile *>       files;           // Key: String (full path)
-	Map<isize>           type_info_map;   // Key: Type *
-	isize                type_info_count;
+	Map<TypeAndValue>     types;           // Key: AstNode * | Expression -> Type (and value)
+	Map<Entity *>         definitions;     // Key: AstNode * | Identifier -> Entity
+	Map<Entity *>         uses;            // Key: AstNode * | Identifier -> Entity
+	Map<Scope *>          scopes;          // Key: AstNode * | Node       -> Scope
+	Map<ExprInfo>         untyped;         // Key: AstNode * | Expression -> ExprInfo
+	Map<Entity *>         implicits;       // Key: AstNode *
+	Map<Array<Entity *> > gen_procs;       // Key: AstNode * | Identifier -> Entity
+	Map<DeclInfo *>       entities;        // Key: Entity *
+	Map<Entity *>         foreigns;        // Key: String
+	Map<AstFile *>        files;           // Key: String (full path)
+	Map<isize>            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<ProcedureInfo>         procs; // Key: DeclInfo *
-	Map<Array<ProcedureInfo> > gen_procs;
 	Array<DelayedDecl>         delayed_imports;
 	Array<DelayedDecl>         delayed_foreign_libraries;
 	Array<CheckerFileNode>     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);

+ 47 - 34
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;
-			}
-
-			// 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;
+			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);
 			}
-
-			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;