Nov 13 18:33 2013 environment.lua Page 1 --[[ Environment Module KILT -- Kamin Interpreters in Lua Toolset H. Conrad Cunningham, Professor Computer and Information Science University of Mississippi Developed for CSci 658, Software Language Engineering, Fall 2013 2013-08-12: Module built from Core interpreter Environment 2013-08-14: Function dumpEnv added to aid in debugging 2013-08-22: Added require of Utilities module 2013-08-24: Cleaned dependencies and comments 2013-11-13: Corrected setVal ("senv" in "assign" call) 1234567890123456789012345678901234567890123456789012345678901234567890 Table globalEnv stores the definitions for variables at the outermost level. Other environment frames are linked to this global environment using their ENCLOSING keys. The Kamin Core and Lisp interpreters only use environment frames for one level of function call parameter/argument bindings. --]] -- KILT tree utilities library local util = require "utilities" local treeConcat = util.treeConcat -- Global Environment table local globalEnv = {} local ENCLOSING = -1 -- key for enclosing environment pointer -- Function "newEnv" constructs a new empty environment frame enclosed -- within "env". If "env" is nil or unspecified, it defaults the -- enclosing environment to "globalEnv". local function newEnv(env) env = env or globalEnv local localEnv = {} -- new empty environment frame localEnv[ENCLOSING] = env -- that is enclosed within "env" return localEnv end -- Function "findBinding" returns the environment frame in which "s" -- is defined; else it returns nil. The returned value is "env" or an -- environment frame that encloses it. local function findBinding(s,env) if not env then return nil elseif env[s] then return env Nov 13 18:33 2013 environment.lua Page 2 else return findBinding(s,env[ENCLOSING]) end end -- Function "getVal" returns the value of name "n" in the environment -- frame "env" or some enclosing environment frame; it returns nil if -- not found. local function getVal(n,env) local boundin = findBinding(n,env) if boundin then return boundin[n] else return nil end end -- Side-effecting function "assign" sets name "n" to have value "v" in -- environment frame "env". local function assign(n,v,env) env[n] = v end -- Side-effecting function "setVal" searches for a binding of name "n" -- in environment frame "env" or any enclosing environment frame. If -- "n" is bound, then "setVal" sets the value to "v"; otherwise,it -- binds "n" to "v" in environment frame "defenv" or in "globalenv" if -- "defenv" is nil or unspecified. local function setVal(n,v,env,defenv) defenv = defenv or globalEnv senv = findBinding(n,env) or defenv assign(n,v,senv) return v end -- Procedure "dumpEnv" prints all bindings in the environment. It is -- intended for debugging. local function dumpEnv(env) print("Environment frame dump") if env then for k,v in pairs(env) do print(k,treeConcat(v)) end dumpEnv(env[ENCLOSING]) else print("End dump") end end Nov 13 18:33 2013 environment.lua Page 3 -- MODULE EXPORT LIST -- ENCLOSING and findBinding are not exported -- Caution: An environment frame's table can be directly accessed by -- clients. This should not be necessary because the "getVal", -- "assign", and "setVal" functions should give the neeed access. return { globalEnv = globalEnv, newEnv = newEnv, getVal = getVal, assign = assign, setVal = setVal, dumpEnv = dumpEnv -- for debugging }