diff options
-rw-r--r-- | build/algorithm.cxx | 4 | ||||
-rw-r--r-- | build/dump.cxx | 97 | ||||
-rw-r--r-- | build/scope | 4 | ||||
-rw-r--r-- | build/target | 5 | ||||
-rw-r--r-- | build/target-type | 6 | ||||
-rw-r--r-- | build/target.cxx | 45 | ||||
-rw-r--r-- | build/variable | 10 |
7 files changed, 145 insertions, 26 deletions
diff --git a/build/algorithm.cxx b/build/algorithm.cxx index 615d4b7..bf10b84 100644 --- a/build/algorithm.cxx +++ b/build/algorithm.cxx @@ -85,9 +85,7 @@ namespace build size_t oi (o - 1); // Operation index in rule_map. scope& bs (t.base_scope ()); - for (auto tt (&t.type ()); - tt != nullptr && !t.recipe (ra); - tt = tt->base) + for (auto tt (&t.type ()); tt != nullptr; tt = tt->base) { // Search scopes outwards, stopping at the project root. // diff --git a/build/dump.cxx b/build/dump.cxx index 6b6debe..e426f0b 100644 --- a/build/dump.cxx +++ b/build/dump.cxx @@ -18,32 +18,76 @@ using namespace std; namespace build { - static bool - dump_variables (ostream& os, string& ind, const variable_map& vars) + static void + dump_variable (ostream& os, const variable& var, const value_ptr& val) { - bool r (false); + os << var.name << " = "; - for (const auto& e: vars) + if (val == nullptr) + os << "[null]"; + else { - const variable& var (e.first); - const value_ptr& val (e.second); + //@@ TODO: assuming it is a list. + // + os << dynamic_cast<list_value&> (*val); + } + } + static void + dump_variables (ostream& os, string& ind, const variable_map& vars) + { + for (const auto& e: vars) + { os << endl - << ind << var.name << " = "; + << ind; - if (val == nullptr) - os << "[null]"; - else + dump_variable (os, e.first, e.second); + } + } + + static void + dump_variables (ostream& os, string& ind, const variable_type_map& vtm) + { + for (const auto& vt: vtm) + { + const target_type& t (vt.first); + const variable_pattern_map& vpm (vt.second); + + for (const auto& vp: vpm) { - //@@ TODO: assuming it is a list. - // - os << dynamic_cast<list_value&> (*val); - } + const string p (vp.first); + const variable_map& vars (vp.second); - r = true; - } + os << endl + << ind; + + if (t.id != target::static_type.id) + os << t.name << '{'; + + os << p; + + if (t.id != target::static_type.id) + os << '}'; + + os << ':'; - return r; + if (vars.size () == 1) + { + os << ' '; + dump_variable (os, vars.begin ()->first, vars.begin ()->second); + } + else + { + os << endl + << ind << '{'; + ind += " "; + dump_variables (os, ind, vars); + ind.resize (ind.size () - 2); + os << endl + << ind << '}'; + } + } + } } static void @@ -120,9 +164,24 @@ namespace build bool vb (false), sb (false); // Variable/scope block. - // Variables. + // Target type/pattern-sepcific variables. + // + if (!p.target_vars.empty ()) + { + dump_variables (os, ind, p.target_vars); + vb = true; + } + + // Scope variables. // - vb = dump_variables (os, ind, p.vars); + if (!p.vars.empty ()) + { + if (vb) + os << endl; + + dump_variables (os, ind, p.vars); + vb = true; + } // Nested scopes of which we are a parent. // diff --git a/build/scope b/build/scope index eb2dafc..9fb8061 100644 --- a/build/scope +++ b/build/scope @@ -104,6 +104,10 @@ namespace build return append (variable_pool.find (name)); } + // Target type/pattern-specific variables. + // + variable_type_map target_vars; + // Prerequisite cache. // public: diff --git a/build/target b/build/target index 6ee65f4..f777268 100644 --- a/build/target +++ b/build/target @@ -259,8 +259,9 @@ namespace build variable_map vars; // Lookup, including in groups to which this target belongs and - // then in outer scopes. If you only want to lookup in this target, - // do it on the the variables map directly. + // then in outer scopes (including target type/pattern-specific + // variables). If you only want to lookup in this target, do it + // on the the variable map directly. // value_proxy operator[] (const variable&) const; diff --git a/build/target-type b/build/target-type index d5e7971..154714c 100644 --- a/build/target-type +++ b/build/target-type @@ -42,6 +42,12 @@ namespace build is_a () const {return is_a (typeid (T));} }; + inline bool + operator< (const target_type& x, const target_type& y) + { + return x.id < y.id; + } + inline std::ostream& operator<< (std::ostream& os, const target_type& tt) { diff --git a/build/target.cxx b/build/target.cxx index df7e2aa..cdcc6b0 100644 --- a/build/target.cxx +++ b/build/target.cxx @@ -85,7 +85,50 @@ namespace build if (group != nullptr) return (*group)[var]; - return base_scope ()[var]; + // Cannot simply delegate to scope's operator[] since we also + // need to check target type/pattern-specific variables. + // + const target_type& btt (type ()); + + for (const scope* s (&base_scope ()); s != nullptr; s = s->parent_scope ()) + { + if (!s->target_vars.empty ()) + { + // Search across target type hierarchy. + // + for (auto tt (&btt); tt != nullptr; tt = tt->base) + { + auto i (s->target_vars.find (*tt)); + + if (i == s->target_vars.end ()) + continue; + + //@@ TODO: match pattern. For now, we only handle '*'. + + auto j (i->second.find ("*")); + + if (j == i->second.end ()) + continue; + + auto k (j->second.find (var)); + + if (k != j->second.end ()) + { + // Note that we use the scope's vars, not from target_vars. + // We use it to identify whether the variable belongs to a + // specific scope/target. + // + return value_proxy (&const_cast<value_ptr&> (k->second), &s->vars); + } + } + } + + auto i (s->vars.find (var)); + if (i != s->vars.end ()) + return value_proxy (&const_cast<value_ptr&> (i->second), &s->vars); + } + + return value_proxy (nullptr, nullptr); } value_proxy target:: diff --git a/build/variable b/build/variable index 809e7d2..998a853 100644 --- a/build/variable +++ b/build/variable @@ -5,18 +5,20 @@ #ifndef BUILD_VARIABLE #define BUILD_VARIABLE +#include <map> #include <string> #include <memory> // unique_ptr #include <cstddef> // nullptr_t #include <utility> // move(), pair, make_pair() #include <cassert> -#include <functional> // hash +#include <functional> // hash, reference_wrapper #include <typeindex> #include <unordered_set> #include <butl/prefix-map> #include <build/types> +#include <build/target-type> namespace build { @@ -340,6 +342,12 @@ namespace build return find_prefix (variable_pool.find (ns)); } }; + + // Target type/pattern-specific variables. + // + using variable_pattern_map = std::map<std::string, variable_map>; + using variable_type_map = std::map<std::reference_wrapper<const target_type>, + variable_pattern_map>; } #include <build/variable.ixx> |