diff options
Diffstat (limited to 'src/check_expr.cpp')
| -rw-r--r-- | src/check_expr.cpp | 154 |
1 files changed, 107 insertions, 47 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 6696af6a4..f61809078 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1,3 +1,37 @@ +enum CallArgumentError { + CallArgumentError_None, + CallArgumentError_NoneProcedureType, + CallArgumentError_WrongTypes, + CallArgumentError_NonVariadicExpand, + CallArgumentError_VariadicTuple, + CallArgumentError_MultipleVariadicExpand, + CallArgumentError_ArgumentCount, + CallArgumentError_TooFewArguments, + CallArgumentError_TooManyArguments, + CallArgumentError_InvalidFieldValue, + CallArgumentError_ParameterNotFound, + CallArgumentError_ParameterMissing, + CallArgumentError_DuplicateParameter, + CallArgumentError_GenericProcedureNotSupported, +}; + +enum CallArgumentErrorMode { + CallArgumentMode_NoErrors, + CallArgumentMode_ShowErrors, +}; + +struct CallArgumentData { + Entity *gen_entity; + i64 score; + Type * result_type; +}; + + +#define CALL_ARGUMENT_CHECKER(name) CallArgumentError name(Checker *c, AstNode *call, Type *proc_type, Entity *entity, Array<Operand> operands, CallArgumentErrorMode show_error_mode, CallArgumentData *data) +typedef CALL_ARGUMENT_CHECKER(CallArgumentCheckerType); + + + void check_expr (Checker *c, Operand *operand, AstNode *expression); void check_multi_expr (Checker *c, Operand *operand, AstNode *expression); void check_expr_or_type (Checker *c, Operand *operand, AstNode *expression); @@ -19,7 +53,7 @@ void check_stmt (Checker *c, AstNode *node, u32 flags); void check_stmt_list (Checker *c, Array<AstNode *> stmts, u32 flags); void check_init_constant (Checker *c, Entity *e, Operand *operand); bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type, ExactValue *out_value); -Type * check_call_arguments (Checker *c, Operand *operand, Type *proc_type, AstNode *call); +CallArgumentData check_call_arguments (Checker *c, Operand *operand, Type *proc_type, AstNode *call); void error_operand_not_expression(Operand *o) { @@ -1173,13 +1207,16 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari if (ast_node_expect(name, AstNode_Ident)) { Entity *param = NULL; bool is_generic = type->kind == Type_Generic; + Type *gen_type = type; if (operands != NULL) { Operand o = (*operands)[j]; is_generic = o.mode == Addressing_Type && o.type == type; + if (is_generic) gen_type = o.type; } if (is_generic) { - param = make_entity_type_name(c->allocator, scope, name->Ident, type); + param = make_entity_type_name(c->allocator, scope, name->Ident, gen_type); + param->TypeName.is_type_alias = true; } else { param = make_entity_param(c->allocator, scope, name->Ident, type, (p->flags&FieldFlag_using) != 0, false); @@ -4858,28 +4895,6 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id return true; } -enum CallArgumentError { - CallArgumentError_None, - CallArgumentError_NoneProcedureType, - CallArgumentError_WrongTypes, - CallArgumentError_NonVariadicExpand, - CallArgumentError_VariadicTuple, - CallArgumentError_MultipleVariadicExpand, - CallArgumentError_ArgumentCount, - CallArgumentError_TooFewArguments, - CallArgumentError_TooManyArguments, - CallArgumentError_InvalidFieldValue, - CallArgumentError_ParameterNotFound, - CallArgumentError_ParameterMissing, - CallArgumentError_DuplicateParameter, - CallArgumentError_GenericProcedureNotSupported, -}; - -enum CallArgumentErrorMode { - CallArgumentMode_NoErrors, - CallArgumentMode_ShowErrors, -}; - struct ValidProcAndScore { isize index; @@ -4934,8 +4949,7 @@ bool check_unpack_arguments(Checker *c, isize lhs_count, Array<Operand> *operand return optional_ok; } -#define CALL_ARGUMENT_CHECKER(name) CallArgumentError name(Checker *c, AstNode *call, Type *proc_type, Array<Operand> operands, CallArgumentErrorMode show_error_mode, i64 *score_, Type **result_type_) -typedef CALL_ARGUMENT_CHECKER(CallArgumentCheckerType); + CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { @@ -4984,6 +4998,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { CallArgumentError err = CallArgumentError_None; Type *final_proc_type = proc_type; + Entity *gen_entity = NULL; if (vari_expand && !variadic) { if (show_error) { @@ -5022,14 +5037,44 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { gb_string_free(proc_str); } } else { + // NOTE(bill): Generate the procedure type for this generic instance + // TODO(bill): Clean this shit up! if (pt->is_generic) { - Scope *scope = make_scope(pt->scope->parent, c->allocator); - CheckerContext prev = c->context; - defer (c->context = prev); - c->context.scope = scope; + GB_ASSERT(entity != NULL); + DeclInfo *old_decl = decl_info_of_entity(&c->info, entity); + GB_ASSERT(old_decl != NULL); + + gbAllocator a = heap_allocator(); + + Scope *scope = entity->scope; + + AstNode *proc_decl = clone_ast_node(a, old_decl->proc_decl); + ast_node(pd, ProcDecl, proc_decl); - final_proc_type = alloc_type(c->allocator, Type_Proc); + check_open_scope(c, pd->type); + defer (check_close_scope(c)); + + final_proc_type = make_type_proc(c->allocator, c->context.scope, NULL, 0, NULL, 0, false, pt->calling_convention); check_procedure_type(c, final_proc_type, pt->node, &operands); + + u64 tags = entity->Procedure.tags; + AstNode *ident = clone_ast_node(a, entity->identifier); + Token token = ident->Ident; + DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, old_decl->parent); + d->gen_proc_type = final_proc_type; + d->type_expr = pd->type; + d->proc_decl = proc_decl; + + gen_entity = make_entity_procedure(c->allocator, entity->scope, token, final_proc_type, tags); + gen_entity->identifier = ident; + + add_entity_and_decl_info(c, ident, gen_entity, d); + add_entity_definition(&c->info, ident, gen_entity); + + add_entity_use(c, ident, gen_entity); + add_entity_use(c, ce->proc, gen_entity); + + check_procedure_later(c, c->curr_ast_file, token, d, final_proc_type, pd->body, tags); } @@ -5082,7 +5127,11 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { if (show_error) { error(o.expr, "`..` in a variadic procedure can only have one variadic argument at the end"); } - if (score_) *score_ = score; + if (data) { + data->score = score; + data->result_type = final_proc_type->Proc.results; + data->gen_entity = gen_entity; + } return CallArgumentError_MultipleVariadicExpand; } } @@ -5099,8 +5148,11 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { } } - if (score_) *score_ = score; - if (result_type_) *result_type_ = final_proc_type->Proc.results; + if (data) { + data->score = score; + data->result_type = final_proc_type->Proc.results; + data->gen_entity = gen_entity; + } return err; } @@ -5250,14 +5302,17 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { err = CallArgumentError_GenericProcedureNotSupported; } - if (score_) *score_ = score; - if (result_type_) *result_type_ = pt->results; + if (data) { + data->score = score; + data->result_type = pt->results; + data->gen_entity = NULL; + } return err; } -Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) { +CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) { ast_node(ce, CallExpr, call); CallArgumentCheckerType *call_checker = check_call_arguments_internal; @@ -5310,11 +5365,11 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod Entity *p = procs[i]; Type *pt = base_type(p->type); if (pt != NULL && is_type_proc(pt)) { - i64 score = 0; - CallArgumentError err = call_checker(c, call, pt, operands, CallArgumentMode_NoErrors, &score, &result_type); + CallArgumentData data = {}; + CallArgumentError err = call_checker(c, call, pt, p, operands, CallArgumentMode_NoErrors, &data); if (err == CallArgumentError_None) { valids[valid_count].index = i; - valids[valid_count].score = score; + valids[valid_count].score = data.score; valid_count++; } } @@ -5355,15 +5410,20 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod Entity *e = procs[valids[0].index]; add_entity_use(c, expr, e); proc_type = e->type; - i64 score = 0; - CallArgumentError err = call_checker(c, call, proc_type, operands, CallArgumentMode_ShowErrors, &score, &result_type); + CallArgumentData data = {}; + CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data); + return data; } } else { - i64 score = 0; - CallArgumentError err = call_checker(c, call, proc_type, operands, CallArgumentMode_ShowErrors, &score, &result_type); + Entity *e = entity_of_ident(&c->info, operand->expr); + CallArgumentData data = {}; + CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data); + return data; } - return result_type; + CallArgumentData data = {}; + data.result_type = t_invalid; + return data; } @@ -5498,8 +5558,8 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { } } - Type *result_type = check_call_arguments(c, operand, proc_type, call); - + CallArgumentData data = check_call_arguments(c, operand, proc_type, call); + Type *result_type = data.result_type; gb_zero_item(operand); operand->expr = call; |