local function eval (prog) local env = {} for _, fn in ipairs (prog) do fn (env) end end local function keywords_for (apply) return function (word_list) local keywords = {} for _, word in ipairs (word_list) do keywords[word] = apply end return setmetatable (keywords, {__call = function (t, ...) return apply(...) end}) end end local function let (var) local _let = function (val) return function (env) if type (val) == "function" then val = val (env) end env[var] = val end end return keywords_for (_let) { "equal", "be" } end local function get (var) return function (env) return env[var] end end local function add (x) local _add = function (y) return function (env) if type (x) == "function" then x = x (env) end if type (y) == "function" then y = y (env) end if type (y) == "table" then print (next(y)) end return x + y end end return keywords_for (_add) { "to", "with" } end local function show (val) local _show = function (env) if type (val) == "function" then val = val (env) end print (val) end return _show end eval { let "x" .equal (1) ; let "y" .be (2) ; let "z" (3) ; show (add (get "x") .to (get "y")) ; show (add (get "y") .with (get "z")) ; }