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 := ` add sub ret ` c := text.NewCompiler(strings.NewReader(src)) res, err := c.Compile() require.NoError(t, err) parts := [][]byte{ opBin(code.OpAdd), 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 }