From e19095ef128f53644bc7650094d8924633c79efa Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 23 Nov 2016 16:53:31 +0200 Subject: Implement value type propagation on expansion Currently, we only propagate types of sole, unquoted expansions (variable, function call, or eval context), similar to NULL. To untypify the value, simply quote it. --- build2/variable.cxx | 73 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 5 deletions(-) (limited to 'build2/variable.cxx') diff --git a/build2/variable.cxx b/build2/variable.cxx index 39fdb5d..5a52557 100644 --- a/build2/variable.cxx +++ b/build2/variable.cxx @@ -336,6 +336,41 @@ namespace build2 } } + void + untypify (value& v) + { + if (v.type == nullptr) + return; + + if (v.null) + { + v.type = nullptr; + return; + } + + names ns; + names_view nv (v.type->reverse (v, ns)); + + if (nv.empty () || nv.data () == ns.data ()) + { + // If the data is in storage, then we are all set. + // + ns.resize (nv.size ()); // Just to be sure. + } + else + { + // If the data is somewhere in the value itself, then steal it. + // + auto b (const_cast (nv.data ())); + ns.assign (make_move_iterator (b), + make_move_iterator (b + nv.size ())); + } + + v = nullptr; // Free old data. + v.type = nullptr; // Change type. + v.assign (move (ns), nullptr); // Assign new data. + } + // Throw invalid_argument for an invalid simple value. // [[noreturn]] static void @@ -736,6 +771,34 @@ namespace build2 } void + process_path_assign (value& v, names&& ns, const variable* var) + { + using traits = value_traits; + + size_t n (ns.size ()); + + if (n <= 2) + { + try + { + traits::assign ( + v, + (n == 0 + ? process_path () + : traits::convert (move (ns[0]), n == 2 ? &ns[1] : nullptr))); + return; + } + catch (const invalid_argument&) {} // Fall through. + } + + diag_record dr (fail); + dr << "invalid process_path value '" << ns << "'"; + + if (var != nullptr) + dr << " in variable " << var->name; + } + + void process_path_copy_ctor (value& l, const value& r, bool m) { const auto& rhs (r.as ()); @@ -798,15 +861,15 @@ namespace build2 { type_name, sizeof (process_path), - nullptr, // No base. + nullptr, // No base. &default_dtor, &process_path_copy_ctor, &process_path_copy_assign, - &simple_assign, // Allow empty values. - nullptr, // Append not supported. - nullptr, // Prepend not supported. + &process_path_assign, + nullptr, // Append not supported. + nullptr, // Prepend not supported. &process_path_reverse, - nullptr, // No cast (cast data_ directly). + nullptr, // No cast (cast data_ directly). &simple_compare, &default_empty }; -- cgit v1.1