From d7cb460833e6dde3e3b958b993eee3eee4ae3bf0 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 29 Sep 2022 09:46:58 +0200 Subject: Fix variable append logic in script --- libbuild2/test/script/parser+for.test.testscript | 4 +-- libbuild2/test/script/parser.cxx | 46 ++++++++++++++++++------ 2 files changed, 36 insertions(+), 14 deletions(-) (limited to 'libbuild2/test/script') diff --git a/libbuild2/test/script/parser+for.test.testscript b/libbuild2/test/script/parser+for.test.testscript index 92fc714..70c1c89 100644 --- a/libbuild2/test/script/parser+for.test.testscript +++ b/libbuild2/test/script/parser+for.test.testscript @@ -87,9 +87,7 @@ cmd $x end EOI - error: type mismatch in variable x - info: value type is dir_path - info: variable type is string + testscript:1:1: error: conflicting variable x type string and value type dir_path EOE : scope-var diff --git a/libbuild2/test/script/parser.cxx b/libbuild2/test/script/parser.cxx index 0ba5a79..f302aee 100644 --- a/libbuild2/test/script/parser.cxx +++ b/libbuild2/test/script/parser.cxx @@ -1549,19 +1549,27 @@ namespace build2 // Note that we rely on "small function object" optimization for the // exec_*() lambdas. // - auto exec_assign = [this] (const variable& var, - value&& val, - type kind, - const location& l) + auto exec_set = [this] (const variable& var, + token& t, build2::script::token_type& tt, + const location&) { + next (t, tt); + type kind (tt); // Assignment kind. + + // We cannot reuse the value mode (see above for details). + // + mode (lexer_mode::variable_line); + value rhs (parse_variable_line (t, tt)); + + assert (tt == type::newline); + + // Assign. + // value& lhs (kind == type::assign ? scope_->assign (var) : scope_->append (var)); - if (kind == type::assign) - lhs = move (val); - else - append_value (&var, lhs, move (val), l); + apply_value_attributes (&var, lhs, move (rhs), kind); if (script_->test_command_var (var.name)) scope_->reset_special (); @@ -1601,6 +1609,22 @@ namespace build2 return runner_->run_cond (*scope_, ce, ii, li, ll); }; + auto exec_for = [this] (const variable& var, + value&& val, + const location& l) + { + value& lhs (scope_->assign (var)); + + // To match the function semantics also pass the value's type + // attribute, restoring it from RHS. Note that the value can't be + // NULL. + // + apply_value (&var, lhs, move (val), type::assign, l, val.type); + + if (script_->test_command_var (var.name)) + scope_->reset_special (); + }; + size_t li (1); if (test* t = dynamic_cast (scope_)) @@ -1608,7 +1632,7 @@ namespace build2 ct = command_type::test; exec_lines (t->tests_.begin (), t->tests_.end (), - exec_assign, exec_cmd, exec_cond, + exec_set, exec_cmd, exec_cond, exec_for, nullptr /* iteration_index */, li); } else if (group* g = dynamic_cast (scope_)) @@ -1617,7 +1641,7 @@ namespace build2 bool exec_scope ( exec_lines (g->setup_.begin (), g->setup_.end (), - exec_assign, exec_cmd, exec_cond, + exec_set, exec_cmd, exec_cond, exec_for, nullptr /* iteration_index */, li)); if (exec_scope) @@ -1788,7 +1812,7 @@ namespace build2 ct = command_type::teardown; exec_lines (g->tdown_.begin (), g->tdown_.end (), - exec_assign, exec_cmd, exec_cond, + exec_set, exec_cmd, exec_cond, exec_for, nullptr /* iteration_index */, li); } else -- cgit v1.1