This commit is contained in:
2026-05-09 13:26:13 -05:00
parent 554a7b55c5
commit 610491c1d7
3 changed files with 51 additions and 16 deletions

View File

@@ -45,8 +45,8 @@ Function operations:
Table and array operations: Table and array operations:
16 getkv Get table's value based on key (pull 1 value, push 1 value) 16 getkv Get table's value based on key (pull 1 value, push 1 value)
17 setkv Set table's key and value (pull 2 values from stack) 17 setkv Set table's key and value (pull 2 values from stack)
a8 c8 e8 geta Get array's position value a8 c8 e8 geti Get array's position value
a9 c9 e9 seta Set array's position value a9 c9 e9 seti Set array's position value
18 appnd Add value to the end of array 18 appnd Add value to the end of array
19 next Push the next pair into the stack (for loops) 19 next Push the next pair into the stack (for loops)
1a smt Set value metatable 1a smt Set value metatable

View File

@@ -341,21 +341,21 @@ do TEST "VM: GC strings"
end end
do TEST "VM: arrays" do TEST "VM: arrays"
local vm = VM.new():set_debug(true):load(assemble [ local vm = VM.new():set_debug(true):load(assemble [[
.func 0 .func 0
newa newa
pushi 10 pushi 10
seta 0 seti 0
pushi 20 pushi 20
seta 1 seti 1
pushi 30 pushi 30
seta 2 seti 2
geta 1 geti 1
]):call(0) ret
]]):call(0)
print(vm:debug_heap()) print(vm:debug_heap())
assert_eq(vm:to_integer(-1), 20) assert_eq(vm:to_integer(-1), 20)
assert_eq(vm:is(-2, 'array'), true)
assert_eq(vm.heap:size(), 1) assert_eq(vm.heap:size(), 1)
end end

View File

@@ -29,6 +29,8 @@ local function validate_value(v)
assert(type(v.value) == 'number' and v.value >= 0, "function must be a positive number") assert(type(v.value) == 'number' and v.value >= 0, "function must be a positive number")
elseif v.type == 'string' then elseif v.type == 'string' then
assert(type(v.ref) == 'number' or type(v.const_ref) == 'number') assert(type(v.ref) == 'number' or type(v.const_ref) == 'number')
elseif v.type == 'array' then
assert(type(v.ref) == 'number')
end end
end end
@@ -228,6 +230,7 @@ function Heap:add_value(value)
end end
function Heap:get_value(key) function Heap:get_value(key)
assert(type(key) == 'number')
return self.items[key] return self.items[key]
end end
@@ -307,6 +310,11 @@ function VM:push_nil()
return self return self
end end
function VM:new_array()
self.stack:push({ type = 'array', ref = self.heap:add_value({}) })
return self
end
-- --
-- information -- information
-- --
@@ -316,6 +324,8 @@ function VM:stack_sz()
end end
function VM:is(idx, type_) function VM:is(idx, type_)
assert(type(idx) == "number")
assert(TYPE_MAP[type_])
return self.stack[idx].type == type_ return self.stack[idx].type == type_
end end
@@ -337,6 +347,14 @@ function VM:_extract_string(value)
end end
end end
function VM:_extract_array(value)
assert(value)
assert(value.type == 'array')
local array = self.heap:get_value(value.ref)
if type(array) ~= 'table' then error('Expected array') end
return self.heap:get_value(value.ref)
end
function VM:to_string(idx) function VM:to_string(idx)
local value = self.stack[idx] local value = self.stack[idx]
if value.type ~= 'string' then error("Type error: not a string") end if value.type ~= 'string' then error("Type error: not a string") end
@@ -348,6 +366,11 @@ function VM:format_value(v)
return tostring(v.value) return tostring(v.value)
elseif v.type == 'string' then elseif v.type == 'string' then
return self_:extract_string(v) return self_:extract_string(v)
elseif v.type == 'array' then
local array = self:_extract_array(v)
local tbl = {}
for _,vv in ipairs(array) do table.insert(tbl, self:format_value(vv)) end
return "[" .. table.concat(tbl, ', ') .. "]"
elseif v.type == 'function' then elseif v.type == 'function' then
return '@' .. tostring(v.value) return '@' .. tostring(v.value)
elseif v.type == 'nil' then elseif v.type == 'nil' then
@@ -365,7 +388,7 @@ function VM:debug_stack()
for _,fp in pairs(self.stack.fps) do for _,fp in pairs(self.stack.fps) do
if i == fp then table.insert(ss, '^ ') end if i == fp then table.insert(ss, '^ ') end
end end
table.insert(ss, '[' .. self:format_value(v) .. '] ') table.insert(ss, self:format_value(v) .. ' ')
end end
return table.concat(ss) return table.concat(ss)
end end
@@ -373,12 +396,7 @@ end
function VM:debug_heap() function VM:debug_heap()
local ss = { "Heap:\n" } local ss = { "Heap:\n" }
for k,v in pairs(self.heap.items) do for k,v in pairs(self.heap.items) do
table.insert(ss, string.format(" [%X] = ", k)) table.insert(ss, string.format(" [%X] = %s", k, pprint.pformat(v)))
if type(v) == 'string' then
table.insert(ss, '"' .. v .. '"')
else
error('Unsupported value in heap')
end
table.insert(ss, "\n") table.insert(ss, "\n")
end end
return table.concat(ss) return table.concat(ss)
@@ -459,6 +477,9 @@ function VM:_step()
error('REAL consts not supported for now.') error('REAL consts not supported for now.')
end end
elseif op.operator == 'newa' then
self:new_array()
elseif op.operator == 'pop' then elseif op.operator == 'pop' then
self.stack:pop() self.stack:pop()
@@ -485,6 +506,20 @@ function VM:_step()
local a = self.stack[op.operand] local a = self.stack[op.operand]
self.stack:push(a) self.stack:push(a)
--
-- table and array operations
--
elseif op.operator == 'seti' then
local array_ref = self.stack[-2]
local array = self:_extract_array(array_ref)
array[op.operand+1] = self.stack:pop()
elseif op.operator == 'geti' then
local array_ref = self.stack[-1]
local array = self:_extract_array(array_ref)
self.stack:push(array[op.operand+1])
-- --
-- logic/arithmetic operations -- logic/arithmetic operations
-- --