From fd689eb883655dcb29e505b041cd02fac01f0bac Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 27 Aug 2015 15:11:40 +0200 Subject: Dist module/meta-operation initial implementation --- build/algorithm.cxx | 197 +++++++++++++++++++++++++++------------------------- 1 file changed, 103 insertions(+), 94 deletions(-) (limited to 'build/algorithm.cxx') diff --git a/build/algorithm.cxx b/build/algorithm.cxx index e09d125..f462bb8 100644 --- a/build/algorithm.cxx +++ b/build/algorithm.cxx @@ -83,7 +83,6 @@ namespace build // action ra (a.meta_operation (), io, o != oo ? 0 : oo); - size_t oi (o - 1); // Operation index in rule_map. scope& bs (t.base_scope ()); for (auto tt (&t.type ()); tt != nullptr; tt = tt->base) @@ -94,129 +93,139 @@ namespace build s != nullptr; s = s->root () ? global_scope : s->parent_scope ()) { - const rule_map& om (s->rules); + const operation_rule_map* om (s->rules[a.meta_operation ()]); - if (om.size () <= oi) - continue; // No entry for this operation id. + if (om == nullptr) + continue; // No entry for this meta-operation id. - const target_type_rule_map& ttm (om[oi]); + // First try the map for the actual operation. If that + // doesn't yeld anything, try the wildcard map. + // + for (size_t oi (o), oip (o); oip != 0; oip = oi, oi = 0) + { + const target_type_rule_map* ttm ((*om)[oi]); - if (ttm.empty ()) - continue; // Empty map for this operation id. + if (ttm == nullptr) + continue; // No entry for this operation id. - auto i (ttm.find (tt->id)); + if (ttm->empty ()) + continue; // Empty map for this operation id. - if (i == ttm.end () || i->second.empty ()) - continue; // No rules registered for this target type. + auto i (ttm->find (tt->id)); - const auto& rules (i->second); // Hint map. + if (i == ttm->end () || i->second.empty ()) + continue; // No rules registered for this target type. - // @@ TODO - // - // Different rules can be used for different operations (update - // vs test is a good example). So, at some point, we will probably - // have to support a list of hints or even an operation-hint map - // (e.g., 'hint=cxx test=foo' if cxx supports the test operation - // but we want the foo rule instead). This is also the place where - // the '{build clean}=cxx' construct (which we currently do not - // support) can come handy. - // - // Also, ignore the hint (that is most likely ment for a different - // operation) if this is a unique match. - // - string hint; - auto rs (rules.size () == 1 - ? make_pair (rules.begin (), rules.end ()) - : rules.find_prefix (hint)); + const auto& rules (i->second); // Hint map. - for (auto i (rs.first); i != rs.second; ++i) - { - const string& n (i->first); - const rule& ru (i->second); - - match_result m; - { - auto g ( - make_exception_guard ( - [](action a, target& t, const string& n) - { - info << "while matching rule " << n << " to " - << diag_do (a, t); - }, - ra, t, n)); - - if (!(m = ru.match (ra, t, hint))) - continue; - - if (!m.recipe_action.valid ()) - m.recipe_action = ra; // Default, if not set. - } - - // Do the ambiguity test. + // @@ TODO // - bool ambig (false); - - diag_record dr; + // Different rules can be used for different operations (update + // vs test is a good example). So, at some point, we will probably + // have to support a list of hints or even an operation-hint map + // (e.g., 'hint=cxx test=foo' if cxx supports the test operation + // but we want the foo rule instead). This is also the place where + // the '{build clean}=cxx' construct (which we currently do not + // support) can come handy. + // + // Also, ignore the hint (that is most likely ment for a different + // operation) if this is a unique match. + // + string hint; + auto rs (rules.size () == 1 + ? make_pair (rules.begin (), rules.end ()) + : rules.find_prefix (hint)); - for (++i; i != rs.second; ++i) + for (auto i (rs.first); i != rs.second; ++i) { - const string& n1 (i->first); - const rule& ru1 (i->second); + const string& n (i->first); + const rule& ru (i->second); + match_result m; { auto g ( make_exception_guard ( - [](action a, target& t, const string& n1) + [](action a, target& t, const string& n) { - info << "while matching rule " << n1 << " to " + info << "while matching rule " << n << " to " << diag_do (a, t); }, - ra, t, n1)); + ra, t, n)); - if (!ru1.match (ra, t, hint)) + if (!(m = ru.match (ra, t, hint))) continue; - } - if (!ambig) - { - dr << fail << "multiple rules matching " << diag_doing (ra, t) - << info << "rule " << n << " matches"; - ambig = true; + if (!m.recipe_action.valid ()) + m.recipe_action = ra; // Default, if not set. } - dr << info << "rule " << n1 << " also matches"; - } + // Do the ambiguity test. + // + bool ambig (false); - if (!ambig) - { - ra = m.recipe_action; // Use custom, if set. + diag_record dr; - if (apply) + for (++i; i != rs.second; ++i) { - auto g ( - make_exception_guard ( - [](action a, target& t, const string& n) - { - info << "while applying rule " << n << " to " - << diag_do (a, t); - }, - ra, t, n)); - - // @@ We could also allow the rule to change the recipe - // action in apply(). Could be useful with delegates. - // - t.recipe (ra, ru.apply (ra, t, m)); + const string& n1 (i->first); + const rule& ru1 (i->second); + + { + auto g ( + make_exception_guard ( + [](action a, target& t, const string& n1) + { + info << "while matching rule " << n1 << " to " + << diag_do (a, t); + }, + ra, t, n1)); + + if (!ru1.match (ra, t, hint)) + continue; + } + + if (!ambig) + { + dr << fail << "multiple rules matching " + << diag_doing (ra, t) + << info << "rule " << n << " matches"; + ambig = true; + } + + dr << info << "rule " << n1 << " also matches"; } - else + + if (!ambig) { - r.first = &ru; - r.second = move (m); + ra = m.recipe_action; // Use custom, if set. + + if (apply) + { + auto g ( + make_exception_guard ( + [](action a, target& t, const string& n) + { + info << "while applying rule " << n << " to " + << diag_do (a, t); + }, + ra, t, n)); + + // @@ We could also allow the rule to change the recipe + // action in apply(). Could be useful with delegates. + // + t.recipe (ra, ru.apply (ra, t, m)); + } + else + { + r.first = &ru; + r.second = move (m); + } + + return r; } - - return r; + else + dr << info << "use rule hint to disambiguate this match"; } - else - dr << info << "use rule hint to disambiguate this match"; } } } -- cgit v1.1