Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://angg.twu.net/SRF/srfx-interpreter.lua.html -- http://angg.twu.net/SRF/srfx-interpreter.lua -- (find-angg "SRF/srfx-interpreter.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- -- (defun es () (interactive) (find-angg "SRF/srfx.lua")) -- (defun ei () (interactive) (find-angg "SRF/srfx-interpreter.lua")) -- «.interpreter_auxiliary» (to "interpreter_auxiliary") -- «.interpreter_primitives» (to "interpreter_primitives") -- «.interpreter_preamble» (to "interpreter_preamble") -- «.interpreter__index» (to "interpreter__index") -- «.tests» (to "tests") dofile "srfx-basics.lua" -- «interpreter_auxiliary» (to ".interpreter_auxiliary") interpreter_auxiliary = { -- functions used by a subset of primitives loop = function(terp, push_index) local n, s = terp:pop(), terp:pop() for i = 0, n-1 do if push_index then terp:push(i) end local status, err = pcall(terp.dophrase, terp, s) if not status then -- break or rethrow if err == 'break' then break else error(err, 0) end end end end, } -- «interpreter_primitives» (to ".interpreter_primitives") interpreter_primitives = { -- o: an interpreter object ['*'] = function(o) o:push(o:pop() * o:pop()) end, ['**'] = function(o) o.stack:swap(); o:push(o:pop() ^ o:pop()) end, ['+'] = function(o) o:push(o:pop() + o:pop()) end, ['-'] = function(o) o.stack:swap(); o:push(o:pop() - o:pop()) end, ['/'] = function(o) o.stack:swap(); o:push(o:pop() / o:pop()) end, ['//'] = function(o) o.stack:swap(); o:push(o:pop() % o:pop()) end, ['.'] = function(o) print(o:pop()) end, ['.s'] = function(o) print(o.stack) end, ['.vocab'] = function(o) local all, max = {}, 0 for word, _ in pairs(o.vocab) do max=math.max(max, #word) table.insert(all, word) end local fmt = string.format('%%-%ds %%s', max+1) for _, word in ipairs(sorted(all)) do print(string.format(fmt, word, trim(o.vocab[word]))) end end, ['<'] = function(o) o:push(fromBool(o:pop() > o:pop())) end, ['<='] = function(o) o:push(fromBool(o:pop() >= o:pop())) end, ['<>'] = function(o) o:push(fromBool(o:pop() ~= o:pop())) end, ['='] = function(o) o:push(fromBool(o:pop() == o:pop())) end, ['>'] = function(o) o:push(fromBool(o:pop() < o:pop())) end, ['>='] = function(o) o:push(fromBool(o:pop() <= o:pop())) end, ['and'] = function(o) o:push(fromBool(toBool(o:pop()) and toBool(o:pop()))) end, ['break'] = function(o) throw.brk() end, ['clear'] = function(o) o.vocab[o:pop()]=nil end, ['concat'] = function(o) o.stack:swap(); o:push(o:pop() .. o:pop()) end, ['defined?'] = function(o) o:push(fromBool(o.vocab[o:pop()] ~= nil)) end, ['do'] = function(o) o:dophrase(o:pop()) end, ['drop'] = function(o) o.stack:pop() end, ['dup'] = function(o) o.stack:dup() end, ['either'] = function(o) if not toBool(o:pop()) then o.stack:swap() end o:pop() end, ['fetch'] = function(o) o:push(o.vocab[o:pop()] or '') end, ['host'] = function(o) local env = copyTable(_ENV or _G); env.self = o local fn, err = loadstr(o.stack:pop(), env) if not fn then throw.host(err) end fn() end, ['not'] = function(o) o:push(fromBool(not toBool(o:pop()))) end, ['or'] = function(o) o:push(fromBool(toBool(o:pop()) or toBool(o:pop()))) end, ['over'] = function(o) o.stack:over() end, ['quote'] = function(o) o:push(quote(o:pop())) end, ['repeat'] = function(o) o.aux.loop(o) end, ['repeat#'] = function(o) o.aux.loop(o, true) end, ['reverse'] = function(o) o:push(string.reverse(o:pop())) end, ['rot'] = function(o) o.stack:rot() end, ['sentence'] = function(o) o:push(o.line); o.line = '' end, ['store'] = function(o) o.vocab[o:pop()]=o:pop() end, ['swap'] = function(o) o.stack:swap() end, ['trim'] = function(o) o:push(trim(o:pop())) end, ['version'] = function(o) o:push(_VERSION) end, ['word'] = function(o) local token = nextToken(o.line) o.line = token.rest o:push(token.word) end, ['words'] = function(o) local all, seen = {}, {} for _, dict in ipairs({o.prims, o.vocab}) do for word, _ in pairs(dict) do if not seen[word] then seen[word]=true table.insert(all, word) end end end print(table.concat(sorted(all), ' ')) end, } -- «interpreter_preamble» (to ".interpreter_preamble") -- interpreter_preamble = [[ 'word sentence swap store' ':' store : if either do : when '' swap if : unless not when : until 'break' swap when : while 'break' swap unless : nip swap drop : tuck swap over : shell 'os.execute(self:pop())' host : value swap quote swap store : drops 'drop' swap repeat : inc 1 + : dec 1 - ]] -- «interpreter__index» (to ".interpreter__index") -- interpreter__index = { doword = function(terp, word, kind) if kind == 'literal' then terp.stack:push(word) elseif terp.vocab[word] then terp:dophrase(terp.vocab[word]) elseif terp.prims[word] then terp.prims[word](terp) else throw.unknown(word) end end, dophrase = function(terp, phrase, top) while string.match(phrase, '%S') do local token = nextToken(phrase); phrase = token.rest if top then terp.line = phrase end terp:doword(token.word, token.kind) if top then phrase = terp.line end end end, doline = function(terp, line) -- the toplevel local status, err = pcall(terp.dophrase, terp, line, 1) if not status then print('[' .. err .. ']') if terp.stack:depth() > 0 then print('stack was: ' .. terp.stack:image()) end terp.stack:reset() end end, pop = function(terp) return terp.stack:pop() end, push = function(terp, v) return terp.stack:push(v) end, } -- ___ _ _ -- |_ _|_ __ | |_ ___ _ __ _ __ _ __ ___| |_ ___ _ __ -- | || '_ \| __/ _ \ '__| '_ \| '__/ _ \ __/ _ \ '__| -- | || | | | || __/ | | |_) | | | __/ || __/ | -- |___|_| |_|\__\___|_| | .__/|_| \___|\__\___|_| -- |_| -- Interpreter = Class { type = "Interpreter", new = function (T) return Interpreter(T or {}) end, newindep = function () return Interpreter.new { vocab = {}, stack = Stack.new() } end, __index = over(interpreter__index) { aux = interpreter_auxiliary, prims = interpreter_primitives, stack = Stack.new(), vocab = {}, dolines = function (t, bigstr) for _,line in ipairs(splitlines(bigstr)) do t:doline(line) end return t end, dopreamble = function (t) t:dolines(interpreter_preamble) return t end, repl = function (t) t.STOP = nil while not(t.STOP) do local line = io.read() t:doline(line) end end, }, } -- «tests» (to ".tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "srfx-interpreter.lua" terp = Interpreter.new():dopreamble() PPV(terp.vocab) = terp.vocab.square interpreter_primitives['setprim0'] = function(o) local body, name = o.stack:pop(), o.stack:pop() local f = expr("function(o) "..body.."\n end") interpreter_primitives[name] = f end terp:repl() 'hello' 'world' 10 20 .s : square dup * 5 square . "\n" . 'print("a\nb")' host 'push42' 'o.stack:push(42)' setprim0 push42 . : prim: word sentence setprim0 prim: push43 o.stack:push(43) push43 . 'terp.STOP = 1' host = terp.vocab.square --]] -- Local Variables: -- coding: utf-8-unix -- End: