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: