local lib = ...
local tree = {}
local let let = lib.class {
__index = {
get = function(self, v)
if self.bind[v] ~= nil then
return self.bind[v]
elseif self.import ~= nil then
for i=#self.import, 1, -1 do
local g = self.import[i]:get(v)
if g then return g end
end
end
if self.parent ~= nil then
return self.parent:get(v)
else return nil end
end;
put = function(self, v, val)
self.bind[v] = val
end;
unify = function(self, v, val)
local x = self:get(v)
if x == nil then self:put(v, val)
return true
elseif x == val then return true
else return false end
end;
newBinds = function(self)
return pairs(self.bind)
end;
binds = function(self)
local k
return function()
k = next(self.bind, k)
if k == nil then
self = self.parent
if not self then return nil end
k = next(self.bind, k)
end
return k, self.bind[k]
end
end;
compile = function(self, into)
-- assemble the entire tree into a single unified list,
-- suitable for returning from a completed query. uses
-- tail recursion for optimal performance
into = into or {}
for k,v in pairs(self.bind) do
into[k]=into[k] or v
end
if self.parent then -- branch node
return self.parent:compile(into)
else -- root node in let tree
return into
end
end;
branch = function(self, ref) return let(self,ref) end;
import = function(i)
if self.import == nil then self.import = {i}
else table.insert(self.import, i) end
end;
};
construct = function(parent, ref)
return {
bind = {};
parent = parent;
import = nil;
ref = ref; -- used to store e.g. a position in a program
}
end;
}
tree.let = let
return tree