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; }
|
| 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;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue