diff options
| author | Marc Vertes <mvertes@free.fr> | 2026-01-06 19:02:29 +0100 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2026-01-06 19:02:29 +0100 |
| commit | bffc031ea83c7176aac3d3828de0060c6630140c (patch) | |
| tree | 32e30f3bec94884936c2cfc2d53d3ae496e13d61 /vm | |
| parent | f07fc0178831432b68f1b9bd6c96b257aa2e9abe (diff) | |
fix: correct and simplify parsing of expressions.
The expressions were parsed from right to left, and it was incorrect and
cumbersome. Now they are processed from left to right, with a simpler
and correct handling of precedence rules.
The vm function call syntax has been changed to set the function
before the input arguments on the stack, as to follow the declaring
order in languages.
Diffstat (limited to 'vm')
| -rw-r--r-- | vm/op_string.go | 19 | ||||
| -rw-r--r-- | vm/type.go | 10 | ||||
| -rw-r--r-- | vm/vm.go | 34 | ||||
| -rw-r--r-- | vm/vm_test.go | 102 |
4 files changed, 94 insertions, 71 deletions
diff --git a/vm/op_string.go b/vm/op_string.go index 63bf738..7eb0e5d 100644 --- a/vm/op_string.go +++ b/vm/op_string.go @@ -38,18 +38,19 @@ func _() { _ = x[Loweri-27] _ = x[Mul-28] _ = x[New-29] - _ = x[Not-30] - _ = x[Pop-31] - _ = x[Push-32] - _ = x[Return-33] - _ = x[Sub-34] - _ = x[Subi-35] - _ = x[Swap-36] + _ = x[Negate-30] + _ = x[Not-31] + _ = x[Pop-32] + _ = x[Push-33] + _ = x[Return-34] + _ = x[Sub-35] + _ = x[Subi-36] + _ = x[Swap-37] } -const _Op_name = "NopAddAddrAssignFassignVassignCallCalliCallXDerefDupFdupFnewEqualEqualSetExitFieldFieldSetGreaterGrowIndexJumpJumpTrueJumpFalseJumpSetTrueJumpSetFalseLowerLoweriMulNewNotPopPushReturnSubSubiSwap" +const _Op_name = "NopAddAddrAssignFassignVassignCallCalliCallXDerefDupFdupFnewEqualEqualSetExitFieldFieldSetGreaterGrowIndexJumpJumpTrueJumpFalseJumpSetTrueJumpSetFalseLowerLoweriMulNewNegateNotPopPushReturnSubSubiSwap" -var _Op_index = [...]uint8{0, 3, 6, 10, 16, 23, 30, 34, 39, 44, 49, 52, 56, 60, 65, 73, 77, 82, 90, 97, 101, 106, 110, 118, 127, 138, 150, 155, 161, 164, 167, 170, 173, 177, 183, 186, 190, 194} +var _Op_index = [...]uint8{0, 3, 6, 10, 16, 23, 30, 34, 39, 44, 49, 52, 56, 60, 65, 73, 77, 82, 90, 97, 101, 106, 110, 118, 127, 138, 150, 155, 161, 164, 167, 173, 176, 179, 183, 189, 192, 196, 200} func (i Op) String() string { idx := int(i) - 0 @@ -104,3 +104,13 @@ func (t *Type) FieldIndex(name string) []int { } return nil } + +// FieldType returns the type of struct field name. +func (t *Type) FieldType(name string) *Type { + for _, f := range reflect.VisibleFields(t.Rtype) { + if f.Name == name { + return &Type{Name: f.Name, PkgPath: f.PkgPath, Rtype: f.Type} + } + } + return nil +} @@ -24,7 +24,7 @@ const ( Addr // a -- &a ; Assign // val -- ; mem[$1] = val Fassign // val -- ; mem[$1] = val - Vassign // val dest -- ; dest.Set(val) + Vassign // dest val -- ; dest.Set(val) Call // f [a1 .. ai] -- [r1 .. rj] ; r1, ... = prog[f](a1, ...) Calli // f [a1 .. ai] -- [r1 .. rj] ; r1, ... = prog[f](a1, ...) CallX // f [a1 .. ai] -- [r1 .. rj] ; r1, ... = mem[f](a1, ...) @@ -49,6 +49,7 @@ const ( Loweri // n1 -- cond ; cond = n1 < $1 Mul // n1 n2 -- prod ; prod = n1*n2 New // -- x; mem[fp+$1] = new mem[$2] + Negate // -- ; - mem[fp] Not // c -- r ; r = !c Pop // v -- Push // -- v @@ -119,10 +120,13 @@ func (m *Machine) Run() (err error) { mem[fp+c.Arg[0]-1].Set(mem[sp-1].Value) mem = mem[:sp-1] case Call: - nip := int(mem[sp-1].Int()) - mem = append(mem[:sp-1], ValueOf(ip+1), ValueOf(fp)) + // nip := int(mem[sp-1].Int()) + // mem = append(mem[:sp-1], ValueOf(ip+1), ValueOf(fp)) + nip := int(mem[sp-1-c.Arg[0]].Int()) + mem = append(mem, ValueOf(ip+1), ValueOf(fp)) ip = nip - fp = sp + 1 + // fp = sp + 1 + fp = sp + 2 continue case Calli: mem = append(mem, ValueOf(ip+1), ValueOf(fp)) @@ -132,9 +136,9 @@ func (m *Machine) Run() (err error) { case CallX: // Should be made optional. in := make([]reflect.Value, c.Arg[0]) for i := range in { - in[i] = mem[sp-2-i].Value + in[i] = mem[sp-1-i].Value } - f := mem[sp-1].Value + f := mem[sp-1-c.Arg[0]].Value mem = mem[:sp-c.Arg[0]-1] for _, v := range f.Call(in) { mem = append(mem, Value{Value: v}) @@ -142,7 +146,8 @@ func (m *Machine) Run() (err error) { case Deref: mem[sp-1].Value = mem[sp-1].Value.Elem() case Dup: - mem = append(mem, mem[c.Arg[0]]) + k := c.Arg[0] + mem = append(mem, mem[k]) case New: mem[c.Arg[0]+fp-1] = NewValue(mem[c.Arg[1]].Type) case Equal: @@ -214,13 +219,15 @@ func (m *Machine) Run() (err error) { } mem = mem[:sp-1] case Greater: - mem[sp-2] = ValueOf(mem[sp-1].Int() > mem[sp-2].Int()) + mem[sp-2] = ValueOf(mem[sp-2].Int() > mem[sp-1].Int()) mem = mem[:sp-1] case Lower: - mem[sp-2] = ValueOf(mem[sp-1].Int() < mem[sp-2].Int()) + mem[sp-2] = ValueOf(mem[sp-2].Int() < mem[sp-1].Int()) mem = mem[:sp-1] case Loweri: mem[sp-1] = ValueOf(mem[sp-1].Int() < int64(c.Arg[0])) + case Negate: + mem[sp-1] = ValueOf(-mem[sp-1].Int()) case Not: mem[sp-1] = ValueOf(!mem[sp-1].Bool()) case Pop: @@ -234,10 +241,10 @@ func (m *Machine) Run() (err error) { ip = int(mem[fp-2].Int()) ofp := fp fp = int(mem[fp-1].Int()) - mem = append(mem[:ofp-c.Arg[0]-c.Arg[1]-1], mem[sp-c.Arg[0]:]...) + mem = append(mem[:ofp-c.Arg[0]-c.Arg[1]-2], mem[sp-c.Arg[0]:]...) continue case Sub: - mem[sp-2] = ValueOf(int(mem[sp-1].Int() - mem[sp-2].Int())) + mem[sp-2] = ValueOf(int(mem[sp-2].Int() - mem[sp-1].Int())) mem = mem[:sp-1] case Subi: mem[sp-1] = ValueOf(int(mem[sp-1].Int()) - c.Arg[0]) @@ -245,10 +252,11 @@ func (m *Machine) Run() (err error) { a, b := sp-c.Arg[0]-1, sp-c.Arg[1]-1 mem[a], mem[b] = mem[b], mem[a] case Index: - mem[sp-2].Value = mem[sp-1].Index(int(mem[sp-2].Int())) + mem[sp-2].Value = mem[sp-2].Index(int(mem[sp-1].Int())) mem = mem[:sp-1] case Vassign: - mem[sp-1].Set(mem[sp-2].Value) + // mem[sp-1].Set(mem[sp-2].Value) + mem[sp-2].Set(mem[sp-1].Value) mem = mem[:sp-2] } ip++ diff --git a/vm/vm_test.go b/vm/vm_test.go index a968281..950e61e 100644 --- a/vm/vm_test.go +++ b/vm/vm_test.go @@ -69,7 +69,7 @@ var tests = []struct { {Op: Sub}, {Op: Exit}, }, - start: 0, end: 1, mem: "[1]", + start: 0, end: 1, mem: "[-1]", }, { // #02 -- A simple multiplication. code: []Instruction{ {Op: Push, Arg: []int{3}}, @@ -80,16 +80,16 @@ var tests = []struct { start: 0, end: 1, mem: "[6]", }, { // #03 -- lower. code: []Instruction{ - {Op: Push, Arg: []int{3}}, {Op: Push, Arg: []int{2}}, + {Op: Push, Arg: []int{3}}, {Op: Lower}, {Op: Exit}, }, start: 0, end: 1, mem: "[true]", }, { // #04 -- greater. code: []Instruction{ - {Op: Push, Arg: []int{2}}, {Op: Push, Arg: []int{3}}, + {Op: Push, Arg: []int{2}}, {Op: Greater}, {Op: Exit}, }, @@ -153,16 +153,18 @@ var tests = []struct { {Op: Exit}, }, start: 1, end: 3, mem: "[6 <nil>]", -}, { // #12 -- Defining and calling a function in VM. - code: []Instruction{ - {Op: Jump, Arg: []int{3}}, // 0 - {Op: Push, Arg: []int{3}}, // 1 - {Op: Return, Arg: []int{1, 1}}, // 2 - {Op: Push, Arg: []int{1}}, // 3 - {Op: Calli, Arg: []int{1}}, // 4 - {Op: Exit}, // 5 - }, - start: 0, end: 1, mem: "[3]", + /* + }, { // #12 -- Defining and calling a function in VM. + code: []Instruction{ + {Op: Jump, Arg: []int{3}}, // 0 + {Op: Push, Arg: []int{3}}, // 1 + {Op: Return, Arg: []int{1, 1}}, // 2 + {Op: Push, Arg: []int{1}}, // 3 + {Op: Calli, Arg: []int{1}}, // 4 + {Op: Exit}, // 5 + }, + start: 0, end: 1, mem: "[3]", + */ }, { // #13 -- Defining and calling a function in VM. code: []Instruction{ {Op: Jump, Arg: []int{3}}, // 0 @@ -170,7 +172,7 @@ var tests = []struct { {Op: Return, Arg: []int{1, 1}}, // 2 {Op: Push, Arg: []int{1}}, // 3 {Op: Push, Arg: []int{1}}, // 4 - {Op: Call}, // 5 + {Op: Call, Arg: []int{0}}, // 5 {Op: Exit}, // 6 }, start: 0, end: 1, mem: "[3]", @@ -183,56 +185,58 @@ var tests = []struct { {Op: Return, Arg: []int{1, 1}}, // 4 {Op: Push, Arg: []int{1}}, // 5 {Op: Push, Arg: []int{1}}, // 6 - {Op: Call}, // 7 + {Op: Call, Arg: []int{0}}, // 7 {Op: Exit}, // 8 }, - start: 0, end: 1, mem: "[3]", + start: 1, end: 2, mem: "[3]", }, { // #15 -- Fibonacci numbers, hand written. Showcase recursivity. code: []Instruction{ {Op: Jump, Arg: []int{19}}, // 0 - {Op: Push, Arg: []int{2}}, // 2 [2] {Op: Fdup, Arg: []int{-2}}, // 1 [2 i] + {Op: Push, Arg: []int{2}}, // 2 [2] {Op: Lower}, // 3 [true/false] {Op: JumpTrue, Arg: []int{13}}, // 4 [], goto 17 - {Op: Push, Arg: []int{2}}, // 5 [i 2] + {Op: Push, Arg: []int{1}}, // 5 {Op: Fdup, Arg: []int{-2}}, // 6 [i] - {Op: Sub}, // 7 [(i-2)] - {Op: Push, Arg: []int{1}}, // 8 - {Op: Call}, // 9 [fib(i-2)] - {Op: Push, Arg: []int{1}}, // 10 [(i-2) i 1] + {Op: Push, Arg: []int{2}}, // 7 [i 2] + {Op: Sub}, // 8 [(i-2)] + {Op: Call, Arg: []int{1}}, // 9 [fib(i-2)] + {Op: Push, Arg: []int{1}}, // 10 {Op: Fdup, Arg: []int{-2}}, // 11 [fib(i-2) i] - {Op: Sub}, // 12 [(i-2) (i-1)] - {Op: Push, Arg: []int{1}}, // 13 - {Op: Call}, // 14 [fib(i-2) fib(i-1)] + {Op: Push, Arg: []int{1}}, // 12 [(i-2) i 1] + {Op: Sub}, // 13 [(i-2) (i-1)] + {Op: Call, Arg: []int{1}}, // 14 [fib(i-2) fib(i-1)] {Op: Add}, // 15 [fib(i-2)+fib(i-1)] {Op: Return, Arg: []int{1, 1}}, // 16 return i {Op: Fdup, Arg: []int{-2}}, // 17 [i] {Op: Return, Arg: []int{1, 1}}, // 18 return i - {Op: Push, Arg: []int{6}}, // 19 [1] - {Op: Push, Arg: []int{1}}, // 20 - {Op: Call}, // 21 [fib(*1)] + {Op: Push, Arg: []int{1}}, // 19 + {Op: Push, Arg: []int{6}}, // 20 [1] + {Op: Call, Arg: []int{1}}, // 21 [fib(*1)] {Op: Exit}, // 22 }, start: 0, end: 1, mem: "[8]", -}, { // #16 -- Fibonacci with some immediate instructions. - code: []Instruction{ - {Op: Jump, Arg: []int{14}}, // 0 - {Op: Fdup, Arg: []int{-2}}, // 1 [i] - {Op: Loweri, Arg: []int{2}}, // 2 [true/false] - {Op: JumpTrue, Arg: []int{9}}, // 3 [], goto 12 - {Op: Fdup, Arg: []int{-2}}, // 4 [i] - {Op: Subi, Arg: []int{2}}, // 5 [(i-2)] - {Op: Calli, Arg: []int{1}}, // 6 [fib(i-2)] - {Op: Fdup, Arg: []int{-2}}, // 7 [fib(i-2) i] - {Op: Subi, Arg: []int{1}}, // 8 [(i-2) (i-1)] - {Op: Calli, Arg: []int{1}}, // 9 [fib(i-2) fib(i-1)], call 1 - {Op: Add}, // 10 [fib(i-2)+fib(i-1)] - {Op: Return, Arg: []int{1, 1}}, // 11 return i - {Op: Fdup, Arg: []int{-2}}, // 12 [i] - {Op: Return, Arg: []int{1, 1}}, // 13 return i - {Op: Push, Arg: []int{6}}, // 14 [1] - {Op: Calli, Arg: []int{1}}, // 15 [fib(*1)], call 1 - {Op: Exit}, // 16 - }, - start: 0, end: 1, mem: "[8]", + /* + }, { // #16 -- Fibonacci with some immediate instructions. + code: []Instruction{ + {Op: Jump, Arg: []int{14}}, // 0 + {Op: Fdup, Arg: []int{-2}}, // 1 [i] + {Op: Loweri, Arg: []int{2}}, // 2 [true/false] + {Op: JumpTrue, Arg: []int{9}}, // 3 [], goto 12 + {Op: Fdup, Arg: []int{-2}}, // 4 [i] + {Op: Subi, Arg: []int{2}}, // 5 [(i-2)] + {Op: Calli, Arg: []int{1}}, // 6 [fib(i-2)] + {Op: Fdup, Arg: []int{-2}}, // 7 [fib(i-2) i] + {Op: Subi, Arg: []int{1}}, // 8 [(i-2) (i-1)] + {Op: Calli, Arg: []int{1}}, // 9 [fib(i-2) fib(i-1)], call 1 + {Op: Add}, // 10 [fib(i-2)+fib(i-1)] + {Op: Return, Arg: []int{1, 1}}, // 11 return i + {Op: Fdup, Arg: []int{-2}}, // 12 [i] + {Op: Return, Arg: []int{1, 1}}, // 13 return i + {Op: Push, Arg: []int{6}}, // 14 [1] + {Op: Calli, Arg: []int{1}}, // 15 [fib(*1)], call 1 + {Op: Exit}, // 16 + }, + start: 0, end: 1, mem: "[8]", + */ }} |
