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() { } } }) } }