1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
package vm1
import (
"fmt"
"testing"
)
func TestVM(t *testing.T) {
for _, test := range tests {
t.Run("", func(t *testing.T) {
m := &Machine{}
for _, v := range test.sym {
m.Push(v)
}
m.PushCode(test.code)
m.Run()
t.Log(m.mem)
r := fmt.Sprintf("%v", m.mem[test.start:test.end])
if r != test.mem {
t.Errorf("got %v, want %v", r, test.mem)
}
})
}
}
func BenchmarkVM(b *testing.B) {
for _, test := range tests {
test := test
b.Run("", func(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
m := &Machine{}
m.PushCode(test.code)
b.StartTimer()
m.Run()
}
})
}
}
var tests = []struct {
sym []any // initial memory values
code [][]int64 // bytecode to execute
start, end int //
mem string // expected memory content
}{{ // #00 -- A simple addition.
code: [][]int64{
{0, Push, 1},
{0, Push, 2},
{0, Add},
{0, Exit},
},
start: 0, end: 1, mem: "[3]",
}, { // #01 -- Calling a function defined outside the VM.
sym: []any{fmt.Println, "Hello"},
code: [][]int64{
{0, CallX, 1},
{0, Exit},
},
start: 0, end: 2, mem: "[6 <nil>]",
}, { // #02 -- Defining and calling a function in VM.
code: [][]int64{
{0, Jump, 4}, // 0
{0, Enter}, // 1
{0, Push, 3}, // 2
{0, Return, 1}, // 3
{0, Push, 1}, // 4
{0, Call, -4}, // 5
{0, Exit}, // 6
},
start: 0, end: 1, mem: "[3]",
}, { // #03 -- Fibonacci numbers, hand written. Showcase recursivity.
code: [][]int64{
{0, Jump, 18}, // 0, goto 18
{0, Enter}, // 1,
{0, Fdup, -2}, // 2, [i]
{0, Push, 2}, // 3, [i 2]
{0, Lower}, // 4, [true/false]
{0, JumpTrue, 11}, // 5, [], goto 16
{0, Fdup, -2}, // 6 [i]
{0, Push, 2}, // 7 [i 2]
{0, Sub}, // 8 [(i-2)]
{0, Call, -8}, // 9 [fib(i-2)]
{0, Fdup, -2}, // 10 [fib(i-2) i]
{0, Push, 1}, // 11 [(i-2) i 1]
{0, Sub}, // 12 [(i-2) (i-1)]
{0, Call, -12}, // 13 [fib(i-2) fib(i-1)]
{0, Add}, // 14 [fib(i-2)+fib(i-1)]
{0, Return, 1}, // 15 return i
{0, Fdup, -2}, // 16 [i]
{0, Return, 1}, // 17 return i
{0, Push, 6}, // 18 [1]
{0, Call, -18}, // 19 [fib(*1)]
{0, Exit}, // 20
},
start: 0, end: 1, mem: "[8]",
}, { // #04 -- Fibonacci with some immediate instructions.
code: [][]int64{
{0, Jump, 15}, // 0, goto 15
{0, Enter}, // 1,
{0, Fdup, -2}, // 2, [i]
{0, Loweri, 2}, // 3, [true/false]
{0, JumpTrue, 9}, // 4, [], goto 13
{0, Fdup, -2}, // 5 [i]
{0, Subi, 2}, // 6 [(i-2)]
{0, Call, -6}, // 7 [fib(i-2)]
{0, Fdup, -2}, // 8 [fib(i-2) i]
{0, Subi, 1}, // 9 [(i-2) (i-1)]
{0, Call, -9}, // 10 [fib(i-2) fib(i-1)], call 1
{0, Add}, // 11 [fib(i-2)+fib(i-1)]
{0, Return, 1}, // 12 return i
{0, Fdup, -2}, // 13 [i]
{0, Return, 1}, // 14 return i
{0, Push, 6}, // 15 [1]
{0, Call, -15}, // 16 [fib(*1)], call 1
{0, Exit}, // 17
},
start: 0, end: 1, mem: "[8]",
}}
|