#5 A stack-based concatenative forthlike system. Not intended as a toy, but probableeee a damn toy.
##Example Code FUNC star 42 EMIT ENDFUNC star Output: *
pc=1 --program counter | |
program = {} --array of words in program | |
dict = {} --dictionary of user defined words | |
prim = {} --language keywords | |
stack= {} --working stack | |
rstack = {} --2nd stack | |
mem = {} --memory | |
mode = "interpret" | |
alive = true --used for halting and error | |
c_word = "" | |
function push(n) | |
stack[#stack+1]=n | |
end | |
function pop() | |
if #stack > 0 then | |
temp = stack[#stack] | |
stack[#stack]=nil | |
else | |
io.write("Stack Underflow") | |
temp = 0 | |
end | |
return temp | |
end | |
prim["+"] = function() push(pop()+pop()) end | |
prim["*"] = function() push(pop()*pop()) end | |
prim["-"] = function() local a = pop(); push(pop()-a) end | |
prim["/"] = function() local a = pop(); push(pop()/a) end | |
prim["."] = function() io.write(pop()) end | |
prim["@"] = function() local addr = pop(); local data = mem[addr] or 0; push(data) end | |
prim["!"] = function() local addr = pop(); mem[addr] = pop() end | |
prim.BL = function() io.write(" ") end | |
prim.EMIT = function() io.write(string.char(pop())) end | |
prim.FUNC = function() mode = "pre-compile" end | |
eval = function(s) | |
if prim[s] then --if word is a language primitive | |
prim[s]() --execute it | |
elseif dict[s] then --if word is a user defined function | |
for i = 1,#dict[s] do --step through each word in definition | |
process(dict[s][i]) --and process it | |
end | |
elseif type(tonumber(s)) == 'number' then --if word is a number | |
push(tonumber(s)) --push it on the stack | |
else --otherwise report the error | |
io.write("\nError: ",s) | |
alive=false | |
end | |
end | |
process = function(s) --process by mode and update modes | |
if mode == "interpret" then | |
eval(s) | |
elseif mode == "pre-compile" then | |
dict[s]={} | |
c_word = s | |
mode = "compile" | |
elseif mode == "compile" then | |
if s ~= "ENDFUNC" then | |
dict[c_word][#dict[c_word]+1] = s | |
else | |
mode = "interpret" | |
end | |
end | |
end | |
-- ******* MAIN LOOP ******** | |
io.write('>') --display our prompt | |
for line in io.lines(arg[1]) do --grab each line of std input | |
program=nil;program={} | |
for word in string.gmatch(line, '([^%s]+)') do --separate each whitespace delimited word | |
program[#program+1] = string.upper(word) --and put word into program array | |
end | |
pc=0;alive=true | |
while alive==true do | |
pc=pc+1 | |
if pc > #program then | |
alive = false | |
else | |
process(program[pc]) | |
end | |
end | |
io.write('\n>') --display our prompt before looping back for more input | |
end |