From de09fda5dcef16bf50663f7ffb56074e6ad20b5a Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Thu, 5 Oct 2023 14:26:22 +0200 Subject: [PATCH] Filter: Fix scope handling in for loops Changes in scope implementation broke scope handling in for loops. The term in for loops is supposed to be parsed in the parent scope. --- filter/config.Y | 5 ++++- filter/test.conf | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/filter/config.Y b/filter/config.Y index 3cd8e3e4..f3ed2dc5 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -20,6 +20,7 @@ static inline u32 pair_a(u32 p) { return p >> 16; } static inline u32 pair_b(u32 p) { return p & 0xFFFF; } static struct symbol *this_function; +static struct sym_scope *this_for_scope; static struct f_method_scope { struct f_inst *object; @@ -993,7 +994,9 @@ cmd: new_config->current_scope->slots += 2; } for_var IN /* Parse term in the parent scope */ - { new_config->current_scope->active = 0; } term { new_config->current_scope->active = 1; } + { this_for_scope = new_config->current_scope; new_config->current_scope = this_for_scope->next; } + term + { new_config->current_scope = this_for_scope; this_for_scope = NULL; } DO cmd { cf_pop_block_scope(new_config); $$ = f_for_cycle($3, $6, $9); diff --git a/filter/test.conf b/filter/test.conf index 22b4984a..f9289189 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -1938,6 +1938,63 @@ bt_test_suite(t_if_else, "Testing if-else statement"); +/* + * Test for-in statement + * --------------------- + */ + +function t_for_in() +{ + bgppath p = +empty+.prepend(5).prepend(4).prepend(3).prepend(2).prepend(1); + bgppath q = +empty+.prepend(30).prepend(20).prepend(10); + int a; + + # basic for loop + a = 0; + for int i in p do { + a = 2 * a + i; + } + bt_assert(a = 57); + + # basic for loop, no braces + a = 0; + for int i in p do a = 2 * a + i; + bt_assert(a = 57); + + # for loop with empty body + a = 0; + for int i in p do { } + bt_assert(a = 0); + + # for loop over empty path + a = 0; + for int i in +empty+ do a = 1; + bt_assert(a = 0); + + # for loop with var name shadowing + a = 0; + for int p in p do { + a = 2 * a + p; + } + bt_assert(a = 57); + + # nested for loops + a = 0; + int n = 1; + for int i in p do { + for int j in q do { + a = a + i * j * n; + n = n + 1; + } + } + bt_assert(a = 9300); +} + +bt_test_suite(t_for_in, "Testing for-in statement"); + + + + /* * Unused functions -- testing only parsing * ----------------------------------------