mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +00:00
Procedure grouping foo :: proc[foo16, foo32];
This commit is contained in:
@@ -708,6 +708,47 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
|||||||
check_init_variables(c, entities, entity_count, init_expr_list, context_name);
|
check_init_variables(c, entities, entity_count, init_expr_list, context_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void check_proc_grouping_decl(Checker *c, Entity *pg_entity, DeclInfo *d) {
|
||||||
|
GB_ASSERT(pg_entity->kind == Entity_ProcedureGrouping);
|
||||||
|
auto *pge = &pg_entity->ProcedureGrouping;
|
||||||
|
|
||||||
|
ast_node(pg, ProcGrouping, d->init_expr);
|
||||||
|
|
||||||
|
array_init(&pge->entities, c->allocator, pg->args.count);
|
||||||
|
|
||||||
|
|
||||||
|
PtrSet<Entity *> entity_map = {};
|
||||||
|
ptr_set_init(&entity_map, heap_allocator());
|
||||||
|
defer (ptr_set_destroy(&entity_map));
|
||||||
|
|
||||||
|
for_array(i, pg->args) {
|
||||||
|
AstNode *arg = pg->args[i];
|
||||||
|
Entity *e = nullptr;
|
||||||
|
Operand o = {};
|
||||||
|
if (arg->kind == AstNode_Ident) {
|
||||||
|
e = check_ident(c, &o, arg, nullptr, nullptr, true);
|
||||||
|
} else if (arg->kind == AstNode_SelectorExpr) {
|
||||||
|
e = check_selector(c, &o, arg, nullptr);
|
||||||
|
}
|
||||||
|
if (e == nullptr) {
|
||||||
|
error(arg, "Expected a valid entity name in procedure grouping");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (e->kind != Entity_Procedure) {
|
||||||
|
error(arg, "Expected a procedure entity");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr_set_exists(&entity_map, e)) {
|
||||||
|
error(arg, "Previous use of `%.*s` in procedure grouping", LIT(e->token.string));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ptr_set_add(&entity_map, e);
|
||||||
|
|
||||||
|
array_add(&pge->entities, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
||||||
if (e->type != nullptr) {
|
if (e->type != nullptr) {
|
||||||
return;
|
return;
|
||||||
@@ -745,6 +786,11 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
|||||||
case Entity_Procedure:
|
case Entity_Procedure:
|
||||||
check_proc_decl(c, e, d);
|
check_proc_decl(c, e, d);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Entity_ProcedureGrouping:
|
||||||
|
// error(e->token, "Procedure groupings are not yet supported");
|
||||||
|
check_proc_grouping_decl(c, e, d);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->context = prev;
|
c->context = prev;
|
||||||
|
|||||||
+58
-4
@@ -997,6 +997,43 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
|
|||||||
gb_free(heap_allocator(), procs);
|
gb_free(heap_allocator(), procs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e->kind == Entity_ProcedureGrouping) {
|
||||||
|
auto *pge = &e->ProcedureGrouping;
|
||||||
|
Entity **procs = pge->entities.data;
|
||||||
|
isize overload_count = pge->entities.count;
|
||||||
|
bool skip = false;
|
||||||
|
|
||||||
|
if (type_hint != nullptr) {
|
||||||
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
|
// NOTE(bill): These should be done
|
||||||
|
for (isize i = 0; i < overload_count; i++) {
|
||||||
|
Type *t = base_type(procs[i]->type);
|
||||||
|
if (t == t_invalid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Operand x = {};
|
||||||
|
x.mode = Addressing_Value;
|
||||||
|
x.type = t;
|
||||||
|
if (check_is_assignable_to(c, &x, type_hint)) {
|
||||||
|
e = procs[i];
|
||||||
|
add_entity_use(c, n, e);
|
||||||
|
skip = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skip) {
|
||||||
|
o->mode = Addressing_Overload;
|
||||||
|
o->type = t_invalid;
|
||||||
|
o->overload_count = overload_count;
|
||||||
|
o->overload_entities = procs;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
add_entity_use(c, n, e);
|
add_entity_use(c, n, e);
|
||||||
check_entity_decl(c, e, nullptr, named_type);
|
check_entity_decl(c, e, nullptr, named_type);
|
||||||
|
|
||||||
@@ -4427,11 +4464,12 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
|
|||||||
defer (gb_free(heap_allocator(), procs));
|
defer (gb_free(heap_allocator(), procs));
|
||||||
defer (gb_free(heap_allocator(), valids));
|
defer (gb_free(heap_allocator(), valids));
|
||||||
|
|
||||||
String name = procs[0]->token.string;
|
gbString expr_name = expr_to_string(operand->expr);
|
||||||
|
defer (gb_string_free(expr_name));
|
||||||
|
|
||||||
for (isize i = 0; i < overload_count; i++) {
|
for (isize i = 0; i < overload_count; i++) {
|
||||||
Entity *e = procs[i];
|
Entity *e = procs[i];
|
||||||
GB_ASSERT(e->token.string == name);
|
// GB_ASSERT(e->token.string == name);
|
||||||
DeclInfo *d = decl_info_of_entity(&c->info, e);
|
DeclInfo *d = decl_info_of_entity(&c->info, e);
|
||||||
GB_ASSERT(d != nullptr);
|
GB_ASSERT(d != nullptr);
|
||||||
check_entity_decl(c, e, d, nullptr);
|
check_entity_decl(c, e, d, nullptr);
|
||||||
@@ -4476,7 +4514,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
|
|||||||
|
|
||||||
|
|
||||||
if (valid_count == 0) {
|
if (valid_count == 0) {
|
||||||
error(operand->expr, "No overloads or ambiguous call for '%.*s' that match with the given arguments", LIT(name));
|
error(operand->expr, "No overloads or ambiguous call for '%s' that match with the given arguments", expr_name);
|
||||||
gb_printf_err("\tGiven argument types -> (");
|
gb_printf_err("\tGiven argument types -> (");
|
||||||
for_array(i, operands) {
|
for_array(i, operands) {
|
||||||
Operand o = operands[i];
|
Operand o = operands[i];
|
||||||
@@ -4502,6 +4540,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
|
|||||||
} else {
|
} else {
|
||||||
pt = type_to_string(t);
|
pt = type_to_string(t);
|
||||||
}
|
}
|
||||||
|
String name = proc->token.string;
|
||||||
gb_printf_err("\t%.*s :: %s at %.*s(%td:%td) with score %lld\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score);
|
gb_printf_err("\t%.*s :: %s at %.*s(%td:%td) with score %lld\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score);
|
||||||
// gb_printf_err("\t%.*s :: %s at %.*s(%td:%td)\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column);
|
// gb_printf_err("\t%.*s :: %s at %.*s(%td:%td)\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column);
|
||||||
gb_string_free(pt);
|
gb_string_free(pt);
|
||||||
@@ -4511,7 +4550,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
|
|||||||
}
|
}
|
||||||
result_type = t_invalid;
|
result_type = t_invalid;
|
||||||
} else if (valid_count > 1) {
|
} else if (valid_count > 1) {
|
||||||
error(operand->expr, "Ambiguous procedure call '%.*s' tha match with the given arguments", LIT(name));
|
error(operand->expr, "Ambiguous procedure call '%s' tha match with the given arguments", expr_name);
|
||||||
gb_printf_err("\tGiven argument types -> (");
|
gb_printf_err("\tGiven argument types -> (");
|
||||||
for_array(i, operands) {
|
for_array(i, operands) {
|
||||||
Operand o = operands[i];
|
Operand o = operands[i];
|
||||||
@@ -4532,6 +4571,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
|
|||||||
} else {
|
} else {
|
||||||
pt = type_to_string(t);
|
pt = type_to_string(t);
|
||||||
}
|
}
|
||||||
|
String name = proc->token.string;
|
||||||
// gb_printf_err("\t%.*s :: %s at %.*s(%td:%td) with score %lld\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score);
|
// gb_printf_err("\t%.*s :: %s at %.*s(%td:%td) with score %lld\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score);
|
||||||
gb_printf_err("\t%.*s :: %s at %.*s(%td:%td)\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column);
|
gb_printf_err("\t%.*s :: %s at %.*s(%td:%td)\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column);
|
||||||
gb_string_free(pt);
|
gb_string_free(pt);
|
||||||
@@ -5149,6 +5189,11 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
|||||||
o->mode = Addressing_Constant;
|
o->mode = Addressing_Constant;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(pg, ProcGrouping, node);
|
||||||
|
error(node, "Illegal use of a procedure grouping");
|
||||||
|
o->mode = Addressing_Invalid;
|
||||||
|
case_end;
|
||||||
|
|
||||||
case_ast_node(pl, ProcLit, node);
|
case_ast_node(pl, ProcLit, node);
|
||||||
CheckerContext prev_context = c->context;
|
CheckerContext prev_context = c->context;
|
||||||
DeclInfo *decl = nullptr;
|
DeclInfo *decl = nullptr;
|
||||||
@@ -6143,6 +6188,15 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
str = gb_string_appendc(str, "---");
|
str = gb_string_appendc(str, "---");
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(pg, ProcGrouping, node);
|
||||||
|
str = gb_string_appendc(str, "proc[");
|
||||||
|
for_array(i, pg->args) {
|
||||||
|
if (i > 0) str = gb_string_appendc(str, ", ");
|
||||||
|
str = write_expr_to_string(str, pg->args[i]);
|
||||||
|
}
|
||||||
|
str = gb_string_append_rune(str, ']');
|
||||||
|
case_end;
|
||||||
|
|
||||||
case_ast_node(pl, ProcLit, node);
|
case_ast_node(pl, ProcLit, node);
|
||||||
str = write_expr_to_string(str, pl->type);
|
str = write_expr_to_string(str, pl->type);
|
||||||
case_end;
|
case_end;
|
||||||
|
|||||||
@@ -2259,6 +2259,13 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
|
|||||||
}
|
}
|
||||||
d->proc_lit = init;
|
d->proc_lit = init;
|
||||||
d->type_expr = pl->type;
|
d->type_expr = pl->type;
|
||||||
|
} else if (init->kind == AstNode_ProcGrouping) {
|
||||||
|
ast_node(pg, ProcGrouping, init);
|
||||||
|
e = make_entity_procedure_grouping(c->allocator, d->scope, token, nullptr);
|
||||||
|
if (fl != nullptr) {
|
||||||
|
error(name, "Procedure groupings are not allowed within a foreign block");
|
||||||
|
}
|
||||||
|
d->init_expr = init;
|
||||||
} else {
|
} else {
|
||||||
e = make_entity_constant(c->allocator, d->scope, token, nullptr, empty_exact_value);
|
e = make_entity_constant(c->allocator, d->scope, token, nullptr, empty_exact_value);
|
||||||
d->type_expr = vd->type;
|
d->type_expr = vd->type;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ struct DeclInfo;
|
|||||||
ENTITY_KIND(Variable) \
|
ENTITY_KIND(Variable) \
|
||||||
ENTITY_KIND(TypeName) \
|
ENTITY_KIND(TypeName) \
|
||||||
ENTITY_KIND(Procedure) \
|
ENTITY_KIND(Procedure) \
|
||||||
|
ENTITY_KIND(ProcedureGrouping) \
|
||||||
ENTITY_KIND(Builtin) \
|
ENTITY_KIND(Builtin) \
|
||||||
ENTITY_KIND(Alias) \
|
ENTITY_KIND(Alias) \
|
||||||
ENTITY_KIND(ImportName) \
|
ENTITY_KIND(ImportName) \
|
||||||
@@ -107,6 +108,9 @@ struct Entity {
|
|||||||
Entity * foreign_library;
|
Entity * foreign_library;
|
||||||
AstNode * foreign_library_ident;
|
AstNode * foreign_library_ident;
|
||||||
} Procedure;
|
} Procedure;
|
||||||
|
struct {
|
||||||
|
Array<Entity *> entities;
|
||||||
|
} ProcedureGrouping;
|
||||||
struct {
|
struct {
|
||||||
i32 id;
|
i32 id;
|
||||||
} Builtin;
|
} Builtin;
|
||||||
@@ -244,6 +248,12 @@ Entity *make_entity_procedure(gbAllocator a, Scope *scope, Token token, Type *si
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Entity *make_entity_procedure_grouping(gbAllocator a, Scope *scope, Token token, Type *type) {
|
||||||
|
Entity *entity = alloc_entity(a, Entity_ProcedureGrouping, scope, token, type);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Entity *make_entity_builtin(gbAllocator a, Scope *scope, Token token, Type *type, i32 id) {
|
Entity *make_entity_builtin(gbAllocator a, Scope *scope, Token token, Type *type, i32 id) {
|
||||||
Entity *entity = alloc_entity(a, Entity_Builtin, scope, token, type);
|
Entity *entity = alloc_entity(a, Entity_Builtin, scope, token, type);
|
||||||
entity->Builtin.id = id;
|
entity->Builtin.id = id;
|
||||||
|
|||||||
+46
-1
@@ -164,6 +164,12 @@ Array<AstNode *> make_ast_node_array(AstFile *f, isize init_capacity = 8) {
|
|||||||
Token token; \
|
Token token; \
|
||||||
AstNode *expr; \
|
AstNode *expr; \
|
||||||
}) \
|
}) \
|
||||||
|
AST_NODE_KIND(ProcGrouping, "procedure grouping", struct { \
|
||||||
|
Token token; \
|
||||||
|
Token open; \
|
||||||
|
Token close; \
|
||||||
|
Array<AstNode *> args; \
|
||||||
|
}) \
|
||||||
AST_NODE_KIND(ProcLit, "procedure literal", struct { \
|
AST_NODE_KIND(ProcLit, "procedure literal", struct { \
|
||||||
AstNode *type; \
|
AstNode *type; \
|
||||||
AstNode *body; \
|
AstNode *body; \
|
||||||
@@ -534,6 +540,7 @@ Token ast_node_token(AstNode *node) {
|
|||||||
case AstNode_Undef: return node->Undef;
|
case AstNode_Undef: return node->Undef;
|
||||||
case AstNode_BasicLit: return node->BasicLit;
|
case AstNode_BasicLit: return node->BasicLit;
|
||||||
case AstNode_BasicDirective: return node->BasicDirective.token;
|
case AstNode_BasicDirective: return node->BasicDirective.token;
|
||||||
|
case AstNode_ProcGrouping: return node->ProcGrouping.token;
|
||||||
case AstNode_ProcLit: return ast_node_token(node->ProcLit.type);
|
case AstNode_ProcLit: return ast_node_token(node->ProcLit.type);
|
||||||
case AstNode_CompoundLit:
|
case AstNode_CompoundLit:
|
||||||
if (node->CompoundLit.type != nullptr) {
|
if (node->CompoundLit.type != nullptr) {
|
||||||
@@ -662,6 +669,9 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
|
|||||||
case AstNode_Ellipsis:
|
case AstNode_Ellipsis:
|
||||||
n->Ellipsis.expr = clone_ast_node(a, n->Ellipsis.expr);
|
n->Ellipsis.expr = clone_ast_node(a, n->Ellipsis.expr);
|
||||||
break;
|
break;
|
||||||
|
case AstNode_ProcGrouping:
|
||||||
|
n->ProcGrouping.args = clone_ast_node_array(a, n->ProcGrouping.args);
|
||||||
|
break;
|
||||||
case AstNode_ProcLit:
|
case AstNode_ProcLit:
|
||||||
n->ProcLit.type = clone_ast_node(a, n->ProcLit.type);
|
n->ProcLit.type = clone_ast_node(a, n->ProcLit.type);
|
||||||
n->ProcLit.body = clone_ast_node(a, n->ProcLit.body);
|
n->ProcLit.body = clone_ast_node(a, n->ProcLit.body);
|
||||||
@@ -1111,6 +1121,15 @@ AstNode *ast_ellipsis(AstFile *f, Token token, AstNode *expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AstNode *ast_proc_grouping(AstFile *f, Token token, Token open, Token close, Array<AstNode *> args) {
|
||||||
|
AstNode *result = make_ast_node(f, AstNode_ProcGrouping);
|
||||||
|
result->ProcGrouping.token = token;
|
||||||
|
result->ProcGrouping.open = open;
|
||||||
|
result->ProcGrouping.close = close;
|
||||||
|
result->ProcGrouping.args = args;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
AstNode *ast_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags) {
|
AstNode *ast_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags) {
|
||||||
AstNode *result = make_ast_node(f, AstNode_ProcLit);
|
AstNode *result = make_ast_node(f, AstNode_ProcLit);
|
||||||
result->ProcLit.type = type;
|
result->ProcLit.type = type;
|
||||||
@@ -2247,9 +2266,35 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
return expr;
|
return expr;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
// Parse Procedure Type or Literal
|
// Parse Procedure Type or Literal or Grouping
|
||||||
case Token_proc: {
|
case Token_proc: {
|
||||||
Token token = expect_token(f, Token_proc);
|
Token token = expect_token(f, Token_proc);
|
||||||
|
|
||||||
|
if (f->curr_token.kind == Token_OpenBracket) { // ProcGrouping
|
||||||
|
Token open = expect_token(f, Token_OpenBracket);
|
||||||
|
|
||||||
|
Array<AstNode *> args = {};
|
||||||
|
array_init(&args, heap_allocator());
|
||||||
|
|
||||||
|
while (f->curr_token.kind != Token_CloseBracket &&
|
||||||
|
f->curr_token.kind != Token_EOF) {
|
||||||
|
AstNode *elem = parse_expr(f, false);
|
||||||
|
array_add(&args, elem);
|
||||||
|
|
||||||
|
if (!allow_token(f, Token_Comma)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Token close = expect_token(f, Token_CloseBracket);
|
||||||
|
|
||||||
|
if (args.count == 0) {
|
||||||
|
syntax_error(token, "Expected a least 1 argument in a procedure grouping");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ast_proc_grouping(f, token, open, close, args);
|
||||||
|
}
|
||||||
|
|
||||||
AstNode *type = parse_proc_type(f, token);
|
AstNode *type = parse_proc_type(f, token);
|
||||||
|
|
||||||
if (f->allow_type && f->expr_level < 0) {
|
if (f->allow_type && f->expr_level < 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user