.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
--
|
--
|
||||||
|
|||||||
Reference in New Issue
Block a user