From 144f49d64e3fc11d334900e90d30c8620ca2991b Mon Sep 17 00:00:00 2001 From: Mel Date: Tue, 7 Jun 2022 09:36:27 +0000 Subject: Add builder for VM bytecode --- pkg/lang/vm/text/compiler.go | 55 +++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 29 deletions(-) (limited to 'pkg/lang/vm/text/compiler.go') 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 } -- cgit 1.4.1