diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-06-22 01:14:45 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-06-22 01:14:45 +0100 |
| commit | 8197c02dcf964be404cd199858e84e9e8f3905e5 (patch) | |
| tree | 177393f565eddb1178423d776cb275d56cfcffee /src/check_expr.cpp | |
| parent | 9faf0020cc04c9c27fc7a7e7e41edce6df31376e (diff) | |
Default result values for procedure types; Named result values in `return` statements
Diffstat (limited to 'src/check_expr.cpp')
| -rw-r--r-- | src/check_expr.cpp | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 639cc27db..317822b84 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1221,15 +1221,64 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) { isize variable_index = 0; for_array(i, results) { ast_node(field, Field, results[i]); - Type *type = check_type(c, field->type); + AstNode *default_value = unparen_expr(field->default_value); + ExactValue value = {}; + bool default_is_nil = false; + + Type *type = NULL; + if (field->type == NULL) { + Operand o = {}; + check_expr(c, &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 { + type = check_type(c, field->type); + + if (default_value != NULL) { + Operand o = {}; + check_expr_with_type_hint(c, &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(c, &o, type); + } + } + + if (type == NULL) { + error(results[i], "Invalid parameter type"); + type = t_invalid; + } + if (is_type_untyped(type)) { + error(results[i], "Cannot determine parameter type from a nil"); + type = t_invalid; + } + + if (field->names.count == 0) { Token token = ast_node_token(field->type); token.string = str_lit(""); Entity *param = make_entity_param(c->allocator, scope, token, type, false, false); + param->Variable.default_value = value; + param->Variable.default_is_nil = default_is_nil; variables[variable_index++] = param; } else { for_array(j, field->names) { - Token token = ast_node_token(field->type); + Token token = ast_node_token(results[i]); + if (field->type != NULL) { + token = ast_node_token(field->type); + } token.string = str_lit(""); AstNode *name = field->names[j]; @@ -1240,6 +1289,8 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) { } Entity *param = make_entity_param(c->allocator, scope, token, type, false, false); + param->Variable.default_value = value; + param->Variable.default_is_nil = default_is_nil; variables[variable_index++] = param; } } @@ -5002,6 +5053,20 @@ isize lookup_procedure_parameter(TypeProc *pt, String parameter_name) { } return -1; } +isize lookup_procedure_result(TypeProc *pt, String result_name) { + isize result_count = pt->result_count; + for (isize i = 0; i < result_count; i++) { + Entity *e = pt->results->Tuple.variables[i]; + String name = e->token.string; + if (name == "_") { + continue; + } + if (name == result_name) { + return i; + } + } + return -1; +} CALL_ARGUMENT_CHECKER(check_named_call_arguments) { ast_node(ce, CallExpr, call); @@ -5013,7 +5078,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { CallArgumentError err = CallArgumentError_None; isize param_count = pt->param_count; - bool *params_visited = gb_alloc_array(c->allocator, bool, param_count); + bool *visited = gb_alloc_array(c->allocator, bool, param_count); for_array(i, ce->args) { AstNode *arg = ce->args[i]; @@ -5036,7 +5101,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { err = CallArgumentError_ParameterNotFound; continue; } - if (params_visited[index]) { + if (visited[index]) { if (show_error) { error(arg, "Duplicate parameter `%.*s` in procedure call", LIT(name)); } @@ -5044,7 +5109,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { continue; } - params_visited[index] = true; + visited[index] = true; Operand *o = &operands[i]; Entity *e = pt->params->Tuple.variables[index]; @@ -5076,7 +5141,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { param_count_to_check--; } for (isize i = 0; i < param_count_to_check; i++) { - if (!params_visited[i]) { + if (!visited[i]) { Entity *e = pt->params->Tuple.variables[i]; if (e->token.string == "_") { continue; @@ -5095,7 +5160,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { if (show_error) { gbString str = type_to_string(e->type); error(call, "Parameter `%.*s` of type `%s` is missing in procedure call", - LIT(e->token.string), str); + LIT(e->token.string), str); gb_string_free(str); } err = CallArgumentError_ParameterMissing; |