From 47ae21f6558f81ae7c13d143d297f61acae2b530 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 19 Sep 2022 10:13:48 +0200 Subject: Allow computed variables in depdb preamble similar to impure functions --- libbuild2/build/script/parser.cxx | 46 +++++++++++++++++++++++++++++++++------ libbuild2/build/script/parser.hxx | 9 +++++++- libbuild2/build/script/script.hxx | 3 ++- libbuild2/parser.hxx | 2 +- 4 files changed, 50 insertions(+), 10 deletions(-) (limited to 'libbuild2') diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx index 2112b5e..0614f20 100644 --- a/libbuild2/build/script/parser.cxx +++ b/libbuild2/build/script/parser.cxx @@ -93,6 +93,15 @@ namespace build2 info << "consider using 'depdb' builtin to track its result " << "changes"; + // Diagnose computed variable exansions. + // + if (computed_var_) + fail (*computed_var_) + << "expansion of computed variable is only allowed in depdb " + << "preamble" << + info << "consider using 'depdb' builtin to track its value " + << "changes"; + // Diagnose absent/ambigous script name. // { @@ -137,6 +146,7 @@ namespace build2 // Save the custom dependency change tracking lines, if present. // s.depdb_clear = depdb_clear_.has_value (); + s.depdb_value = depdb_value_; if (depdb_dyndep_) { s.depdb_dyndep = depdb_dyndep_->second; @@ -579,6 +589,8 @@ namespace build2 info (depdb_dyndep_->first) << "'depdb dyndep' call is here"; } + depdb_value_ = depdb_value_ || (v == "string" || v == "hash"); + // Move the script body to the end of the depdb preamble. // // Note that at this (pre-parsing) stage we cannot evaluate if @@ -603,10 +615,12 @@ namespace build2 script_->body_temp_dir = false; } - // Reset the impure function call info since it's valid for the - // depdb preamble. + // Reset the impure function call and computed variable + // expansion tracking since both are valid for the depdb + // preamble. // impure_func_ = nullopt; + computed_var_ = nullopt; // Instruct the parser to save the depdb builtin line separately // from the script lines, when it is fully parsed. Note that the @@ -2299,6 +2313,9 @@ namespace build2 // In the pre-parse mode collect the referenced variable names for the // script semantics change tracking. // + // Note that during pre-parse a computed (including qualified) name + // is signalled as an empty name. + // if (pre_parse_ || pre_parse_suspended_) { lookup r; @@ -2332,12 +2349,27 @@ namespace build2 vars.push_back (move (name)); } } + else + { + // What about pre_parse_suspended_? Don't think it makes sense to + // diagnose this since it can be indirect (that is, via an + // intermediate variable). + // + if (perform_update_ && file_based_ && !computed_var_) + computed_var_ = loc; + } return r; } if (!qual.empty ()) - fail (loc) << "qualified variable name"; + { + // Qualified variable is computed and we expect the user to track + // its changes manually. + // + return build2::script::parser::lookup_variable ( + move (qual), move (name), loc); + } lookup r (environment_->lookup (name)); @@ -2348,13 +2380,13 @@ namespace build2 // diag builtin argument change (which can be affected by such a // variable expansion) doesn't affect the script semantics and the // depdb argument is specifically used for the script semantics change - // tracking. We also omit this check it the depdb builtin is used in - // the script, assuming that such variables are tracked manually, if - // required. + // tracking. We also omit this check if the depdb "value" (string, + // hash) builtin is used in the script, assuming that such variables + // are tracked manually, if required. // if (script_ != nullptr && !script_->depdb_clear && - script_->depdb_preamble.empty ()) + !script_->depdb_value) { if (r.defined () && !r.belongs (*environment_)) { diff --git a/libbuild2/build/script/parser.hxx b/libbuild2/build/script/parser.hxx index a02e34a..932cbad 100644 --- a/libbuild2/build/script/parser.hxx +++ b/libbuild2/build/script/parser.hxx @@ -327,7 +327,8 @@ namespace build2 // recipe should be provided. // // - optional depdb_clear_; // depdb-clear location. + optional depdb_clear_; // depdb-clear location. + bool depdb_value_ = false; // depdb-{string,hash} optional> depdb_dyndep_; // depdb-dyndep location/position. bool depdb_dyndep_byproduct_ = false; // --byproduct @@ -344,6 +345,12 @@ namespace build2 // optional> impure_func_; + // Similar to the impure function above but for a computed (e.g., + // target-qualified) variable expansion. In this case we don't have a + // name (it's computed). + // + optional computed_var_; + // True during pre-parsing when the pre-parse mode is temporarily // suspended to perform expansion. // diff --git a/libbuild2/build/script/script.hxx b/libbuild2/build/script/script.hxx index 0619253..d0ab139 100644 --- a/libbuild2/build/script/script.hxx +++ b/libbuild2/build/script/script.hxx @@ -75,9 +75,10 @@ namespace build2 // script parser for details). // bool depdb_clear; + bool depdb_value; // String or hash. optional depdb_dyndep; // Pos of first dyndep. bool depdb_dyndep_byproduct = false; // dyndep --byproduct - lines_type depdb_preamble; + lines_type depdb_preamble; // Note include vars. bool depdb_preamble_temp_dir = false; // True if refs $~. location start_loc; diff --git a/libbuild2/parser.hxx b/libbuild2/parser.hxx index c59b90e..5c9d16a 100644 --- a/libbuild2/parser.hxx +++ b/libbuild2/parser.hxx @@ -562,7 +562,7 @@ namespace build2 // Customization hooks. // protected: - // If qual is not empty, then firt element's pair member indicates the + // If qual is not empty, then first element's pair member indicates the // kind of qualification: // // '\0' -- target -- cgit v1.1