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:
parent
3242529750
commit
e471f9e0fb
3 changed files with 19 additions and 10 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue