Commit 6a9b56d7 authored by Phil Hagelberg's avatar Phil Hagelberg

Fix conditionals; rename eval->exec.

parent 8fff5af9
......@@ -3,7 +3,7 @@ local lume = require("lume")
-- helper to turn Lua functions into Forth-like words take/return on stack
local stack_fn = function(arg_count, f)
return function(stack)
assert(#stack >= arg_count, "Stack underflow")
assert(#stack >= arg_count, "stack underflow")
local args = lume.last(stack, arg_count)
for _=1,arg_count do table.remove(stack) end
lume.push(stack, f(unpack(args)))
......@@ -22,18 +22,29 @@ local function read_till(env, stoppers)
return token
end
local function compile_token(token, env, exec_token)
if(not env.compiling) then return exec_token(env, token)
elseif(env.compilers[token]) then env.compilers[token](env.stack, env, token)
else table.insert(env.compiling, token) end
end
local function exec_body(body, env, exec_token)
local function exec_word(body, env, exec_token)
local i = 1
while body[i] do
exec_token(env, body[i])
if(#env.conditionals == 0) then
exec_token(env, body[i])
elseif(body[i] == "then") then
assert(#env.conditionals > 0, "if/then mismatch")
table.remove(env.conditionals)
elseif(body[i] == "else") then
assert(#env.conditionals > 0, "if/else mismatch")
env.conditionals[#env.conditionals] =
not env.conditionals[#env.conditionals]
elseif(lume.last(env.conditionals)) then
exec_token(env, body[i])
elseif(body[i] == "if") then
while(body[i] and body[i] ~= "then") do i = i + 1 end
end
i = i + 1
end
end
......@@ -47,7 +58,7 @@ local function exec_token(env, token)
elseif(type(env.dictionary[token]) == "function") then
env.dictionary[token](env.stack, env)
elseif(type(env.dictionary[token]) == "table") then
exec_body(env.dictionary[token], env, exec_token)
exec_word(env.dictionary[token], env, exec_token)
else
env.write("unknown word: " .. token .. "\n")
end
......@@ -60,8 +71,6 @@ local function exec(env, stoppers)
return exec(env, stoppers)
end
local primitives = {
swap = stack_fn(2, function(a, b) return b, a end),
rot = stack_fn(3, function(a, b, c) return b, c, a end),
......@@ -85,6 +94,10 @@ local primitives = {
env.compiling = {}
env.dictionary[pop_token(env)] = env.compiling
end,
["if"] = function(stack, env)
assert(#stack >= 1, "stack underflow")
table.insert(env.conditionals, table.remove(stack))
end,
["("] = function(_, env) read_till(env, {")"}) end,
[".s"] = function(stack, env)
env.write(table.concat(lume.map(stack, tostring), " ") .. "\n")
......
......@@ -42,17 +42,15 @@ return {test_booleans=
end,
test_if=
function()
-- assert_stack({1, 2}, "1 : f true if 2 then ; f")
-- assert_stack({1}, "1 : f false if 2 3 then ; f")
-- assert_stack({2, 8}, "true if 2 8 else 4 then")
-- assert_stack({4}, "false if 2 1 else 4 then")
-- assert_stack({92}, "true if 3 2 1 + = if 92 else 2 then then")
assert_stack({1, 2}, "1 : f true if 2 then ; f")
assert_stack({1}, "1 : f false if 2 3 then ; f")
assert_stack({2, 8}, ": f true if 2 8 else 4 then ; f")
assert_stack({4}, ": f false if 2 1 else 4 then ; f")
assert_stack({92},
"true : f if 3 2 1 + = if 92 else 2 then then ; f")
assert_stack({32},
": f false if 77 2 1 + = if 92 else 2 then else 32 then ; f")
end,
-- test_nested_if=
-- function()
-- assert_stack({32}, "false if 77 2 1 + = if 92 else 2 then "..
-- " else 32 then")
-- end,
-- test_loops=
-- function()
-- assert_stack({55}, "0 1 10 do i + loop")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment