Filter: Clean up function call instruction

Pass instructions of function call arguments as vararg arguments to
FI_CALL instruction constructor and move necessary magic from parser
code to interpreter / instruction code.
This commit is contained in:
Ondrej Zajicek (work) 2022-03-01 02:04:35 +01:00 committed by Ondrej Zajicek
parent beb5f78ada
commit 4c0c507b1f
2 changed files with 26 additions and 21 deletions

View file

@ -700,27 +700,22 @@ var_list: /* EMPTY */ { $$ = NULL; }
| var_list ',' term { $$ = $3; $$->next = $1; } | var_list ',' term { $$ = $3; $$->next = $1; }
function_call: function_call:
CF_SYM_KNOWN '(' var_list ')' { CF_SYM_KNOWN '(' var_list ')'
{
if ($1->class != SYM_FUNCTION) if ($1->class != SYM_FUNCTION)
cf_error("You can't call something which is not a function. Really."); cf_error("You can't call something which is not a function. Really.");
struct f_inst *fc = f_new_inst(FI_CALL, $1); /* Revert the var_list */
uint args = 0; struct f_inst *args = NULL;
while ($3) { while ($3) {
args++; struct f_inst *tmp = $3;
struct f_inst *tmp = $3->next; $3 = $3->next;
$3->next = fc;
fc = $3; tmp->next = args;
$3 = tmp; args = tmp;
} }
if (args != $1->function->args) $$ = f_new_inst(FI_CALL, args, $1);
cf_error("Function call '%s' got %u arguments, need %u arguments.",
$1->name, args, $1->function->args);
$$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID });
$$->next = fc;
} }
; ;

View file

@ -1079,8 +1079,22 @@
INST(FI_CALL, 0, 1) { INST(FI_CALL, 0, 1) {
NEVER_CONSTANT; NEVER_CONSTANT;
VARARG;
SYMBOL; SYMBOL;
FID_NEW_BODY()
ASSERT(sym->class == SYM_FUNCTION);
if (whati->varcount != sym->function->args)
cf_error("Function '%s' expects %u arguments, got %u arguments",
sym->name, sym->function->args, whati->varcount);
/* Add implicit void slot for the return value */
struct f_inst *tmp = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID });
tmp->next = whati->fvar;
whati->fvar = tmp;
what->size += tmp->size;
FID_SAME_BODY() FID_SAME_BODY()
if (!(f1->sym->flags & SYM_FLAG_SAME)) if (!(f1->sym->flags & SYM_FLAG_SAME))
return 0; return 0;
@ -1092,15 +1106,11 @@
/* Push the body on stack */ /* Push the body on stack */
LINEX(sym->function); LINEX(sym->function);
curline.vbase = curline.ventry;
curline.emask |= FE_RETURN; curline.emask |= FE_RETURN;
/* Before this instruction was called, there was the T_VOID /* Arguments on stack */
* automatic return value pushed on value stack and also fstk->vcnt += sym->function->args;
* sym->function->args function arguments. Setting the
* vbase to point to first argument. */
ASSERT(curline.ventry >= sym->function->args);
curline.ventry -= sym->function->args;
curline.vbase = curline.ventry;
/* Storage for local variables */ /* Storage for local variables */
memset(&(fstk->vstk[fstk->vcnt]), 0, sizeof(struct f_val) * sym->function->vars); memset(&(fstk->vstk[fstk->vcnt]), 0, sizeof(struct f_val) * sym->function->vars);