turtle/tlang: add . map indexing
var.key pushes the value indexed by key in var onto the stack quotes also work for assignment numerical keys do not work yet
This commit is contained in:
parent
a4b2aca647
commit
42a253cc71
@ -68,10 +68,13 @@ function tlang.get_state(code)
|
||||
|
||||
return {
|
||||
locals = {{
|
||||
pc = {sg = 1, pos = "__ast__", elem = 1},
|
||||
v__src__ = tlang.value_to_tlang(code),
|
||||
v__lex__ = tlang.value_to_tlang(lexed),
|
||||
v__ast__ = {type = "code", value = parsed}}},
|
||||
pc = {sg = 1, pos = {"__ast__"}, elem = 1},
|
||||
vars = {
|
||||
__src__ = tlang.value_to_tlang(code),
|
||||
__lex__ = tlang.value_to_tlang(lexed),
|
||||
__ast__ = {type = "code", value = parsed}
|
||||
}
|
||||
}},
|
||||
stack = {},
|
||||
code_stack = {},
|
||||
builtins = tlang.builtins
|
||||
@ -87,6 +90,45 @@ function tlang.pretty_pc(pc)
|
||||
return tostring(pc.sg) .. ";" .. tostring(pc.pos) .. ";" .. tostring(pc.elem)
|
||||
end
|
||||
|
||||
function tlang.format_table(t, depth, maxdepth)
|
||||
depth = depth or 0
|
||||
maxdepth = maxdepth or -1
|
||||
|
||||
if depth == maxdepth then
|
||||
return "{...}"
|
||||
end
|
||||
|
||||
local out = {}
|
||||
out[1] = "{\n"
|
||||
|
||||
for k, v in pairs(t) do
|
||||
local idx = k
|
||||
if type(k) == "string" then
|
||||
idx = '"' .. k .. '"'
|
||||
elseif type(k) == "table" then
|
||||
idx = "{...}"
|
||||
end
|
||||
|
||||
out[#out + 1] = string.rep("\t", depth + 1) .. "[" .. idx .. "] = "
|
||||
|
||||
if type(v) == "table" then
|
||||
out[#out + 1] = tlang.format_table(v, depth + 1, maxdepth)
|
||||
elseif type(v) == "string" then
|
||||
out[#out + 1] = '"' .. v .. '"'
|
||||
else
|
||||
out[#out + 1] = tostring(v)
|
||||
end
|
||||
|
||||
out[#out + 1] = ",\n"
|
||||
end
|
||||
|
||||
out[#out + 1] = string.rep("\t", depth) .. "}"
|
||||
return table.concat(out)
|
||||
end
|
||||
|
||||
function tlang.print_table(t, maxdepth)
|
||||
print(tlang.format_table(t, nil, maxdepth))
|
||||
end
|
||||
|
||||
local function test()
|
||||
local complex = [[{dup *} `square =
|
||||
@ -185,7 +227,25 @@ local function test()
|
||||
|
||||
local paren_test = "('works' print) 'out' print"
|
||||
|
||||
tlang.exec(paren_test)
|
||||
local mapdot_test = [[
|
||||
[1 a:5 b:[a:2 b:3] ] `a =
|
||||
4 `a.a =
|
||||
a.a print
|
||||
a.b.b print
|
||||
]]
|
||||
|
||||
local stackdot_test = [[
|
||||
[a:1 b:2]
|
||||
.b print
|
||||
6 `.a =
|
||||
.a print
|
||||
]]
|
||||
|
||||
local test = stackdot_test
|
||||
|
||||
--tlang.print_table(tlang.lex(test))
|
||||
--tlang.print_table(tlang.parse(tlang.lex(test)))
|
||||
tlang.exec(test)
|
||||
end
|
||||
|
||||
if minetest == nil then
|
||||
|
@ -131,16 +131,12 @@ local function lex_identifier_raw(state, top)
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(identifier)
|
||||
return {table.concat(identifier)}
|
||||
end
|
||||
|
||||
local function lex_identifier(state)
|
||||
local id = lex_identifier_raw(state, true)
|
||||
if type(id) == "string" then
|
||||
return {type = "literal", subtype = "identifier", value = id}
|
||||
elseif type(id) == "table" then
|
||||
return {type = "literal", subtype = "mapid", value = id}
|
||||
end
|
||||
return {type = "literal", subtype = "identifier", value = id}
|
||||
end
|
||||
|
||||
-- `identifier
|
||||
|
@ -13,6 +13,8 @@ symbol
|
||||
|
||||
local tlang = {}
|
||||
|
||||
local internal = {}
|
||||
|
||||
local function sublist(list, istart, iend, inclusive)
|
||||
local o = {}
|
||||
local oi = 1
|
||||
@ -35,8 +37,6 @@ local function sublist(list, istart, iend, inclusive)
|
||||
end
|
||||
|
||||
|
||||
--tlang.parse = function(lexed) end
|
||||
|
||||
local function parse_peek(state)
|
||||
return state.lexed[state.position]
|
||||
end
|
||||
@ -69,15 +69,19 @@ local function parse_map(state)
|
||||
local key = n.value
|
||||
local mr = parse_peek(state)
|
||||
|
||||
if type(key) == "table" then
|
||||
key = key[1]
|
||||
end
|
||||
|
||||
if mr.type == "map_relation" then
|
||||
parse_next(state)
|
||||
local nval = tlang.parse({parse_next(state)})
|
||||
local nval = internal.parse_step(state)
|
||||
|
||||
if nval == nil then
|
||||
return nil -- ERROR
|
||||
end
|
||||
|
||||
map[key] = nval[1]
|
||||
map[key] = nval
|
||||
skip = true
|
||||
end
|
||||
end
|
||||
@ -126,7 +130,7 @@ local function parse_code(state, open, close)
|
||||
}
|
||||
end
|
||||
|
||||
local function parse_step(state)
|
||||
function internal.parse_step(state)
|
||||
local n = parse_peek(state)
|
||||
|
||||
if n == nil then
|
||||
@ -171,7 +175,7 @@ function tlang.parse(lexed)
|
||||
local treei = 1
|
||||
|
||||
while true do
|
||||
local n = parse_step(state)
|
||||
local n = internal.parse_step(state)
|
||||
|
||||
if n == nil then
|
||||
if state.position <= #state.lexed then
|
||||
|
@ -106,7 +106,7 @@ function tlang.call(state, target)
|
||||
target.pos = #state.code_stack
|
||||
end
|
||||
|
||||
state.locals[#state.locals + 1] = {pc = target}
|
||||
state.locals[#state.locals + 1] = {vars = {}, pc = target}
|
||||
end
|
||||
|
||||
function tlang.call_tos(state)
|
||||
@ -151,7 +151,7 @@ local function find_var_pos(state, name)
|
||||
|
||||
for i = 1, slen do
|
||||
local v = state.locals[slen + 1 - i]
|
||||
if in_keys("v" .. name, v) then
|
||||
if in_keys(name, v.vars) then
|
||||
return slen + 1 - i
|
||||
end
|
||||
end
|
||||
@ -160,24 +160,82 @@ end
|
||||
function tlang.near_access(state, name)
|
||||
local n = find_var_pos(state, name)
|
||||
if n then
|
||||
return state.locals[n]["v" .. name]
|
||||
return state.locals[n].vars[name]
|
||||
end
|
||||
end
|
||||
|
||||
function tlang.map_access_assign(state, index, start, assign)
|
||||
local container
|
||||
local curtab
|
||||
|
||||
if start then
|
||||
container = start
|
||||
elseif index[1] == "" and #index > 1 then
|
||||
curtab = state.stack[#state.stack].value
|
||||
else
|
||||
local pos = find_var_pos(state, index[1])
|
||||
-- assignments can go at the current scope
|
||||
if assign then
|
||||
pos = pos or #state.locals
|
||||
end
|
||||
|
||||
container = state.locals[pos].vars
|
||||
end
|
||||
|
||||
if not container and not curtab then
|
||||
return
|
||||
end
|
||||
|
||||
if #index == 1 then
|
||||
if assign then
|
||||
container[index[1]] = assign
|
||||
return
|
||||
else
|
||||
return container[index[1]]
|
||||
end
|
||||
end
|
||||
|
||||
curtab = curtab or container[index[1]].value
|
||||
|
||||
for idx = 2, #index - 1 do
|
||||
curtab = curtab[index[idx]]
|
||||
|
||||
if not curtab then
|
||||
return nil
|
||||
end
|
||||
|
||||
curtab = curtab.value
|
||||
end
|
||||
|
||||
if assign then
|
||||
curtab[index[#index]] = assign
|
||||
else
|
||||
return curtab[index[#index]]
|
||||
end
|
||||
end
|
||||
|
||||
function tlang.near_access_indexed(state, index)
|
||||
return tlang.map_access_assign(state, index)
|
||||
end
|
||||
|
||||
function tlang.near_assign_indexed(state, index, value)
|
||||
tlang.map_access_assign(state, index, nil, value)
|
||||
end
|
||||
|
||||
function tlang.global_assign(state, name, value)
|
||||
state.locals[0]["v" .. name] = value
|
||||
state.locals[0].vars[name] = value
|
||||
end
|
||||
|
||||
function tlang.local_assign(state, name, value)
|
||||
state.locals[#state.locals]["v" .. name] = value
|
||||
state.locals[#state.locals].vars[name] = value
|
||||
end
|
||||
|
||||
function tlang.near_assign(state, name, value)
|
||||
local n = find_var_pos(state, name)
|
||||
if n then
|
||||
state.locals[n]["v" .. name] = value
|
||||
state.locals[n].vars[name] = value
|
||||
else
|
||||
state.locals[#state.locals]["v" .. name] = value
|
||||
state.locals[#state.locals].vars[name] = value
|
||||
end
|
||||
end
|
||||
|
||||
@ -190,7 +248,7 @@ local function accesspc(state, pc)
|
||||
if pc.sg == 0 then -- stack
|
||||
code = state.code_stack[pc.pos]
|
||||
elseif pc.sg == 1 then -- global
|
||||
code = tlang.near_access(state, pc.pos)
|
||||
code = tlang.near_access_indexed(state, pc.pos)
|
||||
end
|
||||
|
||||
if code then
|
||||
@ -315,7 +373,7 @@ tlang.builtins["="] = function(state)
|
||||
local name = statepop_type(state, "quote")
|
||||
local value = tlang.pop_raw(state)
|
||||
|
||||
tlang.near_assign(state, name.value, value)
|
||||
tlang.near_assign_indexed(state, name.value, value)
|
||||
end
|
||||
|
||||
function tlang.unary(func)
|
||||
@ -325,7 +383,7 @@ function tlang.unary(func)
|
||||
statepush_num(state, func(tos.value))
|
||||
elseif tos.type == "quote" then
|
||||
local n = tlang.near_access(state, tos.value)
|
||||
tlang.near_assign(state, tos.value, {type = "number", value = func(n.value)})
|
||||
tlang.near_assign_indexed(state, tos.value, {type = "number", value = func(n.value)})
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -657,13 +715,18 @@ function tlang.step(state)
|
||||
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
|
||||
local f = state.builtins[cur.value]
|
||||
local strname = cur.value
|
||||
if type(cur.value) == "table" then
|
||||
strname = cur.value[1]
|
||||
end
|
||||
|
||||
if in_keys(strname, state.builtins) then
|
||||
local f = state.builtins[strname]
|
||||
f(state)
|
||||
else
|
||||
local var = tlang.near_access(state, cur.value)
|
||||
local var = tlang.near_access_indexed(state, cur.value)
|
||||
if var == nil then
|
||||
return "Undefined identifier: " .. cur.value
|
||||
return "Undefined identifier: " .. table.concat(cur.value, ".")
|
||||
elseif var.type == "code" then
|
||||
tlang.call_var(state, cur.value)
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user