aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-02-26 15:40:29 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-02-26 15:40:29 +0200
commite1d2e3b63934c1e193429f1d6c4e04abc0e85d56 (patch)
treeff542da6cc5d7d1b8202b5ce9cd3573211024b94
parentcd9a4ea692ba87aa03a80489bf03736e713722c7 (diff)
Support for scope parents, initial variable support
-rw-r--r--build/algorithm.cxx2
-rw-r--r--build/context3
-rw-r--r--build/context.cxx2
-rw-r--r--build/prefix-map4
-rw-r--r--build/prefix-map.txx5
-rw-r--r--build/scope31
-rw-r--r--build/scope.cxx66
-rw-r--r--build/variable19
-rw-r--r--tests/build/prefix-map/driver.cxx42
9 files changed, 134 insertions, 40 deletions
diff --git a/build/algorithm.cxx b/build/algorithm.cxx
index d418cda..16bc1bc 100644
--- a/build/algorithm.cxx
+++ b/build/algorithm.cxx
@@ -47,7 +47,7 @@ namespace build
const auto& rules (i->second); // Hint map.
string hint; // @@ TODO
- auto rs (rules.find (hint));
+ auto rs (rules.find_prefix (hint));
for (auto i (rs.first); i != rs.second; ++i)
{
diff --git a/build/context b/build/context
index 4f5b029..c177603 100644
--- a/build/context
+++ b/build/context
@@ -21,9 +21,6 @@ namespace build
extern path src_base;
extern path out_base;
- class scope;
- extern scope* root_scope;
-
// Return the src/out directory corresponding to the given out/src. The
// passed directory should be a sub-directory of out/src_root.
//
diff --git a/build/context.cxx b/build/context.cxx
index a298d41..79753ec 100644
--- a/build/context.cxx
+++ b/build/context.cxx
@@ -20,8 +20,6 @@ namespace build
path src_base;
path out_base;
- scope* root_scope;
-
path
src_out (const path& o)
{
diff --git a/build/prefix-map b/build/prefix-map
index 1b00337..d98c842 100644
--- a/build/prefix-map
+++ b/build/prefix-map
@@ -108,10 +108,10 @@ namespace build
: map_type (std::move (init), compare_type (delimiter)) {}
std::pair<iterator, iterator>
- find (const key_type&);
+ find_prefix (const key_type&);
std::pair<const_iterator, const_iterator>
- find (const key_type&) const;
+ find_prefix (const key_type&) const;
};
template <typename M, typename prefix_map_common<M>::char_type D = 0>
diff --git a/build/prefix-map.txx b/build/prefix-map.txx
index 0da911d..a8bf028 100644
--- a/build/prefix-map.txx
+++ b/build/prefix-map.txx
@@ -6,7 +6,7 @@ namespace build
{
template <typename M>
auto prefix_map_common<M>::
- find (const key_type& k) -> std::pair<iterator, iterator>
+ find_prefix (const key_type& k) -> std::pair<iterator, iterator>
{
std::pair<iterator, iterator> r;
r.first = this->lower_bound (k);
@@ -24,7 +24,8 @@ namespace build
template <typename M>
auto prefix_map_common<M>::
- find (const key_type& k) const -> std::pair<const_iterator, const_iterator>
+ find_prefix (const key_type& k) const ->
+ std::pair<const_iterator, const_iterator>
{
std::pair<const_iterator, const_iterator> r;
r.first = this->lower_bound (k);
diff --git a/build/scope b/build/scope
index 58f7933..6d96b0a 100644
--- a/build/scope
+++ b/build/scope
@@ -7,6 +7,7 @@
#include <build/path>
#include <build/path-map>
+#include <build/variable>
#include <build/prerequisite>
namespace build
@@ -19,6 +20,9 @@ namespace build
const path_type&
path () const {return i_->first;} // Absolute and normalized.
+ scope&
+ parent () const {return *parent_;}
+
private:
friend class scope_map;
@@ -27,32 +31,41 @@ namespace build
scope () = default;
void
- init (const iterator& i) {i_ = i;}
+ init (const iterator& i, scope* p) {i_ = i; parent_ = p;}
+
+ void
+ parent (scope& p) {parent_ = &p;}
public:
+ variable_map variables;
prerequisite_set prerequisites;
private:
iterator i_;
+ scope* parent_;
};
class scope_map: path_map<scope>
{
public:
+ // Note that we assume the first insertion into the map is that
+ // of the root scope.
+ //
+
scope&
- operator[] (const path& k)
- {
- auto i (emplace (k, scope ()));
- auto& r (i.first->second);
+ operator[] (const path&);
- if (i.second)
- r.init (i.first);
+ // Find the most qualified scope that encompasses this path.
+ //
+ scope&
+ find (const path&);
- return r;
- }
+ private:
+ typedef path_map<scope> base;
};
extern scope_map scopes;
+ extern scope* root_scope;
}
#endif // BUILD_SCOPE
diff --git a/build/scope.cxx b/build/scope.cxx
index 0f99b0e..7165663 100644
--- a/build/scope.cxx
+++ b/build/scope.cxx
@@ -9,4 +9,70 @@ using namespace std;
namespace build
{
scope_map scopes;
+ scope* root_scope;
+
+ scope& scope_map::
+ operator[] (const path& k)
+ {
+ auto er (emplace (k, scope ()));
+ scope& s (er.first->second);
+
+ if (er.second)
+ {
+ scope* p (nullptr);
+
+ // Update scopes of which we are a new parent.
+ //
+ for (auto r (find_prefix (k)); r.first != r.second; ++r.first)
+ {
+ scope& c (r.first->second);
+
+ // The first scope of which we are a parent is the least
+ // (shortest) one which means there is no other scope
+ // between it and our parent.
+ //
+ if (p == nullptr)
+ p = &c;
+ else if (p != &c) // A scope with an intermediate parent.
+ continue;
+
+ c.parent (s);
+ }
+
+ // We couldn't get the parent from one of its old children
+ // so we have to find it ourselves (unless this is is the
+ // root scope).
+ //
+ if (p == nullptr && size () != 1)
+ p = &find (k);
+
+ s.init (er.first, p);
+ }
+
+ return s;
+ }
+
+ // Find the most qualified scope that encompasses this path.
+ //
+ scope& scope_map::
+ find (const path& k)
+ {
+ // Normally we would have a scope for the full path so try
+ // that before making any copies.
+ //
+ auto i (base::find (k));
+
+ if (i != end ())
+ return i->second;
+
+ for (path d (k.directory ());; d = d.directory ())
+ {
+ auto i (base::find (k));
+
+ if (i != end ())
+ return i->second;
+
+ assert (d.empty ()); // We should have the root scope.
+ }
+ }
}
diff --git a/build/variable b/build/variable
new file mode 100644
index 0000000..caceb2b
--- /dev/null
+++ b/build/variable
@@ -0,0 +1,19 @@
+// file : build/variable -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BUILD_VARIABLE
+#define BUILD_VARIABLE
+
+#include <build/prefix-map>
+
+namespace build
+{
+ // @@ TODO:
+ // - pool names?
+ //
+
+ typedef prefix_map<std::string, std::string, '.'> variable_map;
+}
+
+#endif // BUILD_VARIABLE
diff --git a/tests/build/prefix-map/driver.cxx b/tests/build/prefix-map/driver.cxx
index 77edb6c..d365df2 100644
--- a/tests/build/prefix-map/driver.cxx
+++ b/tests/build/prefix-map/driver.cxx
@@ -20,12 +20,12 @@ main ()
const pm m ('.');
{
- auto r (m.find (""));
+ auto r (m.find_prefix (""));
assert (r.first == r.second);
}
{
- auto r (m.find ("foo"));
+ auto r (m.find_prefix ("foo"));
assert (r.first == r.second);
}
}
@@ -34,33 +34,33 @@ main ()
pm m {{{"foo", 1}}, '.'};
{
- auto r (m.find (""));
+ auto r (m.find_prefix (""));
assert (r.first != r.second && r.first->second == 1 &&
++r.first == r.second);
}
{
- auto r (m.find ("fo"));
+ auto r (m.find_prefix ("fo"));
assert (r.first == r.second);
}
{
- auto r (m.find ("fox"));
+ auto r (m.find_prefix ("fox"));
assert (r.first == r.second);
}
{
- auto r (m.find ("fooo"));
+ auto r (m.find_prefix ("fooo"));
assert (r.first == r.second);
}
{
- auto r (m.find ("foo.bar"));
+ auto r (m.find_prefix ("foo.bar"));
assert (r.first == r.second);
}
{
- auto r (m.find ("foo"));
+ auto r (m.find_prefix ("foo"));
assert (r.first != r.second && r.first->second == 1 &&
++r.first == r.second);
}
@@ -70,40 +70,40 @@ main ()
pm m {{{"foo", 1}, {"bar", 2}}, '.'};
{
- auto r (m.find (""));
+ auto r (m.find_prefix (""));
assert (r.first != r.second && r.first->second == 2 &&
++r.first != r.second && r.first->second == 1 &&
++r.first == r.second);
}
{
- auto r (m.find ("fo"));
+ auto r (m.find_prefix ("fo"));
assert (r.first == r.second);
}
{
- auto r (m.find ("fox"));
+ auto r (m.find_prefix ("fox"));
assert (r.first == r.second);
}
{
- auto r (m.find ("fooo"));
+ auto r (m.find_prefix ("fooo"));
assert (r.first == r.second);
}
{
- auto r (m.find ("foo.bar"));
+ auto r (m.find_prefix ("foo.bar"));
assert (r.first == r.second);
}
{
- auto r (m.find ("foo"));
+ auto r (m.find_prefix ("foo"));
assert (r.first != r.second && r.first->second == 1 &&
++r.first == r.second);
}
{
- auto r (m.find ("bar"));
+ auto r (m.find_prefix ("bar"));
assert (r.first != r.second && r.first->second == 2 &&
++r.first == r.second);
}
@@ -117,34 +117,34 @@ main ()
'.');
{
- auto r (m.find ("fo"));
+ auto r (m.find_prefix ("fo"));
assert (r.first == r.second);
}
{
- auto r (m.find ("fox"));
+ auto r (m.find_prefix ("fox"));
assert (r.first == r.second);
}
{
- auto r (m.find ("fooo"));
+ auto r (m.find_prefix ("fooo"));
assert (r.first == r.second);
}
{
- auto r (m.find ("foo.bar"));
+ auto r (m.find_prefix ("foo.bar"));
assert (r.first != r.second && r.first->second == 4 &&
++r.first == r.second);
}
{
- auto r (m.find ("foo.fox"));
+ auto r (m.find_prefix ("foo.fox"));
assert (r.first != r.second && r.first->second == 5 &&
++r.first == r.second);
}
{
- auto r (m.find ("foo"));
+ auto r (m.find_prefix ("foo"));
assert (r.first != r.second && r.first->second == 2 &&
++r.first != r.second && r.first->second == 4 &&
++r.first != r.second && r.first->second == 5 &&