aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-04-09 11:38:42 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-04-09 11:38:42 +0200
commit5f7c3f923de106f9d204a8f3500274731ae84fd9 (patch)
treea4993277c75e61b73bb6f984e2ad0c329a514f9a
parent7a7b8ba432977282a90567c77822a72645d2a5c8 (diff)
Tweak override logic WRT location of overridden value
-rw-r--r--build2/scope18
-rw-r--r--build2/scope.cxx66
-rw-r--r--build2/variable10
-rw-r--r--build2/variable.cxx3
4 files changed, 62 insertions, 35 deletions
diff --git a/build2/scope b/build2/scope
index 566466a..09914a9 100644
--- a/build2/scope
+++ b/build2/scope
@@ -92,7 +92,7 @@ namespace build2
lookup
operator[] (const variable& var) const
{
- return find (var, nullptr, nullptr);
+ return find (var).first;
}
lookup
@@ -106,7 +106,7 @@ namespace build2
lookup
find (const variable& var, const target_key& tk) const
{
- return find (var, tk.type, tk.name);
+ return find (var, tk.type, tk.name).first;
}
lookup
@@ -118,7 +118,7 @@ namespace build2
lookup
find (const variable& var, const target_type& tt, const string& tn) const
{
- return find (var, &tt, &tn);
+ return find (var, &tt, &tn).first;
}
lookup
@@ -127,13 +127,13 @@ namespace build2
return find (var_pool.find (var), tt, tn);
}
- lookup
- find (const variable& var, const target_type* tt, const string* tn) const
+ pair<lookup, size_t>
+ find (const variable& var,
+ const target_type* tt = nullptr,
+ const string* tn = nullptr) const
{
auto p (find_original (var, tt, tn));
- return var.override == nullptr
- ? p.first
- : find_override (var, move (p), false).first;
+ return var.override == nullptr ? p : find_override (var, move (p));
}
// Implementation details (used by scope target lookup).
@@ -147,7 +147,7 @@ namespace build2
pair<lookup, size_t>
find_override (const variable&,
pair<lookup, size_t>&& original,
- bool target) const;
+ bool target = false) const;
// Return a value suitable for assignment (or append if you only
// want to append to the value from this scope). If the variable
diff --git a/build2/scope.cxx b/build2/scope.cxx
index 3fd3c95..75652a2 100644
--- a/build2/scope.cxx
+++ b/build2/scope.cxx
@@ -66,6 +66,11 @@ namespace build2
// be a few of them. As a result, here we concentrate on keeping the logic
// as straightforward as possible without trying to optimize anything.
//
+ // Note also that we rely (e.g., in the config module) on the fact that if
+ // no overrides apply, then we return the original value and not its copy
+ // in the cache (this can be used to detect if the value was overriden).
+ //
+ //
assert (var.override != nullptr);
lookup& origl (original.first);
@@ -73,9 +78,9 @@ namespace build2
// The first step is to find out where our cache will reside. After some
// meditation it becomes clear it should be next to the innermost (scope-
- // wise) value (override or original) that contributes to the end result.
+ // wise) value (override or original) that could contribute to the end
+ // result.
//
- size_t depth (0);
const variable_map* vars (nullptr);
// Root scope of a project from which our initial value comes. See below.
@@ -92,12 +97,9 @@ namespace build2
if (targetspec)
{
- depth = origd;
vars = origl.vars;
proj = root_scope ();
}
- else
- depth = 2; // For implied target-specific lookup.
}
const scope* s;
@@ -172,16 +174,11 @@ namespace build2
//
if (vars == nullptr && origl.defined () && belongs (origl))
{
- depth = origd;
vars = origl.vars;
- proj = s->root_scope ();
+ proj = s->root_scope (); // This is so we skip non-recursive overrides
+ // that would not apply. We reset it later.
}
- if (vars == nullptr)
- // Extra 2 for implied target type/pattern-specific lookup.
- //
- depth += target ? 3 : 1;
-
for (const variable* o (var.override.get ());
o != nullptr;
o = o->override.get ())
@@ -218,17 +215,20 @@ namespace build2
// versioning (incremented on every update) to detect stem value changes.
// We also need to watch out for the change of the stem itself in addition
// to its value (think of a new variable set since last lookup which is
- // now a new stem).
+ // now a new stem). Thus stem_vars in variable_override_value.
//
// @@ MT
//
- variable_override_value& cache (variable_override_cache[vars]);
+ variable_override_value& cache (
+ variable_override_cache[make_pair (vars, &var)]);
// Now find our "stem", that is the value to which we will be appending
// suffixes and prepending prefixes. This is either the original or the
// __override provided it applies. We may also not have either.
//
lookup stem (targetspec ? origl : lookup ());
+ size_t depth (targetspec ? origd : 0);
+ size_t ovrd (target ? 2 : 0); // For implied target-specific lookup.
for (s = this; s != nullptr; s = s->parent_scope ())
{
@@ -239,10 +239,13 @@ namespace build2
if (origl.defined () && belongs (origl))
{
stem = origl;
+ depth = origd;
proj = s->root_scope ();
// Keep searching.
}
+ ++ovrd;
+
// Then look for an __override that applies.
//
for (const variable* o (var.override.get ());
@@ -259,6 +262,7 @@ namespace build2
if (l.defined ())
{
+ depth = ovrd;
stem = move (l);
proj = s->root_scope ();
done = true;
@@ -301,8 +305,13 @@ namespace build2
// Now apply override prefixes and suffixes.
//
+ ovrd = target ? 2 : 0;
+ const variable_map* ovrv (cache.stem_vars);
+
for (s = this; s != nullptr; s = s->parent_scope ())
{
+ ++ovrd;
+
for (const variable* o (var.override.get ());
o != nullptr;
o = o->override.get ())
@@ -331,18 +340,31 @@ namespace build2
cache.value.append (names (cast<names> (l)), var);
}
- // If we had no stem, use the scope of the first override that applies
- // as the project.
- //
- if (proj == nullptr && l.defined ())
- proj = s;
+ if (l.defined ())
+ {
+ // If we had no stem, use the scope of the first override that
+ // applies as the project. For vars/depth we need to pick the
+ // innermost.
+ //
+ if (proj == nullptr)
+ {
+ proj = s->root_scope ();
+ depth = ovrd;
+ ovrv = &s->vars;
+ }
+ else if (ovrd < depth)
+ {
+ depth = ovrd;
+ ovrv = &s->vars;
+ }
+ }
}
}
- // Use the location of the cache (innermost value that contributes) as
- // the location of the result.
+ // Use the location of the innermost value that contributed as the
+ // location of the result.
//
- return make_pair (lookup (&cache.value, vars), depth);
+ return make_pair (lookup (&cache.value, ovrv), depth);
}
value& scope::
diff --git a/build2/variable b/build2/variable
index 5a33037..77e9db2 100644
--- a/build2/variable
+++ b/build2/variable
@@ -277,11 +277,15 @@ namespace build2
belongs (const T& x) const {return vars == &x.vars;}
lookup (): value (nullptr), vars (nullptr) {}
- lookup (const value_type* v, const variable_map* vs)
- : value (v), vars (v != nullptr ? vs : nullptr) {}
template <typename T>
lookup (const value_type& v, const T& x): lookup (&v, &x.vars) {}
+
+ lookup (const value_type& v, const variable_map& vs)
+ : value (&v), vars (&vs) {}
+
+ lookup (const value_type* v, const variable_map* vs)
+ : value (v), vars (v != nullptr ? vs : nullptr) {}
};
// Two lookups are equal if they point to the same variable.
@@ -735,7 +739,7 @@ namespace build2
const variable_map* stem_vars = nullptr; // NULL means there is no stem.
};
- extern std::map<const variable_map*,
+ extern std::map<pair<const variable_map*, const variable*>,
variable_override_value> variable_override_cache;
}
diff --git a/build2/variable.cxx b/build2/variable.cxx
index 61f5975..4a2ffa9 100644
--- a/build2/variable.cxx
+++ b/build2/variable.cxx
@@ -742,5 +742,6 @@ namespace build2
// variable_override
//
- map<const variable_map*, variable_override_value> variable_override_cache;
+ map<pair<const variable_map*, const variable*>, variable_override_value>
+ variable_override_cache;
}