diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2016-11-23 16:53:31 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2016-11-23 16:53:31 +0200 |
commit | e19095ef128f53644bc7650094d8924633c79efa (patch) | |
tree | d039eb841341af2d7b3f544b95644ad1afcb846c /build2/variable.cxx | |
parent | 793f078ec31dc61921b382f14412ed3e25cc51d8 (diff) |
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.
Diffstat (limited to 'build2/variable.cxx')
-rw-r--r-- | build2/variable.cxx | 73 |
1 files changed, 68 insertions, 5 deletions
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<name*> (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<process_path>; + + 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<process_path> ()); @@ -798,15 +861,15 @@ namespace build2 { type_name, sizeof (process_path), - nullptr, // No base. + nullptr, // No base. &default_dtor<process_path>, &process_path_copy_ctor, &process_path_copy_assign, - &simple_assign<process_path, true>, // 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<process_path>, &default_empty<process_path> }; |