1 --------------------------------------------------------------------------------
3 -- Scopes: this library helps keeping track of identifier scopes,
4 -- typically in code walkers.
6 -- * scope:new() returns a new scope instance s
8 -- * s:push() bookmarks the current set of variables, so the it can be
9 -- retrieved next time a s:pop() is performed.
11 -- * s:pop() retrieves the last state saved by s:push(). Calls to
12 -- :push() and :pop() can be nested as deep as one wants.
14 -- * s:add(var_list, val) adds new variable names (stirng) into the
15 -- scope, as keys. val is the (optional) value associated with them:
16 -- it allows to attach arbitrary information to variables, e.g. the
17 -- statement or expression that created them.
19 -- * s:push(var_list, val) is a shortcut for
20 -- s:push(); s:add(var_list, val).
22 -- * s.current is the current scope, a table with variable names as
23 -- keys and their associated value val (or 'true') as value.
25 --------------------------------------------------------------------------------
31 local ret = { current = { } }
32 ret.stack = { ret.current }
33 setmetatable (ret, self)
37 function scope:push(...)
38 table.insert (self.stack, table.shallow_copy (self.current))
39 if ... then return self:add(...) end
43 self.current = table.remove (self.stack)
46 function scope:add (vars, val)
48 for i, id in ipairs (vars) do
49 assert(id.tag=='Id' or id.tag=='Dots' and i==#vars)
50 if id.tag=='Id' then self.current[id[1]] = val end