| ------------------------------------------------------------------------------- |
| -- Copyright (c) 2006-2013 Fabien Fleutot and others. |
| -- |
| -- All rights reserved. |
| -- |
| -- This program and the accompanying materials are made available |
| -- under the terms of the Eclipse Public License v1.0 which |
| -- accompanies this distribution, and is available at |
| -- http://www.eclipse.org/legal/epl-v10.html |
| -- |
| -- This program and the accompanying materials are also made available |
| -- under the terms of the MIT public license which accompanies this |
| -- distribution, and is available at http://www.lua.org/license.html |
| -- |
| -- Contributors: |
| -- Fabien Fleutot - API and implementation |
| -- |
| ------------------------------------------------------------------------------- |
| |
| ------------------------------------------------------------------------------- |
| -- |
| -- Scopes: this library helps keeping track of identifier scopes, |
| -- typically in code walkers. |
| -- |
| -- * scope:new() returns a new scope instance s |
| -- |
| -- * s:push() bookmarks the current set of variables, so the it can be |
| -- retrieved next time a s:pop() is performed. |
| -- |
| -- * s:pop() retrieves the last state saved by s:push(). Calls to |
| -- :push() and :pop() can be nested as deep as one wants. |
| -- |
| -- * s:add(var_list, val) adds new variable names (stirng) into the |
| -- scope, as keys. val is the (optional) value associated with them: |
| -- it allows to attach arbitrary information to variables, e.g. the |
| -- statement or expression that created them. |
| -- |
| -- * s:push(var_list, val) is a shortcut for |
| -- s:push(); s:add(var_list, val). |
| -- |
| -- * s.current is the current scope, a table with variable names as |
| -- keys and their associated value val (or 'true') as value. |
| -- |
| ------------------------------------------------------------------------------- |
| |
| scope = { } |
| scope.__index = scope |
| |
| function scope:new() |
| local ret = { current = { } } |
| ret.stack = { ret.current } |
| setmetatable (ret, self) |
| return ret |
| end |
| |
| function scope:push(...) |
| table.insert (self.stack, table.shallow_copy (self.current)) |
| if ... then return self:add(...) end |
| end |
| |
| function scope:pop() |
| self.current = table.remove (self.stack) |
| end |
| |
| function scope:add (vars, val) |
| val = val or true |
| for i, id in ipairs (vars) do |
| assert(id.tag=='Id' or id.tag=='Dots' and i==#vars) |
| if id.tag=='Id' then self.current[id[1]] = val end |
| end |
| end |
| |
| return scope |