Filter: Fix handling of variables in anonymous filters

Define scope for anonymous filters, and also explicitly distinguish block
scopes and function/filter scopes instead of using anonymous / named
distinction.

Anonymous filters forgot to push scope, so variables for them were in
fact defined in the top scope and therefore they shared a frame. This got
broken after rework of variables, which assumed that there is a named
scope for every function/filter.
This commit is contained in:
Ondrej Zajicek 2022-10-18 03:58:19 +02:00
parent 3242529750
commit e471f9e0fb
3 changed files with 19 additions and 10 deletions

View file

@ -812,7 +812,7 @@ cf_push_soft_scope(void)
if (conf_this_scope->soft_scopes < 0xfe) if (conf_this_scope->soft_scopes < 0xfe)
conf_this_scope->soft_scopes++; conf_this_scope->soft_scopes++;
else else
cf_push_scope(NULL); cf_push_block_scope();
} }
/** /**
@ -826,7 +826,7 @@ cf_pop_soft_scope(void)
if (conf_this_scope->soft_scopes) if (conf_this_scope->soft_scopes)
conf_this_scope->soft_scopes--; conf_this_scope->soft_scopes--;
else else
cf_pop_scope(); cf_pop_block_scope();
} }
/** /**
@ -841,7 +841,7 @@ cf_swap_soft_scope(void)
if (conf_this_scope->soft_scopes) if (conf_this_scope->soft_scopes)
{ {
conf_this_scope->soft_scopes--; conf_this_scope->soft_scopes--;
cf_push_scope(NULL); cf_push_block_scope();
} }
} }

View file

@ -134,6 +134,7 @@ struct sym_scope {
struct symbol *name; /* Name of this scope */ struct symbol *name; /* Name of this scope */
uint slots; /* Variable slots */ uint slots; /* Variable slots */
byte active; /* Currently entered */ byte active; /* Currently entered */
byte block; /* No independent stack frame */
byte soft_scopes; /* Number of soft scopes above */ byte soft_scopes; /* Number of soft scopes above */
}; };
@ -220,6 +221,12 @@ void cf_pop_scope(void);
void cf_push_soft_scope(void); void cf_push_soft_scope(void);
void cf_pop_soft_scope(void); void cf_pop_soft_scope(void);
static inline void cf_push_block_scope(void)
{ cf_push_scope(NULL); conf_this_scope->block = 1; }
static inline void cf_pop_block_scope(void)
{ ASSERT(conf_this_scope->block); cf_pop_scope(); }
char *cf_symbol_class_name(struct symbol *sym); char *cf_symbol_class_name(struct symbol *sym);
/* Parser */ /* Parser */

View file

@ -28,9 +28,9 @@ f_new_var(struct sym_scope *s)
/* /*
* - A variable is an offset on vstack from vbase. * - A variable is an offset on vstack from vbase.
* - Vbase is set on filter start / function call. * - Vbase is set on filter start / function call.
* - Scopes contain anonymous scopes (blocks) inside filter/function scope * - Scopes contain (non-frame) block scopes inside filter/function scope
* - Each scope knows number of vars in that scope * - Each scope knows number of vars in that scope
* - Offset is therefore a sum of 'slots' up to named scope * - Offset is therefore a sum of 'slots' up to filter/function scope
* - New variables are added on top of vstk, so intermediate values cannot * - New variables are added on top of vstk, so intermediate values cannot
* be there during FI_VAR_INIT. I.e. no 'var' inside 'term'. * be there during FI_VAR_INIT. I.e. no 'var' inside 'term'.
* - Also, each f_line must always have its scope, otherwise a variable may * - Also, each f_line must always have its scope, otherwise a variable may
@ -39,7 +39,7 @@ f_new_var(struct sym_scope *s)
int offset = s->slots++; int offset = s->slots++;
while (!s->name) while (s->block)
{ {
s = s->next; s = s->next;
ASSERT(s); ASSERT(s);
@ -465,10 +465,12 @@ filter:
cf_assert_symbol($1, SYM_FILTER); cf_assert_symbol($1, SYM_FILTER);
$$ = $1->filter; $$ = $1->filter;
} }
| filter_body { | { cf_push_scope(NULL); } filter_body {
struct filter *f = cfg_alloc(sizeof(struct filter)); struct filter *f = cfg_alloc(sizeof(struct filter));
*f = (struct filter) { .root = $1 }; *f = (struct filter) { .root = $2 };
$$ = f; $$ = f;
cf_pop_scope();
} }
; ;
@ -913,13 +915,13 @@ cmd:
} }
| FOR { | FOR {
/* Reserve space for walk data on stack */ /* Reserve space for walk data on stack */
cf_push_scope(NULL); cf_push_block_scope();
conf_this_scope->slots += 2; conf_this_scope->slots += 2;
} for_var IN } for_var IN
/* Parse term in the parent scope */ /* Parse term in the parent scope */
{ conf_this_scope->active = 0; } term { conf_this_scope->active = 1; } { conf_this_scope->active = 0; } term { conf_this_scope->active = 1; }
DO cmd { DO cmd {
cf_pop_scope(); cf_pop_block_scope();
$$ = f_new_inst(FI_FOR_INIT, $6, $3); $$ = f_new_inst(FI_FOR_INIT, $6, $3);
$$->next = f_new_inst(FI_FOR_NEXT, $3, $9); $$->next = f_new_inst(FI_FOR_NEXT, $3, $9);
} }