139 lines
2.6 KiB
Go
139 lines
2.6 KiB
Go
package core
|
|
|
|
import (
|
|
"math/big"
|
|
"testing"
|
|
)
|
|
|
|
type AllTestCase struct {
|
|
src string
|
|
expectedStack []Value
|
|
expectedScope []map[string]Value
|
|
}
|
|
|
|
func GetAllTestCases() map[string]AllTestCase {
|
|
return map[string]AllTestCase{
|
|
"constant_number": {
|
|
"a := 1\na",
|
|
[]Value{&IntegerValue{new(big.Int).SetInt64(1)}},
|
|
[]map[string]Value{},
|
|
},
|
|
"func": {
|
|
"fn sum(a: int, b: int) -> int {\n\treturn a + b\n}\nres := sum(1, 2)",
|
|
[]Value{&IntegerValue{new(big.Int).SetInt64(3)}},
|
|
[]map[string]Value{},
|
|
},
|
|
"list": {
|
|
"a := [1.0, 2.0]\na",
|
|
[]Value{&ListValue{
|
|
[]Value{
|
|
&FloatValue{1},
|
|
&FloatValue{2},
|
|
},
|
|
}},
|
|
[]map[string]Value{},
|
|
},
|
|
"constant_list_concat": {
|
|
"a := [1, 2] + [3]\na",
|
|
[]Value{&ListValue{
|
|
[]Value{
|
|
&IntegerValue{big.NewInt(1)},
|
|
&IntegerValue{big.NewInt(2)},
|
|
&IntegerValue{big.NewInt(3)},
|
|
},
|
|
}},
|
|
[]map[string]Value{},
|
|
},
|
|
"list_concat": {
|
|
"a := [1.0, 2.0]\na + [3.0]",
|
|
[]Value{&ListValue{
|
|
[]Value{
|
|
&FloatValue{1},
|
|
&FloatValue{2},
|
|
&FloatValue{3},
|
|
},
|
|
}},
|
|
[]map[string]Value{},
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestAll(t *testing.T) {
|
|
cases := GetAllTestCases()
|
|
|
|
for name, tc := range cases {
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Logf("Initializing lexer")
|
|
l := NewLexer(tc.src)
|
|
|
|
t.Logf("Lexing tokens")
|
|
tokens, err := l.Tokenize()
|
|
|
|
if err != nil {
|
|
t.Fatalf("Unexpeced error tokenizing: %v", err)
|
|
}
|
|
|
|
t.Log("Initializing parser")
|
|
p := NewParser(tc.src, []string{}, tokens)
|
|
|
|
t.Log("Parsing tokens")
|
|
tree, err := p.Parse(tc.src)
|
|
|
|
if err != nil {
|
|
print(err.(ParsingError).Format())
|
|
t.Fatalf("parser had an error")
|
|
}
|
|
|
|
t.Log("Initializing compiler")
|
|
c := NewCompiler([]rune(tc.src))
|
|
|
|
t.Log("Compiling parse tree")
|
|
_, err = c.Compile(tree)
|
|
if err != nil {
|
|
t.Fatalf("Compiler had an error: %s", err)
|
|
}
|
|
|
|
printChunk(t, name, c.Chunk)
|
|
|
|
t.Log("Initializing vm")
|
|
vm := NewVM(c.Chunk, 256, 256)
|
|
|
|
t.Log("Running bytecode")
|
|
for vm.Next() {
|
|
}
|
|
|
|
t.Log("Comparing stacks")
|
|
|
|
CompareStacks(t, tc.expectedStack, vm.Stack)
|
|
|
|
// expected scope == nil => we don't care
|
|
if tc.expectedScope != nil {
|
|
CompareScope(t, tc.expectedScope, vm.scope)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkAll(b *testing.B) {
|
|
cases := GetAllTestCases()
|
|
|
|
for name, tc := range cases {
|
|
b.Run(name, func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
l := NewLexer(tc.src)
|
|
tokens, _ := l.Tokenize()
|
|
|
|
p := NewParser(tc.src, []string{}, tokens)
|
|
tree, _ := p.Parse(tc.src)
|
|
|
|
c := NewCompiler([]rune(tc.src))
|
|
_, _ = c.Compile(tree)
|
|
|
|
vm := NewVM(c.Chunk, 256, 256)
|
|
|
|
for vm.Next() {
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|