diff options
| author | gingerBill <bill@gingerbill.org> | 2019-10-26 11:50:42 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2019-10-26 11:50:42 +0100 |
| commit | 2c75fe2314aa6de6c8f80d519bbb1812ad77b444 (patch) | |
| tree | 9e925e975a60ee65550dac4c615f6540515db455 /src | |
| parent | 1da0668653a4bc800a56629664f4e716c4560fa3 (diff) | |
Allow for cycles in record polymorphic parameters but not in actualized fields
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.cpp | 72 |
1 files changed, 41 insertions, 31 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 195443159..ea9248089 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6127,47 +6127,57 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper defer (array_free(&operands)); bool named_fields = false; - - if (is_call_expr_field_value(ce)) { - named_fields = true; - operands = array_make<Operand>(heap_allocator(), ce->args.count); - for_array(i, ce->args) { - Ast *arg = ce->args[i]; - ast_node(fv, FieldValue, arg); - - if (fv->field->kind == Ast_Ident) { - String name = fv->field->Ident.token.string; - isize index = lookup_polymorphic_record_parameter(original_type, name); - if (index >= 0) { - TypeTuple *params = get_record_polymorphic_params(original_type); - Entity *e = params->variables[i]; - if (e->kind == Entity_Constant) { - check_expr_with_type_hint(c, &operands[i], fv->value, e->type); + { + // NOTE(bill, 2019-10-26): Allow a cycle in the parameters but not in the fields themselves + auto prev_type_path = c->type_path; + c->type_path = new_checker_type_path(); + defer ({ + destroy_checker_type_path(c->type_path); + c->type_path = prev_type_path; + }); + + if (is_call_expr_field_value(ce)) { + named_fields = true; + operands = array_make<Operand>(heap_allocator(), ce->args.count); + for_array(i, ce->args) { + Ast *arg = ce->args[i]; + ast_node(fv, FieldValue, arg); + + if (fv->field->kind == Ast_Ident) { + String name = fv->field->Ident.token.string; + isize index = lookup_polymorphic_record_parameter(original_type, name); + if (index >= 0) { + TypeTuple *params = get_record_polymorphic_params(original_type); + Entity *e = params->variables[i]; + if (e->kind == Entity_Constant) { + check_expr_with_type_hint(c, &operands[i], fv->value, e->type); + } } + } + check_expr_or_type(c, &operands[i], fv->value); + } + bool vari_expand = (ce->ellipsis.pos.line != 0); + if (vari_expand) { + error(ce->ellipsis, "Invalid use of '..' in a polymorphic type call'"); } - check_expr_or_type(c, &operands[i], fv->value); - } - bool vari_expand = (ce->ellipsis.pos.line != 0); - if (vari_expand) { - error(ce->ellipsis, "Invalid use of '..' in a polymorphic type call'"); - } + } else { + operands = array_make<Operand>(heap_allocator(), 0, 2*ce->args.count); - } else { - operands = array_make<Operand>(heap_allocator(), 0, 2*ce->args.count); + Entity **lhs = nullptr; + isize lhs_count = -1; - Entity **lhs = nullptr; - isize lhs_count = -1; + TypeTuple *params = get_record_polymorphic_params(original_type); + if (params != nullptr) { + lhs = params->variables.data; + lhs_count = params->variables.count; + } - TypeTuple *params = get_record_polymorphic_params(original_type); - if (params != nullptr) { - lhs = params->variables.data; - lhs_count = params->variables.count; + check_unpack_arguments(c, lhs, lhs_count, &operands, ce->args, false, false); } - check_unpack_arguments(c, lhs, lhs_count, &operands, ce->args, false, false); } CallArgumentError err = CallArgumentError_None; |