From 60711dd355540b0b315a4508fc40b0e3b4df7bc9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 5 Aug 2018 23:57:34 +0100 Subject: [PATCH] Refactor default parameter values --- src/check_expr.cpp | 23 ++++---------- src/check_type.cpp | 37 ++++++++++++++++------ src/entity.cpp | 22 +++++++++++--- src/ir.cpp | 76 +++++++++++++++++++++++++++++++++++----------- 4 files changed, 110 insertions(+), 48 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 029d4562c..c5b8b80c5 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4168,9 +4168,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { } if (e->kind == Entity_Variable) { - if (e->Variable.default_value.kind != ExactValue_Invalid || - e->Variable.default_is_nil || - e->Variable.default_is_location) { + if (e->Variable.param_value.kind != ParameterValue_Invalid) { param_count--; continue; } @@ -4190,9 +4188,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { } if (e->kind == Entity_Variable) { - if (e->Variable.default_value.kind != ExactValue_Invalid || - e->Variable.default_is_nil || - e->Variable.default_is_location) { + if (e->Variable.param_value.kind != ParameterValue_Invalid) { param_count_excluding_defaults--; continue; } @@ -4442,10 +4438,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { continue; } if (e->kind == Entity_Variable) { - if (e->Variable.default_value.kind != ExactValue_Invalid) { - score += assign_score_function(1); - continue; - } else if (e->Variable.default_is_nil) { + if (e->Variable.param_value.kind != ParameterValue_Invalid) { score += assign_score_function(1); continue; } @@ -5218,8 +5211,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type case_ast_node(i, Implicit, node) switch (i->kind) { case Token_context: - if (c->proc_name.len == 0) { - error(node, "'context' is only allowed within procedures"); + if (c->proc_name.len == 0 && c->curr_proc_sig == nullptr) { + error(node, "'context' is only allowed within procedures %p", c->curr_proc_decl); return kind; } @@ -5500,11 +5493,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type for (isize i = min_field_count-1; i >= 0; i--) { Entity *e = t->Struct.fields[i]; GB_ASSERT(e->kind == Entity_Variable); - if (e->Variable.default_is_nil) { - min_field_count--; - } else if (e->Variable.default_is_undef) { - min_field_count--; - } else if (e->Variable.default_value.kind != ExactValue_Invalid) { + if (e->Variable.param_value.kind != ParameterValue_Invalid) { min_field_count--; } else { break; diff --git a/src/check_type.cpp b/src/check_type.cpp index 9d840b0d1..8ef485a52 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1065,9 +1065,14 @@ 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->Variable.default_value = value; - param->Variable.default_is_nil = default_is_nil; - param->Variable.default_is_location = default_is_location; + if (default_is_nil) { + 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) { param->flags |= EntityFlag_NoAlias; @@ -1194,8 +1199,12 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) { Token token = ast_token(field->type); token.string = str_lit(""); Entity *param = alloc_entity_param(scope, token, type, false, false); - param->Variable.default_value = value; - param->Variable.default_is_nil = default_is_nil; + if (default_is_nil) { + 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); } else { for_array(j, field->names) { @@ -1218,8 +1227,12 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) { Entity *param = alloc_entity_param(scope, token, type, false, false); param->flags |= EntityFlag_Result; - param->Variable.default_value = value; - param->Variable.default_is_nil = default_is_nil; + if (default_is_nil) { + 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); add_entity(ctx->checker, scope, name, param); } @@ -1465,9 +1478,13 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, if (param_count > 0) { for_array(i, params->Tuple.variables) { Entity *param = params->Tuple.variables[i]; - if (param->kind == Entity_Variable && param->Variable.default_value.kind == ExactValue_Procedure) { - type->Proc.has_proc_default_values = true; - break; + if (param->kind == Entity_Variable) { + ParameterValue pv = param->Variable.param_value; + if (pv.kind == ParameterValue_Constant && + pv.value.kind == ExactValue_Procedure) { + type->Proc.has_proc_default_values = true; + break; + } } } } diff --git a/src/entity.cpp b/src/entity.cpp index fa76026ff..1374f8c06 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -56,6 +56,19 @@ enum EntityState { }; +enum ParameterValueKind { + ParameterValue_Invalid, + ParameterValue_Constant, + ParameterValue_Nil, + ParameterValue_Location, +}; + +struct ParameterValue { + ParameterValueKind kind; + ExactValue value; +}; + + // An Entity is a named "thing" in the language struct Entity { EntityKind kind; @@ -84,7 +97,9 @@ struct Entity { struct { i32 field_index; i32 field_src_index; - ExactValue default_value; + + ParameterValue param_value; + String thread_local_model; Entity * foreign_library; Ast * foreign_library_ident; @@ -93,9 +108,8 @@ struct Entity { bool is_foreign; bool is_export; - bool default_is_nil; - bool default_is_undef; - bool default_is_location; + // bool default_is_nil; + // bool default_is_location; bool is_immutable; } Variable; struct { diff --git a/src/ir.cpp b/src/ir.cpp index 311b0496d..d11812455 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -5348,10 +5348,17 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) { } else { GB_ASSERT(e->kind == Entity_Variable); if (args[i] == nullptr) { - if (e->Variable.default_value.kind != ExactValue_Invalid) { - args[i] = ir_value_constant(e->type, e->Variable.default_value); - } else { + switch (e->Variable.param_value.kind) { + case ParameterValue_Constant: + args[i] = ir_value_constant(e->type, e->Variable.param_value.value); + break; + case ParameterValue_Nil: args[i] = ir_value_nil(e->type); + break; + case ParameterValue_Location: + // args[i] = + GB_PANIC("TODO ParameterValue_Location"); + break; } } else { args[i] = ir_emit_conv(proc, args[i], e->type); @@ -5434,12 +5441,17 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) { while (arg_index < end) { Entity *e = param_tuple->variables[arg_index]; GB_ASSERT(e->kind == Entity_Variable); - if (e->Variable.default_value.kind != ExactValue_Invalid) { - args[arg_index++] = ir_value_constant(e->type, e->Variable.default_value); - } else if (e->Variable.default_is_location) { - args[arg_index++] = ir_emit_source_code_location(proc, proc_name, pos); - } else { + + switch (e->Variable.param_value.kind) { + case ParameterValue_Constant: + args[arg_index++] = ir_value_constant(e->type, e->Variable.param_value.value); + break; + case ParameterValue_Nil: args[arg_index++] = ir_value_nil(e->type); + break; + case ParameterValue_Location: + args[arg_index++] = ir_emit_source_code_location(proc, proc_name, pos); + break; } } } @@ -5521,12 +5533,16 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) { if (variadic && variadic_index+1 < param_count) { for (isize i = variadic_index+1; i < param_count; i++) { Entity *e = param_tuple->variables[i]; - if (e->Variable.default_value.kind != ExactValue_Invalid) { - args[i] = ir_value_constant(e->type, e->Variable.default_value); - } else if (e->Variable.default_is_location) { - args[i] = ir_emit_source_code_location(proc, proc_name, pos); - } else { + switch (e->Variable.param_value.kind) { + case ParameterValue_Constant: + args[i] = ir_value_constant(e->type, e->Variable.param_value.value); + break; + case ParameterValue_Nil: args[i] = ir_value_nil(e->type); + break; + case ParameterValue_Location: + args[i] = ir_emit_source_code_location(proc, proc_name, pos); + break; } } } @@ -7602,8 +7618,20 @@ void ir_begin_procedure_body(irProcedure *proc) { if (e->token.string != "") { GB_ASSERT(!is_blank_ident(e->token)); irValue *res = ir_add_local(proc, e, e->identifier, true); - if (e->Variable.default_value.kind != ExactValue_Invalid) { - irValue *c = ir_value_constant(e->type, e->Variable.default_value); + + irValue *c = nullptr; + switch (e->Variable.param_value.kind) { + case ParameterValue_Constant: + c = ir_value_constant(e->type, e->Variable.param_value.value); + break; + case ParameterValue_Nil: + c = ir_value_nil(e->type); + break; + case ParameterValue_Location: + GB_PANIC("ParameterValue_Location"); + break; + } + if (c != nullptr) { ir_emit_store(proc, res, c); } } @@ -7704,8 +7732,22 @@ void ir_build_proc(irValue *value, irProcedure *parent) { for_array(i, p->params->Tuple.variables) { Entity *f = p->params->Tuple.variables[i]; if (f->kind == Entity_Variable) { - if (f->Variable.default_value.kind == ExactValue_Procedure) { - Ast *expr = f->Variable.default_value.value_procedure; + ParameterValue pv = f->Variable.param_value; + if (pv.kind == ParameterValue_Constant && pv.value.kind == ExactValue_Procedure) { + Ast *expr = f->Variable.param_value.value.value_procedure; + GB_ASSERT(expr != nullptr); + if (expr->kind == Ast_ProcLit) { + ir_gen_anonymous_proc_lit(proc->module, proc->name, expr, proc); + } + } + } + } + for_array(i, p->results->Tuple.variables) { + Entity *f = p->results->Tuple.variables[i]; + if (f->kind == Entity_Variable) { + ParameterValue pv = f->Variable.param_value; + if (pv.kind == ParameterValue_Constant && pv.value.kind == ExactValue_Procedure) { + Ast *expr = f->Variable.param_value.value.value_procedure; GB_ASSERT(expr != nullptr); if (expr->kind == Ast_ProcLit) { ir_gen_anonymous_proc_lit(proc->module, proc->name, expr, proc);