turtle/tlang: improve API, add more boolean builtins

This commit is contained in:
cron 2020-11-07 19:27:25 +00:00 committed by Schmappie Eldress
parent 76f3138dbe
commit e77a5f9e83
2 changed files with 79 additions and 9 deletions

View File

@ -85,6 +85,10 @@ function tlang.exec(code)
tlang.run(state)
end
function tlang.pretty_pc(pc)
return tostring(pc.sg) .. ";" .. tostring(pc.pos) .. ";" .. tostring(pc.elem)
end
local function test()
local complex = [[{dup *} `square =

View File

@ -117,6 +117,39 @@ function tlang.call_tos(state)
tlang.call(state, {sg = 0, pos = #state.stack, elem = 1})
end
function tlang.call_var(state, name)
tlang.call(state, {sg = 1, pos = name, elem = 1})
end
function tlang.call_builtin(state, name)
local f = state.builtins[name]
f(state)
end
function tlang.call_var_or_builtin(state, name)
if in_keys(name, state.builtins) then
tlang.call_builtin(state, name)
else
tlang.call_var(state, name)
end
end
function tlang.push_values(state, vals)
for i, v in ipairs(vals) do
tlang.push(state, v)
end
end
function tlang.lua_call_tos(state, ...)
tlang.push_values(state, {...})
tlang.call_tos(state)
end
function tlang.lua_call_var(state, name, ...)
tlang.push_values(state, {...})
tlang.call_var(state, name)
end
local function find_var_pos(state, name)
local slen = #state.locals
@ -152,7 +185,7 @@ function tlang.near_assign(state, name, value)
end
end
local function getpc(state)
function tlang.get_pc(state)
return state.locals[#state.locals].pc
end
@ -169,7 +202,7 @@ local function accesspc(state, pc)
end
end
local function incpc(state, pc)
function tlang.increment_pc(state, pc)
local next_pc = {sg = pc.sg, pos = pc.pos, elem = pc.elem + 1}
if accesspc(state, next_pc) then
@ -179,13 +212,15 @@ end
local function getnext(state)
if state.locals[#state.locals].nextpop then
local pc = getpc(state)
local pc = tlang.get_pc(state)
state.locals[#state.locals] = nil
if #state.locals == 0 then
-- allows for finished states to be used in calls
if #state.locals == 1 then
return nil
end
state.locals[#state.locals] = nil
-- pop code stack
if pc.sg == 0 then
state.code_stack[pc.pos] = nil
@ -196,11 +231,11 @@ local function getnext(state)
local current
if not state.locals[#state.locals].nextpop then
state.current_pc = getpc(state)
state.current_pc = tlang.get_pc(state)
current = accesspc(state, state.current_pc)
end
local incd = incpc(state, getpc(state))
local incd = tlang.increment_pc(state, tlang.get_pc(state))
if not incd then
state.locals[#state.locals].nextpop = true
else
@ -348,6 +383,32 @@ tlang.builtins["!="] = tlang.binary(function(v1, v2)
return tlang.boolean_to_number(v1 ~= v2)
end)
tlang.builtins[">="] = tlang.binary(function(v1, v2)
return tlang.boolean_to_number(v1 >= v2)
end)
tlang.builtins["<="] = tlang.binary(function(v1, v2)
return tlang.boolean_to_number(v1 <= v2)
end)
tlang.builtins[">"] = tlang.binary(function(v1, v2)
return tlang.boolean_to_number(v1 > v2)
end)
tlang.builtins["<"] = tlang.binary(function(v1, v2)
return tlang.boolean_to_number(v1 < v2)
end)
tlang.builtins["&&"] = tlang.binary(function(v1, v2)
return tlang.boolean_to_number(
tlang.number_to_boolean(v1) and tlang.number_to_boolean(v2))
end)
tlang.builtins["||"] = tlang.binary(function(v1, v2)
return tlang.boolean_to_number(
tlang.number_to_boolean(v1) or tlang.number_to_boolean(v2))
end)
tlang.builtins["if"] = function(state)
local tos = statepop_type(state, "code")
local tos1 = tlang.pop_raw(state)
@ -578,8 +639,13 @@ function tlang.step(state)
local cur = getnext(state)
if cur == nil then
state.finished = true
return false
elseif in_list(cur.type, literals) then
else
state.finished = false
end
if in_list(cur.type, literals) then
state.stack[#state.stack + 1] = cur
elseif cur.type == "identifier" or cur.type == "symbol" then
if in_keys(cur.value, state.builtins) then
@ -590,7 +656,7 @@ function tlang.step(state)
if var == nil then
return "Undefined identifier: " .. cur.value
elseif var.type == "code" then
tlang.call(state, {sg = 1, pos = cur.value, elem = 1})
tlang.call_var(state, cur.value)
else
state.stack[#state.stack + 1] = var
end