about summary refs log tree commit diff
path: root/pkg/lang/vm/text/compiler.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/text/compiler.go')
-rw-r--r--pkg/lang/vm/text/compiler.go55
1 files changed, 26 insertions, 29 deletions
diff --git a/pkg/lang/vm/text/compiler.go b/pkg/lang/vm/text/compiler.go
index 1480171..68889eb 100644
--- a/pkg/lang/vm/text/compiler.go
+++ b/pkg/lang/vm/text/compiler.go
@@ -1,11 +1,9 @@
 package text
 
 import (
-	"encoding/binary"
 	"io"
 	"jinx/pkg/lang/vm/code"
 	"jinx/pkg/libs/source"
-	"math"
 	"strconv"
 	"strings"
 	"unicode"
@@ -30,8 +28,7 @@ func NewCompiler(src io.Reader) *Compiler {
 }
 
 func (cpl *Compiler) Compile() (code.Code, error) {
-	res := []byte{}
-	info := code.NewDebugInfo("unknown file")
+	builder := code.NewBuilder()
 
 	for {
 		_, eof, err := cpl.src.Peek()
@@ -50,22 +47,22 @@ func (cpl *Compiler) Compile() (code.Code, error) {
 
 		cpl.codePos += len(line)
 
-		if line != nil {
-			info.AppendLine(cpl.codePos-1, cpl.src.Loc().Row-1)
-		}
+		builder.AppendRaw(line)
 
-		res = append(res, line...)
+		if len(line) > 0 {
+			builder.AppendLine(cpl.src.Loc().Row - 1)
+		}
 	}
 
-	if err := cpl.linkLabels(res); err != nil {
+	if err := cpl.linkLabels(&builder); err != nil {
 		return code.Code{}, err
 	}
 
-	return code.New(res, info), nil
+	return builder.Build(), nil
 }
 
-func (cpl *Compiler) compileLine() ([]byte, error) {
-	res := []byte{}
+func (cpl *Compiler) compileLine() (code.Raw, error) {
+	builder := code.NewBuilder()
 
 	start, value, err := cpl.splitLine()
 	if err != nil || start == "" {
@@ -93,7 +90,7 @@ func (cpl *Compiler) compileLine() ([]byte, error) {
 		return nil, err
 	}
 
-	res = append(res, byte(op))
+	builder.AppendOp(op)
 
 	// Find the value, of which there is at most one.
 	if value != "" {
@@ -102,10 +99,10 @@ func (cpl *Compiler) compileLine() ([]byte, error) {
 			return nil, err
 		}
 
-		res = append(res, val...)
+		builder.AppendRaw(val)
 	}
 
-	return res, nil
+	return builder.Code(), nil
 }
 
 func (cpl *Compiler) compileOp(str string) (code.Op, error) {
@@ -117,8 +114,8 @@ func (cpl *Compiler) compileOp(str string) (code.Op, error) {
 	return op, nil
 }
 
-func (cpl *Compiler) compileValue(str string) ([]byte, error) {
-	res := make([]byte, 8)
+func (cpl *Compiler) compileValue(str string) (code.Raw, error) {
+	builder := code.NewBuilder()
 
 	// Save label reference.
 	if str[0] == '@' {
@@ -127,38 +124,38 @@ func (cpl *Compiler) compileValue(str string) ([]byte, error) {
 			label: label,
 			at:    cpl.codePos + 1, // +1 to skip the opcode.
 		})
-		return res, nil
+		builder.AppendInt(0)
+		return builder.Code(), nil
 	}
 
 	if unicode.IsDigit(rune(str[0])) || str[0] == '-' {
 		if strings.Contains(str, ".") {
 			val, err := strconv.ParseFloat(str, 64)
 			if err != nil {
-				return res, err
+				return nil, err
 			}
 
-			binary.LittleEndian.PutUint64(res, math.Float64bits(val))
+			builder.AppendFloat(val)
 		} else {
 			val, err := strconv.ParseInt(str, 10, 64)
 			if err != nil {
-				return res, err
+				return nil, err
 			}
 
-			binary.LittleEndian.PutUint64(res, uint64(val))
+			builder.AppendInt(val)
 		}
 
-		return res, nil
+		return builder.Code(), nil
 	}
 
 	if str[0] == '"' {
 		str = strings.Trim(str, "\"")
-		res = []byte(str)
-		res = append(res, 0)
+		builder.AppendString(str)
 
-		return res, nil
+		return builder.Code(), nil
 	}
 
-	return res, ErrInvalidValue{str}
+	return nil, ErrInvalidValue{str}
 }
 
 func (cpl *Compiler) splitLine() (string, string, error) {
@@ -195,14 +192,14 @@ type labelReference struct {
 	at    int
 }
 
-func (cpl *Compiler) linkLabels(code []byte) error {
+func (cpl *Compiler) linkLabels(builder *code.Builder) error {
 	for _, ref := range cpl.labelReferences {
 		pos, ok := cpl.labelPositions[ref.label]
 		if !ok {
 			return ErrUnkonwnLabel{ref.label}
 		}
 
-		binary.LittleEndian.PutUint64(code[ref.at:], uint64(pos))
+		builder.SetInt(ref.at, int64(pos))
 	}
 	return nil
 }