aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-10-01 20:27:02 +0100
committerGinger Bill <bill@gingerbill.org>2017-10-01 20:27:02 +0100
commitafb5538e832d7772b5149c899e78ccb8edf2dde3 (patch)
treeb19b8ab0a6869d6b9f90443fa9002862d394f2b5 /src/check_expr.cpp
parent1f24f105cc49cff6bbe1034215ae86cb4450f831 (diff)
Default procedure values for `proc`
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp74
1 files changed, 71 insertions, 3 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index afa8327a0..ceac342b4 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -1071,7 +1071,26 @@ Array<Entity *> check_struct_fields(Checker *c, AstNode *node, Array<AstNode *>
if (is_operand_nil(o)) {
default_is_nil = true;
} else if (o.mode != Addressing_Constant) {
- error(default_value, "Default parameter must be a constant");
+ if (default_value->kind == AstNode_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 == AstNode_Ident) {
+ e = check_ident(c, &x, default_value, nullptr, nullptr, false);
+ } else if (default_value->kind == AstNode_SelectorExpr) {
+ e = check_selector(c, &x, default_value, nullptr);
+ }
+ }
+
+ if (e != nullptr && e->kind == Entity_Procedure) {
+ value = exact_value_procedure(e->identifier);
+ add_entity_use(c, e->identifier, e);
+ } else {
+ error(default_value, "Default parameter must be a constant");
+ }
+ }
} else {
value = o.value;
}
@@ -2132,7 +2151,26 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
if (is_operand_nil(o)) {
default_is_nil = true;
} else if (o.mode != Addressing_Constant) {
- error(default_value, "Default parameter must be a constant");
+ if (default_value->kind == AstNode_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 == AstNode_Ident) {
+ e = check_ident(c, &x, default_value, nullptr, nullptr, false);
+ } else if (default_value->kind == AstNode_SelectorExpr) {
+ e = check_selector(c, &x, default_value, nullptr);
+ }
+ }
+
+ if (e != nullptr && e->kind == Entity_Procedure) {
+ value = exact_value_procedure(e->identifier);
+ add_entity_use(c, e->identifier, e);
+ } else {
+ error(default_value, "Default parameter must be a constant");
+ }
+ }
} else {
value = o.value;
}
@@ -2201,7 +2239,26 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
if (is_operand_nil(o)) {
default_is_nil = true;
} else if (o.mode != Addressing_Constant) {
- error(default_value, "Default parameter must be a constant");
+ if (default_value->kind == AstNode_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 == AstNode_Ident) {
+ e = check_ident(c, &x, default_value, nullptr, nullptr, false);
+ } else if (default_value->kind == AstNode_SelectorExpr) {
+ e = check_selector(c, &x, default_value, nullptr);
+ }
+ }
+
+ if (e != nullptr && e->kind == Entity_Procedure) {
+ value = exact_value_procedure(e->identifier);
+ add_entity_use(c, e->identifier, e);
+ } else {
+ error(default_value, "Default parameter must be a constant");
+ }
+ }
} else {
value = o.value;
}
@@ -2682,11 +2739,22 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
Type *params = check_get_params(c, c->context.scope, pt->params, &variadic, &success, &specialization_count, operands);
Type *results = check_get_results(c, c->context.scope, pt->results);
+
isize param_count = 0;
isize result_count = 0;
if (params) param_count = params ->Tuple.variables.count;
if (results) result_count = results->Tuple.variables.count;
+ 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;
+ }
+ }
+ }
+
type->Proc.node = proc_type_node;
type->Proc.scope = c->context.scope;
type->Proc.params = params;