mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-01 10:52:19 +00:00
Allow nested para-poly procedures
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
81
src/ir.cpp
81
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user