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:
parent
beb5f78ada
commit
4c0c507b1f
2 changed files with 26 additions and 21 deletions
|
@ -700,27 +700,22 @@ var_list: /* EMPTY */ { $$ = NULL; }
|
|||
| var_list ',' term { $$ = $3; $$->next = $1; }
|
||||
|
||||
function_call:
|
||||
CF_SYM_KNOWN '(' var_list ')' {
|
||||
CF_SYM_KNOWN '(' var_list ')'
|
||||
{
|
||||
if ($1->class != SYM_FUNCTION)
|
||||
cf_error("You can't call something which is not a function. Really.");
|
||||
|
||||
struct f_inst *fc = f_new_inst(FI_CALL, $1);
|
||||
uint args = 0;
|
||||
/* Revert the var_list */
|
||||
struct f_inst *args = NULL;
|
||||
while ($3) {
|
||||
args++;
|
||||
struct f_inst *tmp = $3->next;
|
||||
$3->next = fc;
|
||||
struct f_inst *tmp = $3;
|
||||
$3 = $3->next;
|
||||
|
||||
fc = $3;
|
||||
$3 = tmp;
|
||||
tmp->next = args;
|
||||
args = tmp;
|
||||
}
|
||||
|
||||
if (args != $1->function->args)
|
||||
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;
|
||||
$$ = f_new_inst(FI_CALL, args, $1);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
@ -1079,8 +1079,22 @@
|
|||
|
||||
INST(FI_CALL, 0, 1) {
|
||||
NEVER_CONSTANT;
|
||||
VARARG;
|
||||
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()
|
||||
if (!(f1->sym->flags & SYM_FLAG_SAME))
|
||||
return 0;
|
||||
|
@ -1092,15 +1106,11 @@
|
|||
|
||||
/* Push the body on stack */
|
||||
LINEX(sym->function);
|
||||
curline.vbase = curline.ventry;
|
||||
curline.emask |= FE_RETURN;
|
||||
|
||||
/* Before this instruction was called, there was the T_VOID
|
||||
* automatic return value pushed on value stack and also
|
||||
* 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;
|
||||
/* Arguments on stack */
|
||||
fstk->vcnt += sym->function->args;
|
||||
|
||||
/* Storage for local variables */
|
||||
memset(&(fstk->vstk[fstk->vcnt]), 0, sizeof(struct f_val) * sym->function->vars);
|
||||
|
|
Loading…
Reference in a new issue