diff options
| author | Marc Vertes <mvertes@free.fr> | 2023-08-31 17:53:54 +0200 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2023-08-31 17:53:54 +0200 |
| commit | 851c793da43be9e4d3319afe440d603c85834045 (patch) | |
| tree | fd4b3d3812f5743213b5849858c459c8196dbf7f /vm1/vm.go | |
| parent | 0f4bfe6e70263fbeb580014b62632f403b29b414 (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/vm.go')
| -rw-r--r-- | vm1/vm.go | 14 |
1 files changed, 11 insertions, 3 deletions
@@ -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 { |
