Full test (which fails)
This commit is contained in:
@@ -27,4 +27,8 @@ functions:
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if state.GlobalMemory().MustReadUnsigned(0) != 3 {
|
||||
t.Fatalf("Expected 3, found %d\n", state.GlobalMemory().MustReadUnsigned(0))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,5 @@ func NewInstructionsFromByteCode(byteCode []byte) ([]*Instruction, error) {
|
||||
instrs = append(instrs, instr)
|
||||
}
|
||||
|
||||
if len(instrs) == 0 || instrs[len(instrs)-1].OpCode != OpReturn {
|
||||
// Add implicit return at the end of each function
|
||||
instrs = append(instrs, &Instruction{
|
||||
OpCode: OpReturn,
|
||||
})
|
||||
}
|
||||
|
||||
return instrs, nil
|
||||
}
|
||||
|
||||
14
vm/memory.go
14
vm/memory.go
@@ -2,17 +2,17 @@ package vm
|
||||
|
||||
import "fmt"
|
||||
|
||||
type memory struct {
|
||||
type Memory struct {
|
||||
entries []uint64
|
||||
}
|
||||
|
||||
func newMemory(size uint64) *memory {
|
||||
return &memory{
|
||||
func NewMemory(size uint64) *Memory {
|
||||
return &Memory{
|
||||
entries: make([]uint64, size),
|
||||
}
|
||||
}
|
||||
|
||||
func (mem *memory) readUnsigned(index uint64) (uint64, error) {
|
||||
func (mem *Memory) ReadUnsigned(index uint64) (uint64, error) {
|
||||
if index >= uint64(len(mem.entries)) {
|
||||
return 0, fmt.Errorf("Invalid memory index: %016x", index)
|
||||
}
|
||||
@@ -20,15 +20,15 @@ func (mem *memory) readUnsigned(index uint64) (uint64, error) {
|
||||
return mem.entries[index], nil
|
||||
}
|
||||
|
||||
func (mem *memory) mustReadUnsigned(index uint64) uint64 {
|
||||
value, err := mem.readUnsigned(index)
|
||||
func (mem *Memory) MustReadUnsigned(index uint64) uint64 {
|
||||
value, err := mem.ReadUnsigned(index)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (mem *memory) writeUnsigned(index uint64, value uint64) error {
|
||||
func (mem *Memory) WriteUnsigned(index uint64, value uint64) error {
|
||||
if index >= uint64(len(mem.entries)) {
|
||||
return fmt.Errorf("Invalid memory index: %016x", index)
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@ package vm
|
||||
type stackFrame struct {
|
||||
previousFunctionIndex int64
|
||||
previousInstructionIndex int64
|
||||
functionMemory *memory
|
||||
functionMemory *Memory
|
||||
}
|
||||
|
||||
func newStackFrame(state *State) *stackFrame {
|
||||
return &stackFrame{
|
||||
previousFunctionIndex: state.functionIndex,
|
||||
previousInstructionIndex: state.instructionIndex,
|
||||
functionMemory: newMemory(16),
|
||||
functionMemory: NewMemory(16),
|
||||
}
|
||||
}
|
||||
|
||||
20
vm/state.go
20
vm/state.go
@@ -13,14 +13,14 @@ type State struct {
|
||||
instructionIndex int64
|
||||
|
||||
comparisonResult bool
|
||||
globalMemory *memory
|
||||
globalMemory *Memory
|
||||
stack []*stackFrame
|
||||
}
|
||||
|
||||
func NewState(functions [][]*Instruction) (*State, error) {
|
||||
return &State{
|
||||
functions: functions,
|
||||
globalMemory: newMemory(16),
|
||||
globalMemory: NewMemory(16),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -51,6 +51,10 @@ func (state *State) Execute() error {
|
||||
return state.err
|
||||
}
|
||||
|
||||
func (state *State) GlobalMemory() *Memory {
|
||||
return state.globalMemory
|
||||
}
|
||||
|
||||
func (state *State) stackFrame() *stackFrame {
|
||||
return state.stack[len(state.stack)-1]
|
||||
}
|
||||
@@ -83,6 +87,10 @@ func (state *State) processInstruction() {
|
||||
instr := fnc[state.instructionIndex]
|
||||
state.instructionIndex += 1
|
||||
instr.opHandler(state, instr)
|
||||
|
||||
if state.instructionIndex >= int64(len(fnc)) {
|
||||
state.ret()
|
||||
}
|
||||
}
|
||||
|
||||
func (state *State) readUnsigned(op *Operand) uint64 {
|
||||
@@ -91,14 +99,14 @@ func (state *State) readUnsigned(op *Operand) uint64 {
|
||||
return op.Value
|
||||
|
||||
case FunctionMemoryIndex:
|
||||
value, err := state.stackFrame().functionMemory.readUnsigned(op.Value)
|
||||
value, err := state.stackFrame().functionMemory.ReadUnsigned(op.Value)
|
||||
if err != nil {
|
||||
state.setError(err)
|
||||
}
|
||||
return value
|
||||
|
||||
case GlobalMemoryIndex:
|
||||
value, err := state.globalMemory.readUnsigned(op.Value)
|
||||
value, err := state.globalMemory.ReadUnsigned(op.Value)
|
||||
if err != nil {
|
||||
state.setError(err)
|
||||
}
|
||||
@@ -120,13 +128,13 @@ func (state *State) writeUnsigned(op *Operand, value uint64) {
|
||||
state.setError(fmt.Errorf("Write to literal operand"))
|
||||
|
||||
case FunctionMemoryIndex:
|
||||
err := state.stackFrame().functionMemory.writeUnsigned(op.Value, value)
|
||||
err := state.stackFrame().functionMemory.WriteUnsigned(op.Value, value)
|
||||
if err != nil {
|
||||
state.setError(err)
|
||||
}
|
||||
|
||||
case GlobalMemoryIndex:
|
||||
err := state.globalMemory.writeUnsigned(op.Value, value)
|
||||
err := state.globalMemory.WriteUnsigned(op.Value, value)
|
||||
if err != nil {
|
||||
state.setError(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user