[pure-lang-svn] SF.net SVN: pure-lang:[453] pure/trunk
Status: Beta
Brought to you by:
agraef
|
From: <ag...@us...> - 2008-08-08 08:53:24
|
Revision: 453
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=453&view=rev
Author: agraef
Date: 2008-08-08 08:53:33 +0000 (Fri, 08 Aug 2008)
Log Message:
-----------
Rework FMap structure so that it can accommodate a forest of local environments.
Modified Paths:
--------------
pure/trunk/interpreter.cc
pure/trunk/interpreter.hh
Modified: pure/trunk/interpreter.cc
===================================================================
--- pure/trunk/interpreter.cc 2008-08-07 08:07:20 UTC (rev 452)
+++ pure/trunk/interpreter.cc 2008-08-08 08:53:33 UTC (rev 453)
@@ -1932,8 +1932,11 @@
FMap& FMap::operator= (const FMap& f)
{
clear(); m.resize(f.m.size());
- for (size_t i = 0, n = f.m.size(); i < n; i++) m[i] = new EnvMap(*f.m[i]);
- idx = f.idx; return *this;
+ for (size_t i = 0, n = f.m.size(); i < n; i++)
+ m[i] = new EnvMap(*f.m[i]);
+ root = f.root; pred = f.pred; succ = f.succ;
+ idx = f.idx; lastidx = f.lastidx;
+ return *this;
}
void FMap::clear()
@@ -1948,9 +1951,69 @@
for (set<Env*>::iterator it = e.begin(), end = e.end();
it != end; it++)
delete *it;
- m.clear(); idx = 0;
+ m.clear(); root.clear(); pred.clear(); succ.clear();
+ idx = 0; lastidx = -1;
}
+void FMap::next()
+{
+ assert(pred[idx] < 0);
+ if (succ[idx] >= 0)
+ idx = succ[idx];
+ else {
+ // create a new root
+ size_t n = root.size(), k = m.size();
+ root.resize(n+1);
+ m.resize(k+1); pred.resize(k+1); succ.resize(k+1);
+ root[n] = succ[idx] = k;
+ pred[k] = succ[k] = -1;
+ m[k] = new EnvMap;
+ idx = k;
+ }
+ lastidx = -1;
+}
+
+void FMap::select(size_t n)
+{
+ if (root.size() > 1) {
+ assert(n < root.size());
+ idx = root[n];
+ } else
+ idx = 0;
+ lastidx = -1;
+}
+
+void FMap::push()
+{
+ if (lastidx >= 0) {
+ assert(pred[lastidx] == idx);
+ if (succ[lastidx] >= 0)
+ idx = succ[lastidx];
+ else {
+ // create a new child, link from the previous one
+ size_t k = m.size();
+ m.resize(k+1); pred.resize(k+1); succ.resize(k+1);
+ pred[k] = idx; succ[k] = -1;
+ m[k] = new EnvMap(*m[idx]);
+ succ[lastidx] = k;
+ idx = k;
+ }
+ } else if (++idx >= (int32_t)m.size()) {
+ // the first child always immediately follows its parent
+ assert(idx == m.size());
+ m.resize(idx+1); pred.resize(idx+1); succ.resize(idx+1);
+ pred[idx] = idx-1; succ[idx] = -1;
+ m[idx] = new EnvMap(*m[idx-1]);
+ }
+ lastidx = -1;
+}
+
+void FMap::pop()
+{
+ assert(pred[idx] >= 0);
+ lastidx = idx; idx = pred[idx];
+}
+
Env& Env::operator= (const Env& e)
{
if (f) {
Modified: pure/trunk/interpreter.hh
===================================================================
--- pure/trunk/interpreter.hh 2008-08-07 08:07:20 UTC (rev 452)
+++ pure/trunk/interpreter.hh 2008-08-08 08:53:33 UTC (rev 453)
@@ -88,22 +88,49 @@
typedef map<int32_t,Env*> EnvMap;
typedef pair<int32_t,uint8_t> xmap_key;
+/* Manage local function environments. The FMap structure is organized as a
+ forest with one root per rule and one child per 'with' clause. Each node of
+ the forest holds a map mapping function symbols to the corresponding
+ environments. Initially, there is just one root holding an empty map. New
+ roots can be added with 'next', new children with 'push'; 'pop' backs out
+ to the parent level.
+
+ Child nodes are initialized to a copy of its parent map, to which you can
+ then add any local bindings. After the structure has been built, you can
+ use 'first' to reposition the "cursor" so that it points to the first root
+ and then traverse the forest using the same sequence of calls to 'next',
+ 'push' and 'pop'. The 'select' method can be used to position the cursor at
+ the given root. The 'act' method returns the current map.
+
+ Implementation: The forest is encoded as a collection of vectors: 'm' holds
+ the map for each node, 'root' the node number of each root, 'pred' the
+ parent link for each node, and 'succ' the link to the next sibling of each
+ node. A 'pred' value of -1 denotes a root node, in which case 'succ' points
+ to the next root (or contains -1 to indicate the last root). The 'idx'
+ member points to the current node, 'lastidx' to the most recently visited
+ child after a 'pop' operation (-1 otherwise). */
+
struct FMap {
- // manage local function environments
+ // map of each node
vector<EnvMap*> m;
- // current map index
- size_t idx;
+ // vectors encoding the forest structure (see explanation above)
+ vector<int32_t> root, pred, succ;
+ // index of current node and most previously visited child
+ int32_t idx, lastidx;
// constructor (create one empty map by default)
- FMap() : m(1), idx(0) { m[0] = new EnvMap; }
+ FMap() : m(1), root(1, 0), pred(1, -1), succ(1, -1), idx(0), lastidx(-1)
+ { m[0] = new EnvMap; }
// assignment
FMap& operator= (const FMap& f);
- // clear local environments
+ // clear
void clear();
- // set index to first, next and given map
- void first() { idx = 0; }
- void next()
- { if (++idx >= m.size()) { m.resize(idx+1); m[idx] = new EnvMap; } }
- void select(size_t n) { if (m.size() > 1) idx = n; }
+ // set index to first, next and given root node
+ void first() { idx = 0; lastidx = -1; }
+ void next();
+ void select(size_t n);
+ // set index to the parent or next child of the current node
+ void push();
+ void pop();
// access the current map
EnvMap& act() { return *m[idx]; }
};
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|