package compiler_test import ( "fmt" "jinx/pkg/lang/compiler" "jinx/pkg/lang/parser" "jinx/pkg/lang/scanner" "jinx/pkg/lang/vm/text" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestSimpleAddExpr(t *testing.T) { src := ` 1 + 2 ` expected := ` push_int 2 push_int 1 add ` mustCompileTo(t, src, expected) } func TestOperationOrder(t *testing.T) { grouped := ` (((1 + 2) - 3) + 4) ` free := ` 1 + 2 - 3 + 4 ` expected := ` push_int 4 push_int 3 push_int 2 push_int 1 add sub add ` mustCompileTo(t, grouped, expected) mustCompileTo(t, free, expected) } func TestNestedExpr(t *testing.T) { // Yeah, we don't compile identifiers yet, so here we call and index directly on literals. src := ` 1 + 2 - 3 - (123("a", "b", "c") + 456[321]) ` expected := ` push_int 321 push_int 456 index push_string "c" push_string "b" push_string "a" push_int 123 call 3 add push_int 3 push_int 2 push_int 1 add sub sub ` mustCompileTo(t, src, expected) } func mustCompileTo(t *testing.T, src, expected string) { scanner := scanner.New(strings.NewReader(src)) tokens, err := scanner.Scan() require.NoError(t, err) parser := parser.New(tokens) program, err := parser.Parse() require.NoError(t, err) // spew.Dump(program) fmt.Printf("%#v\n", program) langCompiler := compiler.New(program) testResult, err := langCompiler.Compile() require.NoError(t, err) textCompiler := text.NewCompiler(strings.NewReader(expected)) expectedResult, err := textCompiler.Compile() require.NoError(t, err) if !assert.Equal(t, expectedResult.Code(), testResult.Code()) { d1 := text.NewDecompiler(expectedResult) d2 := text.NewDecompiler(testResult) require.Equal(t, d1.Decompile(), d2.Decompile()) } }