summaryrefslogtreecommitdiff
path: root/vm1
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2023-08-31 17:53:54 +0200
committerMarc Vertes <mvertes@free.fr>2023-08-31 17:53:54 +0200
commit851c793da43be9e4d3319afe440d603c85834045 (patch)
treefd4b3d3812f5743213b5849858c459c8196dbf7f /vm1
parent0f4bfe6e70263fbeb580014b62632f403b29b414 (diff)
codegen: fix interpreter re-entrance
So multiple successive incremental Evals function correctly. Also improve the following: - Apply the same Eval API to vm0 and vm1 - parser: dot diagram display is now synchronous - codegen: outsource complex code generation for readability - vm1: Pop take the number of values to pop as operand
Diffstat (limited to 'vm1')
-rw-r--r--vm1/vm.go14
1 files changed, 11 insertions, 3 deletions
diff --git a/vm1/vm.go b/vm1/vm.go
index c2f4882..572a171 100644
--- a/vm1/vm.go
+++ b/vm1/vm.go
@@ -57,14 +57,15 @@ type Machine struct {
code [][]int64 // code to execute
mem []any // memory, as a stack
ip, fp int // instruction and frame pointer
+ ic uint64 // instruction counter, incremented at each instruction executed
// flags uint // to set options such as restrict CallX, etc...
}
// Run runs a program.
func (m *Machine) Run() (err error) {
- code, mem, ip, fp, sp := m.code, m.mem, m.ip, m.fp, 0
+ code, mem, ip, fp, sp, ic := m.code, m.mem, m.ip, m.fp, 0, m.ic
- defer func() { m.mem, m.ip, m.fp = mem, ip, fp }()
+ defer func() { m.mem, m.ip, m.fp, m.ic = mem, ip, fp, ic }()
trace := func() {
if !debug {
@@ -84,6 +85,7 @@ func (m *Machine) Run() (err error) {
for {
sp = len(mem) // stack pointer
trace()
+ ic++
switch op := code[ip]; op[1] {
case Add:
mem[sp-2] = mem[sp-2].(int) + mem[sp-1].(int)
@@ -136,7 +138,7 @@ func (m *Machine) Run() (err error) {
case Loweri:
mem[sp-1] = mem[sp-1].(int) < int(op[2])
case Pop:
- mem = mem[:sp-1]
+ mem = mem[:sp-int(op[2])]
case Push:
mem = append(mem, int(op[2]))
case Return:
@@ -164,6 +166,12 @@ func (m *Machine) PushCode(code ...[]int64) (p int) {
func (m *Machine) SetIP(ip int) { m.ip = ip }
func (m *Machine) Push(v ...any) (l int) { l = len(m.mem); m.mem = append(m.mem, v...); return }
func (m *Machine) Pop() (v any) { l := len(m.mem) - 1; v = m.mem[l]; m.mem = m.mem[:l]; return }
+func (m *Machine) Top() (v any) {
+ if l := len(m.mem); l > 0 {
+ v = m.mem[l-1]
+ }
+ return
+}
func (m *Machine) PopExit() {
if l := len(m.code); l > 0 && m.code[l-1][1] == Exit {