Split out the loader from the VM

This commit is contained in:
Ian Gulliver
2021-11-18 19:56:58 -10:00
parent 941939da83
commit 4332632c77
4 changed files with 66 additions and 52 deletions

54
load/load.go Normal file
View File

@@ -0,0 +1,54 @@
package load
import "bytes"
import "github.com/firestuff/subcoding/vm"
import "github.com/lunixbochs/struc"
import "github.com/pkg/errors"
const instructionBytes = 32
func Load(byteCodes [][]byte) ([][]*vm.Instruction, error) {
fncs := [][]*vm.Instruction{}
for i, byteCode := range byteCodes {
instrs, err := loadFunction(byteCode)
if err != nil {
return nil, errors.Wrapf(err, "At function index %d", i)
}
fncs = append(fncs, instrs)
}
return fncs, nil
}
func loadFunction(byteCode []byte) ([]*vm.Instruction, error) {
instrs := []*vm.Instruction{}
for start := 0; start < len(byteCode); start += instructionBytes {
chunk := byteCode[start : start+instructionBytes]
instr, err := loadInstruction(chunk)
if err != nil {
return nil, errors.Wrapf(err, "At byte offset %d", start)
}
instrs = append(instrs, instr)
}
return instrs, nil
}
func loadInstruction(byteCode []byte) (*vm.Instruction, error) {
instr := &vm.Instruction{}
reader := bytes.NewReader(byteCode)
err := struc.Unpack(reader, instr)
if err != nil {
return nil, errors.Wrap(err, "Error decoding instruction")
}
return instr, nil
}

12
test/load_test.go Normal file
View File

@@ -0,0 +1,12 @@
package test
import "testing"
import "github.com/firestuff/subcoding/load"
func TestLoad(t *testing.T) {
_, err := load.Load(nil)
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,10 +1,5 @@
package vm package vm
import "bytes"
import "github.com/lunixbochs/struc"
import "github.com/pkg/errors"
type Instruction struct { type Instruction struct {
OpCode OpCodeType OpCode OpCodeType
Reserved [4]byte Reserved [4]byte
@@ -13,33 +8,3 @@ type Instruction struct {
opHandler opHandler `struc:"skip"` opHandler opHandler `struc:"skip"`
} }
const instructionBytes = 32
func NewInstructionFromByteCode(byteCode []byte) (*Instruction, error) {
instr := &Instruction{}
reader := bytes.NewReader(byteCode)
err := struc.Unpack(reader, instr)
if err != nil {
return nil, errors.Wrap(err, "Error decoding instruction")
}
return instr, nil
}
func NewInstructionsFromByteCode(byteCode []byte) ([]*Instruction, error) {
instrs := []*Instruction{}
for start := 0; start < len(byteCode); start += instructionBytes {
chunk := byteCode[start : start+instructionBytes]
instr, err := NewInstructionFromByteCode(chunk)
if err != nil {
return nil, errors.Wrapf(err, "At byte offset %d", start)
}
instrs = append(instrs, instr)
}
return instrs, nil
}

View File

@@ -2,8 +2,6 @@ package vm
import "fmt" import "fmt"
import "github.com/pkg/errors"
type State struct { type State struct {
running bool running bool
err error err error
@@ -24,21 +22,6 @@ func NewState(functions [][]*Instruction) (*State, error) {
}, nil }, nil
} }
func NewStateFromByteCode(byteCodes [][]byte) (*State, error) {
functions := [][]*Instruction{}
for i, byteCode := range byteCodes {
instrs, err := NewInstructionsFromByteCode(byteCode)
if err != nil {
return nil, errors.Wrapf(err, "At function index %d", i)
}
functions = append(functions, instrs)
}
return NewState(functions)
}
func (state *State) Execute() error { func (state *State) Execute() error {
state.setHandlers() state.setHandlers()
state.call(0) state.call(0)