aboutsummaryrefslogtreecommitdiff
path: root/build/algorithm.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'build/algorithm.cxx')
-rw-r--r--build/algorithm.cxx197
1 files changed, 103 insertions, 94 deletions
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";
}
}
}