mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-30 01:44:36 +00:00
Slice variadic expansion ..
This commit is contained in:
@@ -2032,7 +2032,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
||||
}
|
||||
|
||||
AstNode *len = ce->args[1];
|
||||
AstNode *cap = ce->args[2];
|
||||
AstNode *cap = NULL;
|
||||
if (gb_array_count(ce->args) > 2) {
|
||||
cap = ce->args[2];
|
||||
}
|
||||
|
||||
check_expr(c, &op, len);
|
||||
if (op.mode == Addressing_Invalid)
|
||||
@@ -2542,7 +2545,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
||||
}
|
||||
|
||||
AstNode *len = ce->args[1];
|
||||
AstNode *cap = ce->args[2];
|
||||
AstNode *cap = NULL;
|
||||
if (gb_array_count(ce->args) > 2) {
|
||||
cap = ce->args[2];
|
||||
}
|
||||
|
||||
Operand op = {};
|
||||
check_expr(c, &op, len);
|
||||
@@ -2753,6 +2759,7 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
|
||||
isize param_index = 0;
|
||||
isize param_count = 0;
|
||||
b32 variadic = proc_type->Proc.variadic;
|
||||
b32 vari_expand = (ce->ellipsis.pos.line != 0);
|
||||
|
||||
if (proc_type->Proc.params) {
|
||||
param_count = proc_type->Proc.params->Tuple.variable_count;
|
||||
@@ -2782,23 +2789,37 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
|
||||
} else {
|
||||
Entity **sig_params = proc_type->Proc.params->Tuple.variables;
|
||||
gb_for_array(arg_index, ce->args) {
|
||||
AstNode *call_arg = ce->args[arg_index];
|
||||
check_multi_expr(c, operand, call_arg);
|
||||
check_multi_expr(c, operand, ce->args[arg_index]);
|
||||
if (operand->mode == Addressing_Invalid)
|
||||
continue;
|
||||
if (operand->type->kind != Type_Tuple) {
|
||||
check_not_tuple(c, operand);
|
||||
isize index = param_index;
|
||||
b32 end_variadic = false;
|
||||
b32 variadic_expand = false;
|
||||
if (variadic && param_index >= param_count-1) {
|
||||
index = param_count-1;
|
||||
end_variadic = true;
|
||||
if (vari_expand) {
|
||||
variadic_expand = true;
|
||||
if (param_index != param_count-1) {
|
||||
error(&c->error_collector, ast_node_token(operand->expr),
|
||||
"`..` in a variadic procedure can only have one variadic argument at the end");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Type *arg_type = sig_params[index]->type;
|
||||
if (end_variadic && is_type_slice(arg_type)) {
|
||||
arg_type = get_base_type(arg_type)->Slice.elem;
|
||||
if (variadic_expand) {
|
||||
check_assignment(c, operand, arg_type, make_string("argument"), true);
|
||||
} else {
|
||||
arg_type = get_base_type(arg_type)->Slice.elem;
|
||||
check_assignment(c, operand, arg_type, make_string("argument"), true);
|
||||
}
|
||||
} else {
|
||||
check_assignment(c, operand, arg_type, make_string("argument"), true);
|
||||
}
|
||||
check_assignment(c, operand, arg_type, make_string("argument"), true);
|
||||
param_index++;
|
||||
} else {
|
||||
auto *tuple = &operand->type->Tuple;
|
||||
@@ -2815,6 +2836,11 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
|
||||
if (variadic && param_index >= param_count-1) {
|
||||
index = param_count-1;
|
||||
end_variadic = true;
|
||||
if (vari_expand) {
|
||||
error(&c->error_collector, ast_node_token(operand->expr),
|
||||
"`..` in a variadic procedure cannot be applied to a %td-valued expression", tuple->variable_count);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
Type *arg_type = sig_params[index]->type;
|
||||
if (end_variadic && is_type_slice(arg_type)) {
|
||||
@@ -2824,6 +2850,8 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
|
||||
param_index++;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
if (i < tuple->variable_count && param_index == param_count) {
|
||||
error_code = +1;
|
||||
break;
|
||||
|
||||
@@ -2273,6 +2273,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
}
|
||||
ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, arg_count);
|
||||
b32 variadic = proc_type_->Proc.variadic;
|
||||
b32 vari_expand = ce->ellipsis.pos.line != 0;
|
||||
|
||||
gb_for_array(i, ce->args) {
|
||||
ssaValue *a = ssa_build_expr(proc, ce->args[i]);
|
||||
@@ -2295,11 +2296,13 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
for (; i < type->param_count-1; i++) {
|
||||
args[i] = ssa_emit_conv(proc, args[i], pt->variables[i]->type, true);
|
||||
}
|
||||
Type *variadic_type = pt->variables[i]->type;
|
||||
GB_ASSERT(is_type_slice(variadic_type));
|
||||
variadic_type = get_base_type(variadic_type)->Slice.elem;
|
||||
for (; i < arg_count; i++) {
|
||||
args[i] = ssa_emit_conv(proc, args[i], variadic_type, true);
|
||||
if (!vari_expand) {
|
||||
Type *variadic_type = pt->variables[i]->type;
|
||||
GB_ASSERT(is_type_slice(variadic_type));
|
||||
variadic_type = get_base_type(variadic_type)->Slice.elem;
|
||||
for (; i < arg_count; i++) {
|
||||
args[i] = ssa_emit_conv(proc, args[i], variadic_type, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (isize i = 0; i < arg_count; i++) {
|
||||
@@ -2307,7 +2310,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
}
|
||||
}
|
||||
|
||||
if (variadic) {
|
||||
if (variadic && !vari_expand) {
|
||||
ssa_emit_comment(proc, make_string("variadic call argument generation"));
|
||||
gbAllocator allocator = proc->module->allocator;
|
||||
Type *slice_type = pt->variables[type->param_count-1]->type;
|
||||
|
||||
Reference in New Issue
Block a user