require("interpret") local nelli_scope = Scope() local function B(abstract,callback) nelli_scope:insert( Binding( interpret(abstract), callback ) ) end B("print (text)",function(s,e) log(s:evaluate(e.text)) end) B("text (literal)",function(s,e) return e.literal:text() end) B("do (expressions)",function(s,e) scope = Scope() scope.parent = s local res print(e.expressions) for item in iterate(e.expressions.items) do if type_of(item) ~= Expression then error( string.format( "Unexpected words '%s' in 'do' expression.", tostring(item) ) ) end res = scope:evaluate(item) end return res end) B("if (predicate) then (expression)",function(s,e) if s:evaluate(e.predicate) then return s:evaluate(e.expression) end end) B("true",function(s,e) return true end) B("false",function(s,e) return false end) B("(constant) = (expression)",function(s,e) local value = s:evaluate(e.expression) s:insert( Binding(e.constant:text(),function(s,e) return value end) ) end) B("format (string) with (terms)",function(s,e) local items = {} for expression in iterate(e.terms.items) do table.insert(items,s:evaluate(expression)) end return string.format( s:evaluate(e.string), table.unpack(items) ) end) B("while (predicate) (expression)",function(s,e) while s:evaluate(e.predicate) do s:evaluate(e.expression) end end) B("repeat (expression) while (predicate)",function(s,e) while true do s:evaluate(e.expression) if not s:evaluate(e.predicate) then break end end end B("repeat (expression) until (predicate)",function(s,e) while true do s:evaluate(e.expression) if s:evaluate(e.predicate) then break end end end B("new table",function(s,e) return {} end) B("(index) of (table)",function(s,e) return s:evaluate(e.table)[s:evaluate(e.index)] end) B("set (index) of (table) to (item)",function(s,e) s:evaluate(e.table)[s:evaluate(e.index)] end) B("macro (macro) expands to (expression)",function(s,e) s:insert(Binding(e.abstract,function(_s,_e) for identifier,expression in pairs(_e) do end _s:evaluate(e.expression) end) end) B("define (abstract) as (expression)",function(s,e) s:insert(Binding(e.abstract,function(_s,_e) return s:evaluate(e.expression) end)) end) local List = class("List") function List:new(...) do self.items = {...} end B("new list",function(s,e) return List() end) B("insert (item) into (list)",function(s,e) end) B("insert (item) into (list) at (index)",function(s,e) end) B("remove (needle) from (haystack)",function(s,e) end) B("remove from (haystack) at (index)",function(s,e) s:evaluate(e.haystack) end) local Variable = class() function Variable:new() end function Variable:set(item) self.data = item end function Variable:get() return self.data end B("let (variable)",function(s,e) local variable = Variable() s:insert( Binding(e.variable,function(s,e) return variable end) ) return variable end) B("set (variable) to (expression)",function(s,e) local var = s:evaluate(e.variable) local value = s:evaluate(e.expression) assert_meta(Variable)(var) var:set(value) end) B("get (variable)",function(s,e) local var = s:evaluate(e.variable) assert_meta(Variable)(var) return var:get(value) end) for item in iterate(nelli_scope.bindings) do print(item.template) end local args = {...} local function main() -- Take arguments as neli files to read and interpret for _,parameter in pairs(args) do local root = interpret(read(parameter)) nelli_scope:evaluate(root) end end main()