From 3abe18ffca484efc3553aa4ec9cb677eb19cdaf4 Mon Sep 17 00:00:00 2001 From: Mel Date: Wed, 18 May 2022 01:37:09 +0200 Subject: Create compiler for Lang bytecode assembly --- pkg/lang/vm/text/compiler_test.go | 164 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 pkg/lang/vm/text/compiler_test.go (limited to 'pkg/lang/vm/text/compiler_test.go') diff --git a/pkg/lang/vm/text/compiler_test.go b/pkg/lang/vm/text/compiler_test.go new file mode 100644 index 0000000..cf2f6a9 --- /dev/null +++ b/pkg/lang/vm/text/compiler_test.go @@ -0,0 +1,164 @@ +package text_test + +import ( + "encoding/binary" + "jinx/pkg/lang/vm/code" + "jinx/pkg/lang/vm/text" + "math" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSimple(t *testing.T) { + src := ` + get_arg + get_arg + sub + ret + ` + + c := text.NewCompiler(strings.NewReader(src)) + res, err := c.Compile() + require.NoError(t, err) + + parts := [][]byte{ + opBin(code.OpGetArg), + opBin(code.OpGetArg), + opBin(code.OpSub), + opBin(code.OpRet), + } + + require.Equal(t, joinSlices(parts), res.Code()) +} + +func TestInt(t *testing.T) { + src := ` + push_int 1 + push_int 2 + add + ret + ` + + c := text.NewCompiler(strings.NewReader(src)) + res, err := c.Compile() + require.NoError(t, err) + + parts := [][]byte{ + opBin(code.OpPushInt), + uintBin(1), + opBin(code.OpPushInt), + uintBin(2), + opBin(code.OpAdd), + opBin(code.OpRet), + } + + require.Equal(t, joinSlices(parts), res.Code()) +} + +func TestFloat(t *testing.T) { + src := ` + push_float 3.1415 + push_float -2.71828 + ` + + c := text.NewCompiler(strings.NewReader(src)) + res, err := c.Compile() + require.NoError(t, err) + + parts := [][]byte{ + opBin(code.OpPushFloat), + floatBin(3.1415), + opBin(code.OpPushFloat), + floatBin(-2.71828), + } + + require.Equal(t, joinSlices(parts), res.Code()) +} + +func TestString(t *testing.T) { + src := ` + push_string "Hello, " + push_string "world!" + add + ` + + c := text.NewCompiler(strings.NewReader(src)) + res, err := c.Compile() + require.NoError(t, err) + + parts := [][]byte{ + opBin(code.OpPushString), + stringBin("Hello, "), + opBin(code.OpPushString), + stringBin("world!"), + opBin(code.OpAdd), + } + + require.Equal(t, joinSlices(parts), res.Code()) +} + +func TestLabels(t *testing.T) { + src := ` + @1: + nop + @2: + nop + @3: + nop + jmp @1 + jmp @2 + jmp @3 + ` + + c := text.NewCompiler(strings.NewReader(src)) + res, err := c.Compile() + require.NoError(t, err) + + parts := [][]byte{ + opBin(code.OpNop), + opBin(code.OpNop), + opBin(code.OpNop), + opBin(code.OpJmp), + uintBin(0), + opBin(code.OpJmp), + uintBin(1), + opBin(code.OpJmp), + uintBin(2), + } + + require.Equal(t, joinSlices(parts), res.Code()) +} + +func opBin(op code.Op) []byte { + return []byte{byte(op)} +} + +func uintBin(x uint64) []byte { + res := make([]byte, 8) + binary.LittleEndian.PutUint64(res, x) + return res +} + +func floatBin(x float64) []byte { + res := make([]byte, 8) + binary.LittleEndian.PutUint64(res, math.Float64bits(x)) + return res +} + +func stringBin(x string) []byte { + res := []byte(x) + res = append(res, 0) + return res +} + +func joinSlices[T any](slices [][]T) []T { + res := []T{} + + for _, slice := range slices { + res = append(res, slice...) + } + + return res +} -- cgit 1.4.1