diff options
| author | Marc Vertes <mvertes@free.fr> | 2023-11-23 17:56:35 +0100 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2023-11-24 09:12:46 +0100 |
| commit | 6a32a7bc5f6320902cd5c2910a1353a0f7039237 (patch) | |
| tree | 0fcce51e4d4f54d48d57a5dda8a896a35264f68b /vm | |
| parent | c548093d79edece3c1cbb7e4dc03d92fe45b1cc7 (diff) | |
parser: fix allocation of local variables
A 'New' instruction is added in VM to manage initialisation
of typed variables in the stack. The instantiated type symbols
are now added to global data. Accessing and setting values by
address is now working.
Diffstat (limited to 'vm')
| -rw-r--r-- | vm/vm.go | 40 | ||||
| -rw-r--r-- | vm/vm_test.go | 5 |
2 files changed, 30 insertions, 15 deletions
@@ -14,7 +14,7 @@ const ( // instruction effect on stack: values consumed -- values produced Nop = iota // -- Add // n1 n2 -- sum ; sum = n1+n2 - Address // a -- &a ; + Addr // a -- &a ; Assign // val -- ; mem[$1] = val Fassign // val -- ; mem[$1] = val Vassign // val dest -- ; dest.Set(val) @@ -39,6 +39,7 @@ const ( Lower // n1 n2 -- cond ; cond = n1 < n2 Loweri // n1 -- cond ; cond = n1 < $1 Mul // n1 n2 -- prod ; prod = n1*n2 + New // -- x; mem[fp+$1] = new mem[$2] Not // c -- r ; r = !c Pop // v -- Push // -- v @@ -50,7 +51,7 @@ const ( var strop = [...]string{ // for VM tracing. Nop: "Nop", Add: "Add", - Address: "Address", + Addr: "Addr", Assign: "Assign", Call: "Call", Calli: "Calli", @@ -74,6 +75,7 @@ var strop = [...]string{ // for VM tracing. Lower: "Lower", Loweri: "Loweri", Mul: "Mul", + New: "New", Not: "Not", Pop: "Pop", Push: "Push", @@ -87,8 +89,7 @@ type Code [][]int64 // Machine represents a virtual machine. type Machine struct { - code Code // code to execute - // mem []any // memory, as a stack + code Code // code to execute mem []reflect.Value // memory, as a stack ip, fp int // instruction and frame pointer ic uint64 // instruction counter, incremented at each instruction executed @@ -113,7 +114,7 @@ func (m *Machine) Run() (err error) { op3 = strconv.Itoa(int(c[3])) } } - log.Printf("ip:%-4d sp:%-4d fp:%-4d op:[%-12s %-4s %-4s] mem:%v\n", ip, sp, fp, strop[c[1]], op2, op3, mem) + log.Printf("ip:%-4d sp:%-4d fp:%-4d op:[%-12s %-4s %-4s] mem:%v\n", ip, sp, fp, strop[c[1]], op2, op3, Vstring(mem)) } for { @@ -125,15 +126,15 @@ func (m *Machine) Run() (err error) { mem[sp-2] = reflect.ValueOf(int(mem[sp-2].Int() + mem[sp-1].Int())) mem = mem[:sp-1] case Mul: - mem[sp-2].SetInt(mem[sp-2].Int() * mem[sp-1].Int()) + mem[sp-2] = reflect.ValueOf(int(mem[sp-2].Int() * mem[sp-1].Int())) mem = mem[:sp-1] - case Address: + case Addr: mem[sp-1] = mem[sp-1].Addr() case Assign: - mem[op[2]] = mem[sp-1] + mem[op[2]].Set(mem[sp-1]) mem = mem[:sp-1] case Fassign: - mem[fp+int(op[2])-1] = mem[sp-1] + mem[fp+int(op[2])-1].Set(mem[sp-1]) mem = mem[:sp-1] case Call: nip := int(mem[sp-1].Int()) @@ -161,6 +162,8 @@ func (m *Machine) Run() (err error) { mem[sp-1] = mem[sp-1].Elem() case Dup: mem = append(mem, mem[int(op[2])]) + case New: + mem[int(op[2])+fp-1] = reflect.New(mem[int(op[3])].Type()).Elem() case Equal: mem[sp-2] = reflect.ValueOf(mem[sp-2].Equal(mem[sp-1])) mem = mem[:sp-1] @@ -226,7 +229,9 @@ func (m *Machine) Run() (err error) { case Pop: mem = mem[:sp-int(op[2])] case Push: - mem = append(mem, reflect.ValueOf(int(op[2]))) + //mem = append(mem, reflect.ValueOf(int(op[2]))) + mem = append(mem, reflect.New(reflect.TypeOf(0)).Elem()) + mem[sp].SetInt(op[2]) case Grow: mem = append(mem, make([]reflect.Value, op[2])...) case Return: @@ -236,10 +241,10 @@ func (m *Machine) Run() (err error) { mem = append(mem[:ofp-int(op[2])-int(op[3])-1], mem[sp-int(op[2]):]...) continue case Sub: - mem[sp-2].SetInt(mem[sp-1].Int() - mem[sp-2].Int()) + mem[sp-2] = reflect.ValueOf(int(mem[sp-1].Int() - mem[sp-2].Int())) mem = mem[:sp-1] case Subi: - mem[sp-1].SetInt(mem[sp-1].Int() - op[2]) + mem[sp-1] = reflect.ValueOf(int(mem[sp-1].Int() - op[2])) case Index: mem[sp-2] = mem[sp-1].Index(int(mem[sp-2].Int())) mem = mem[:sp-1] @@ -309,3 +314,14 @@ func slint(a []int64) []int { } return r } + +func Vstring(lv []reflect.Value) string { + s := "[" + for _, v := range lv { + if s != "[" { + s += " " + } + s += fmt.Sprintf("%v", v) + } + return s + "]" +} diff --git a/vm/vm_test.go b/vm/vm_test.go index c9540d2..07c063e 100644 --- a/vm/vm_test.go +++ b/vm/vm_test.go @@ -23,9 +23,8 @@ func TestVM(t *testing.T) { if err := m.Run(); err != nil { t.Errorf("run error: %v", err) } - t.Log(m.mem) - r := fmt.Sprintf("%v", m.mem[test.start:test.end]) - if r != test.mem { + t.Log(Vstring(m.mem)) + if r := Vstring(m.mem[test.start:test.end]); r != test.mem { t.Errorf("got %v, want %v", r, test.mem) } }) |
