mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Refactor handle_parameter_value code
This commit is contained in:
+82
-147
@@ -757,6 +757,72 @@ Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *poly_type, Oper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ParameterValue handle_parameter_value(CheckerContext *ctx, Type *in_type, Type **out_type_, Ast *expr, bool allow_caller_location) {
|
||||||
|
ParameterValue param_value = {};
|
||||||
|
// gb_printf_err("HERE\n");
|
||||||
|
if (expr == nullptr) {
|
||||||
|
return param_value;
|
||||||
|
}
|
||||||
|
Operand o = {};
|
||||||
|
|
||||||
|
if (allow_caller_location &&
|
||||||
|
expr->kind == Ast_BasicDirective &&
|
||||||
|
expr->BasicDirective.name == "caller_location") {
|
||||||
|
init_core_source_code_location(ctx->checker);
|
||||||
|
param_value.kind = ParameterValue_Location;
|
||||||
|
o.type = t_source_code_location;
|
||||||
|
} else {
|
||||||
|
if (in_type) {
|
||||||
|
check_expr_with_type_hint(ctx, &o, expr, in_type);
|
||||||
|
} else {
|
||||||
|
check_expr(ctx, &o, expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_operand_nil(o)) {
|
||||||
|
param_value.kind = ParameterValue_Nil;
|
||||||
|
} else if (o.mode != Addressing_Constant) {
|
||||||
|
if (expr->kind == Ast_ProcLit) {
|
||||||
|
param_value.kind = ParameterValue_Constant;
|
||||||
|
param_value.value = exact_value_procedure(expr);
|
||||||
|
} else {
|
||||||
|
Entity *e = nullptr;
|
||||||
|
if (o.mode == Addressing_Value && is_type_proc(o.type)) {
|
||||||
|
Operand x = {};
|
||||||
|
if (expr->kind == Ast_Ident) {
|
||||||
|
e = check_ident(ctx, &x, expr, nullptr, nullptr, false);
|
||||||
|
} else if (expr->kind == Ast_SelectorExpr) {
|
||||||
|
e = check_selector(ctx, &x, expr, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e != nullptr && e->kind == Entity_Procedure) {
|
||||||
|
param_value.kind = ParameterValue_Constant;
|
||||||
|
param_value.value = exact_value_procedure(e->identifier);
|
||||||
|
add_entity_use(ctx, e->identifier, e);
|
||||||
|
} else {
|
||||||
|
error(expr, "Default parameter must be a constant %d", o.mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (o.value.kind != ExactValue_Invalid) {
|
||||||
|
param_value.kind = ParameterValue_Constant;
|
||||||
|
param_value.value = o.value;
|
||||||
|
} else {
|
||||||
|
error(o.expr, "Invalid constant parameter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_type) {
|
||||||
|
check_is_assignable_to(ctx, &o, in_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_type_) *out_type_ = default_type(o.type);
|
||||||
|
|
||||||
|
return param_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is_variadic_, isize *variadic_index_, bool *success_, isize *specialization_count_, Array<Operand> *operands) {
|
Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is_variadic_, isize *variadic_index_, bool *success_, isize *specialization_count_, Array<Operand> *operands) {
|
||||||
if (_params == nullptr) {
|
if (_params == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -809,9 +875,8 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
|
|||||||
Ast *type_expr = p->type;
|
Ast *type_expr = p->type;
|
||||||
Type *type = nullptr;
|
Type *type = nullptr;
|
||||||
Ast *default_value = unparen_expr(p->default_value);
|
Ast *default_value = unparen_expr(p->default_value);
|
||||||
ExactValue value = {};
|
ParameterValue param_value = {};
|
||||||
bool default_is_nil = false;
|
|
||||||
bool default_is_location = false;
|
|
||||||
bool is_type_param = false;
|
bool is_type_param = false;
|
||||||
bool is_type_polymorphic_type = false;
|
bool is_type_polymorphic_type = false;
|
||||||
bool detemine_type_from_operand = false;
|
bool detemine_type_from_operand = false;
|
||||||
@@ -820,62 +885,16 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
|
|||||||
bool is_using = (p->flags&FieldFlag_using) != 0;
|
bool is_using = (p->flags&FieldFlag_using) != 0;
|
||||||
|
|
||||||
if (type_expr == nullptr) {
|
if (type_expr == nullptr) {
|
||||||
if (default_value->kind == Ast_BasicDirective &&
|
param_value = handle_parameter_value(ctx, nullptr, &type, default_value, true);
|
||||||
default_value->BasicDirective.name == "caller_location") {
|
|
||||||
init_core_source_code_location(ctx->checker);
|
|
||||||
default_is_location = true;
|
|
||||||
type = t_source_code_location;
|
|
||||||
} else {
|
|
||||||
Operand o = {};
|
|
||||||
check_expr_or_type(ctx, &o, default_value);
|
|
||||||
if (is_operand_nil(o)) {
|
|
||||||
default_is_nil = true;
|
|
||||||
} else if (o.mode != Addressing_Constant) {
|
|
||||||
if (default_value->kind == Ast_ProcLit) {
|
|
||||||
value = exact_value_procedure(default_value);
|
|
||||||
} else {
|
|
||||||
Entity *e = nullptr;
|
|
||||||
if (o.mode == Addressing_Value && is_type_proc(o.type)) {
|
|
||||||
Operand x = {};
|
|
||||||
if (default_value->kind == Ast_Ident) {
|
|
||||||
e = check_ident(ctx, &x, default_value, nullptr, nullptr, false);
|
|
||||||
} else if (default_value->kind == Ast_SelectorExpr) {
|
|
||||||
e = check_selector(ctx, &x, default_value, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e != nullptr && e->kind == Entity_Procedure) {
|
|
||||||
value = exact_value_procedure(e->identifier);
|
|
||||||
add_entity_use(ctx, e->identifier, e);
|
|
||||||
} else {
|
|
||||||
error(default_value, "Default parameter must be a constant");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value = o.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
type = default_type(o.type);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (type_expr->kind == Ast_Ellipsis) {
|
if (type_expr->kind == Ast_Ellipsis) {
|
||||||
type_expr = type_expr->Ellipsis.expr;
|
type_expr = type_expr->Ellipsis.expr;
|
||||||
#if 1
|
is_variadic = true;
|
||||||
is_variadic = true;
|
variadic_index = variables.count;
|
||||||
variadic_index = variables.count;
|
if (p->names.count != 1) {
|
||||||
if (p->names.count != 1) {
|
error(param, "Invalid AST: Invalid variadic parameter with multiple names");
|
||||||
error(param, "Invalid AST: Invalid variadic parameter with multiple names");
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (i+1 == params.count) {
|
|
||||||
is_variadic = true;
|
|
||||||
} else {
|
|
||||||
error(param, "Invalid AST: Invalid variadic parameter");
|
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (type_expr->kind == Ast_TypeType) {
|
if (type_expr->kind == Ast_TypeType) {
|
||||||
ast_node(tt, TypeType, type_expr);
|
ast_node(tt, TypeType, type_expr);
|
||||||
@@ -884,13 +903,6 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
|
|||||||
if (specialization == t_invalid){
|
if (specialization == t_invalid){
|
||||||
specialization = nullptr;
|
specialization = nullptr;
|
||||||
}
|
}
|
||||||
// if (specialization) {
|
|
||||||
// if (!is_type_polymorphic(specialization)) {
|
|
||||||
// gbString str = type_to_string(specialization);
|
|
||||||
// error(tt->specialization, "Type specialization requires a polymorphic type, got %s", str);
|
|
||||||
// gb_string_free(str);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (operands != nullptr) {
|
if (operands != nullptr) {
|
||||||
detemine_type_from_operand = true;
|
detemine_type_from_operand = true;
|
||||||
@@ -913,49 +925,10 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (default_value != nullptr) {
|
if (default_value != nullptr) {
|
||||||
if (type_expr->kind == Ast_TypeType) {
|
if (type_expr != nullptr && type_expr->kind == Ast_TypeType) {
|
||||||
error(default_value, "A type parameter may not have a default value");
|
error(type_expr, "A type parameter may not have a default value");
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
Operand o = {};
|
param_value = handle_parameter_value(ctx, type, nullptr, default_value, true);
|
||||||
if (default_value->kind == Ast_BasicDirective &&
|
|
||||||
default_value->BasicDirective.name == "caller_location") {
|
|
||||||
init_core_source_code_location(ctx->checker);
|
|
||||||
default_is_location = true;
|
|
||||||
o.type = t_source_code_location;
|
|
||||||
o.mode = Addressing_Value;
|
|
||||||
} else {
|
|
||||||
check_expr_with_type_hint(ctx, &o, default_value, type);
|
|
||||||
|
|
||||||
if (is_operand_nil(o)) {
|
|
||||||
default_is_nil = true;
|
|
||||||
} else if (o.mode != Addressing_Constant) {
|
|
||||||
if (default_value->kind == Ast_ProcLit) {
|
|
||||||
value = exact_value_procedure(default_value);
|
|
||||||
} else {
|
|
||||||
Entity *e = nullptr;
|
|
||||||
if (o.mode == Addressing_Value && is_type_proc(o.type)) {
|
|
||||||
Operand x = {};
|
|
||||||
if (default_value->kind == Ast_Ident) {
|
|
||||||
e = check_ident(ctx, &x, default_value, nullptr, nullptr, false);
|
|
||||||
} else if (default_value->kind == Ast_SelectorExpr) {
|
|
||||||
e = check_selector(ctx, &x, default_value, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e != nullptr && e->kind == Entity_Procedure) {
|
|
||||||
value = exact_value_procedure(e->identifier);
|
|
||||||
add_entity_use(ctx, e->identifier, e);
|
|
||||||
} else {
|
|
||||||
error(default_value, "Default parameter must be a constant");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value = o.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
check_is_assignable_to(ctx, &o, type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1065,14 +1038,7 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
|
|||||||
}
|
}
|
||||||
|
|
||||||
param = alloc_entity_param(scope, name->Ident.token, type, is_using, is_in);
|
param = alloc_entity_param(scope, name->Ident.token, type, is_using, is_in);
|
||||||
if (default_is_nil) {
|
param->Variable.param_value = param_value;
|
||||||
param->Variable.param_value.kind = ParameterValue_Nil;
|
|
||||||
} else if (default_is_location) {
|
|
||||||
param->Variable.param_value.kind = ParameterValue_Location;
|
|
||||||
} else if (value.kind != ExactValue_Invalid) {
|
|
||||||
param->Variable.param_value.kind = ParameterValue_Constant;
|
|
||||||
param->Variable.param_value.value = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (p->flags&FieldFlag_no_alias) {
|
if (p->flags&FieldFlag_no_alias) {
|
||||||
param->flags |= EntityFlag_NoAlias;
|
param->flags |= EntityFlag_NoAlias;
|
||||||
@@ -1151,37 +1117,16 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
|
|||||||
for_array(i, results) {
|
for_array(i, results) {
|
||||||
ast_node(field, Field, results[i]);
|
ast_node(field, Field, results[i]);
|
||||||
Ast *default_value = unparen_expr(field->default_value);
|
Ast *default_value = unparen_expr(field->default_value);
|
||||||
ExactValue value = {};
|
ParameterValue param_value = {};
|
||||||
bool default_is_nil = false;
|
|
||||||
|
|
||||||
Type *type = nullptr;
|
Type *type = nullptr;
|
||||||
if (field->type == nullptr) {
|
if (field->type == nullptr) {
|
||||||
Operand o = {};
|
handle_parameter_value(ctx, nullptr, &type, default_value, false);
|
||||||
check_expr(ctx, &o, default_value);
|
|
||||||
if (is_operand_nil(o)) {
|
|
||||||
default_is_nil = true;
|
|
||||||
} else if (o.mode != Addressing_Constant) {
|
|
||||||
error(default_value, "Default parameter must be a constant");
|
|
||||||
} else {
|
|
||||||
value = o.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
type = default_type(o.type);
|
|
||||||
} else {
|
} else {
|
||||||
type = check_type(ctx, field->type);
|
type = check_type(ctx, field->type);
|
||||||
|
|
||||||
if (default_value != nullptr) {
|
if (default_value != nullptr) {
|
||||||
Operand o = {};
|
handle_parameter_value(ctx, type, nullptr, default_value, false);
|
||||||
check_expr_with_type_hint(ctx, &o, default_value, type);
|
|
||||||
|
|
||||||
if (is_operand_nil(o)) {
|
|
||||||
default_is_nil = true;
|
|
||||||
} else if (o.mode != Addressing_Constant) {
|
|
||||||
error(default_value, "Default parameter must be a constant");
|
|
||||||
} else {
|
|
||||||
value = o.value;
|
|
||||||
}
|
|
||||||
check_is_assignable_to(ctx, &o, type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1199,12 +1144,7 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
|
|||||||
Token token = ast_token(field->type);
|
Token token = ast_token(field->type);
|
||||||
token.string = str_lit("");
|
token.string = str_lit("");
|
||||||
Entity *param = alloc_entity_param(scope, token, type, false, false);
|
Entity *param = alloc_entity_param(scope, token, type, false, false);
|
||||||
if (default_is_nil) {
|
param->Variable.param_value = param_value;
|
||||||
param->Variable.param_value.kind = ParameterValue_Nil;
|
|
||||||
} else if (value.kind != ExactValue_Invalid) {
|
|
||||||
param->Variable.param_value.kind = ParameterValue_Constant;
|
|
||||||
param->Variable.param_value.value = value;
|
|
||||||
}
|
|
||||||
array_add(&variables, param);
|
array_add(&variables, param);
|
||||||
} else {
|
} else {
|
||||||
for_array(j, field->names) {
|
for_array(j, field->names) {
|
||||||
@@ -1227,12 +1167,7 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
|
|||||||
|
|
||||||
Entity *param = alloc_entity_param(scope, token, type, false, false);
|
Entity *param = alloc_entity_param(scope, token, type, false, false);
|
||||||
param->flags |= EntityFlag_Result;
|
param->flags |= EntityFlag_Result;
|
||||||
if (default_is_nil) {
|
param->Variable.param_value = param_value;
|
||||||
param->Variable.param_value.kind = ParameterValue_Nil;
|
|
||||||
} else if (value.kind != ExactValue_Invalid) {
|
|
||||||
param->Variable.param_value.kind = ParameterValue_Constant;
|
|
||||||
param->Variable.param_value.value = value;
|
|
||||||
}
|
|
||||||
array_add(&variables, param);
|
array_add(&variables, param);
|
||||||
add_entity(ctx->checker, scope, name, param);
|
add_entity(ctx->checker, scope, name, param);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user