summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2022-03-01 02:04:35 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2022-06-27 21:13:31 +0200
commit4c0c507b1fabbdab557d66eb9d90a2d3c8009880 (patch)
tree0dd48bda43648b60748235504afbd2c6fa771e16 /filter
parentbeb5f78ada79ac90f31f2c4923302c74d9ab38bf (diff)
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.
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y23
-rw-r--r--filter/f-inst.c24
2 files changed, 26 insertions, 21 deletions
diff --git a/filter/config.Y b/filter/config.Y
index 8916ea97..0ab32a57 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -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);
}
;
diff --git a/filter/f-inst.c b/filter/f-inst.c
index 901d2939..0d935859 100644
--- a/filter/f-inst.c
+++ b/filter/f-inst.c
@@ -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);