Catch range errors, add implicit return
This commit is contained in:
67
main.go
67
main.go
@@ -17,6 +17,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const InstructionBytes = 32
|
const InstructionBytes = 32
|
||||||
|
const GlobalMemoryEntries = 16
|
||||||
|
const FunctionMemoryEntries = 16
|
||||||
|
|
||||||
type Operand struct {
|
type Operand struct {
|
||||||
Type OperandType
|
Type OperandType
|
||||||
@@ -39,15 +41,14 @@ type State struct {
|
|||||||
InstructionIndex int64
|
InstructionIndex int64
|
||||||
|
|
||||||
ComparisonResult bool
|
ComparisonResult bool
|
||||||
GlobalMemory [16]uint64
|
GlobalMemory [GlobalMemoryEntries]uint64
|
||||||
Stack []*StackFrame
|
Stack []*StackFrame
|
||||||
StackFrame *StackFrame
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type StackFrame struct {
|
type StackFrame struct {
|
||||||
PreviousFunctionIndex int64
|
PreviousFunctionIndex int64
|
||||||
PreviousInstructionIndex int64
|
PreviousInstructionIndex int64
|
||||||
FunctionMemory [16]uint64
|
FunctionMemory [FunctionMemoryEntries]uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
type OpHandler func(*State, *Instruction)
|
type OpHandler func(*State, *Instruction)
|
||||||
@@ -86,15 +87,26 @@ func NewState(functionByteCode [][]byte) *State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (state *State) StackFrame() *StackFrame {
|
||||||
|
return state.Stack[len(state.Stack) - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *State) Function() []byte {
|
||||||
|
return state.FunctionByteCode[state.FunctionIndex]
|
||||||
|
}
|
||||||
|
|
||||||
func (state *State) Execute() {
|
func (state *State) Execute() {
|
||||||
state.call(0)
|
state.call(0)
|
||||||
|
|
||||||
for len(state.Stack) > 0 && state.Error == nil {
|
for len(state.Stack) > 0 && state.Error == nil {
|
||||||
fnc := state.FunctionByteCode[state.FunctionIndex]
|
|
||||||
start := state.InstructionIndex * InstructionBytes
|
start := state.InstructionIndex * InstructionBytes
|
||||||
chunk := fnc[start : start+InstructionBytes]
|
chunk := state.Function()[start : start+InstructionBytes]
|
||||||
state.InstructionIndex += 1
|
state.InstructionIndex += 1
|
||||||
state.ProcessInstruction(chunk)
|
state.ProcessInstruction(chunk)
|
||||||
|
|
||||||
|
if state.InstructionIndex >= int64(len(state.Function()) / InstructionBytes) {
|
||||||
|
state.ret()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.Error != nil {
|
if state.Error != nil {
|
||||||
@@ -128,10 +140,21 @@ func (state *State) ReadUnsigned(op *Operand) uint64 {
|
|||||||
switch op.Type {
|
switch op.Type {
|
||||||
case Literal:
|
case Literal:
|
||||||
return op.Value
|
return op.Value
|
||||||
|
|
||||||
case FunctionMemoryIndex:
|
case FunctionMemoryIndex:
|
||||||
return state.StackFrame.FunctionMemory[op.Value]
|
if op.Value >= FunctionMemoryEntries {
|
||||||
|
state.Error = fmt.Errorf("Invalid function memory index: %016x", op.Value)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return state.StackFrame().FunctionMemory[op.Value]
|
||||||
|
|
||||||
case GlobalMemoryIndex:
|
case GlobalMemoryIndex:
|
||||||
|
if op.Value >= GlobalMemoryEntries {
|
||||||
|
state.Error = fmt.Errorf("Invalid global memory index: %016x", op.Value)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
return state.GlobalMemory[op.Value]
|
return state.GlobalMemory[op.Value]
|
||||||
|
|
||||||
default:
|
default:
|
||||||
state.Error = fmt.Errorf("Unknown operand type: 0x%02x", op.Type)
|
state.Error = fmt.Errorf("Unknown operand type: 0x%02x", op.Type)
|
||||||
return 0
|
return 0
|
||||||
@@ -146,10 +169,21 @@ func (state *State) WriteUnsigned(op *Operand, value uint64) {
|
|||||||
switch op.Type {
|
switch op.Type {
|
||||||
case Literal:
|
case Literal:
|
||||||
state.Error = fmt.Errorf("Write to literal operand")
|
state.Error = fmt.Errorf("Write to literal operand")
|
||||||
|
|
||||||
case FunctionMemoryIndex:
|
case FunctionMemoryIndex:
|
||||||
state.StackFrame.FunctionMemory[op.Value] = value
|
if op.Value >= FunctionMemoryEntries {
|
||||||
|
state.Error = fmt.Errorf("Invalid function memory index: %016x", op.Value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.StackFrame().FunctionMemory[op.Value] = value
|
||||||
|
|
||||||
case GlobalMemoryIndex:
|
case GlobalMemoryIndex:
|
||||||
|
if op.Value >= GlobalMemoryEntries {
|
||||||
|
state.Error = fmt.Errorf("Invalid global memory index: %016x", op.Value)
|
||||||
|
return
|
||||||
|
}
|
||||||
state.GlobalMemory[op.Value] = value
|
state.GlobalMemory[op.Value] = value
|
||||||
|
|
||||||
default:
|
default:
|
||||||
state.Error = fmt.Errorf("Unknown operand type: 0x%02x", op.Type)
|
state.Error = fmt.Errorf("Unknown operand type: 0x%02x", op.Type)
|
||||||
}
|
}
|
||||||
@@ -170,24 +204,29 @@ func (state *State) Call(instr *Instruction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (state *State) call(functionOffset int64) {
|
func (state *State) call(functionOffset int64) {
|
||||||
|
if state.FunctionIndex + functionOffset >= int64(len(state.FunctionByteCode)) {
|
||||||
|
state.Error = fmt.Errorf("Invalid function call index: %d + %d = %d", state.FunctionIndex, functionOffset, state.FunctionIndex + functionOffset)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
stackFrame := &StackFrame{
|
stackFrame := &StackFrame{
|
||||||
PreviousFunctionIndex: state.FunctionIndex,
|
PreviousFunctionIndex: state.FunctionIndex,
|
||||||
PreviousInstructionIndex: state.InstructionIndex,
|
PreviousInstructionIndex: state.InstructionIndex,
|
||||||
}
|
}
|
||||||
state.Stack = append(state.Stack, stackFrame)
|
state.Stack = append(state.Stack, stackFrame)
|
||||||
state.StackFrame = stackFrame
|
|
||||||
state.FunctionIndex += functionOffset
|
state.FunctionIndex += functionOffset
|
||||||
state.InstructionIndex = 0
|
state.InstructionIndex = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *State) Return(instr *Instruction) {
|
func (state *State) Return(instr *Instruction) {
|
||||||
fmt.Printf("Return\n")
|
fmt.Printf("Return\n")
|
||||||
state.FunctionIndex = state.StackFrame.PreviousFunctionIndex
|
state.ret()
|
||||||
state.InstructionIndex = state.StackFrame.PreviousInstructionIndex
|
}
|
||||||
|
|
||||||
|
func (state *State) ret() {
|
||||||
|
state.FunctionIndex = state.StackFrame().PreviousFunctionIndex
|
||||||
|
state.InstructionIndex = state.StackFrame().PreviousInstructionIndex
|
||||||
state.Stack = state.Stack[:len(state.Stack)-1]
|
state.Stack = state.Stack[:len(state.Stack)-1]
|
||||||
if len(state.Stack) > 0 {
|
|
||||||
state.StackFrame = state.Stack[len(state.Stack)-1]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *State) Move(instr *Instruction) {
|
func (state *State) Move(instr *Instruction) {
|
||||||
@@ -321,11 +360,9 @@ func main() {
|
|||||||
"0000000100000000000000000000000000000001000000000000000000000000",
|
"0000000100000000000000000000000000000001000000000000000000000000",
|
||||||
"0000030100000000010000000000000000000000000000000000000000000003",
|
"0000030100000000010000000000000000000000000000000000000000000003",
|
||||||
"000004010000000000000000fffffffffffffffd000000000000000000000000",
|
"000004010000000000000000fffffffffffffffd000000000000000000000000",
|
||||||
"0000000200000000000000000000000000000000000000000000000000000000",
|
|
||||||
},
|
},
|
||||||
[]string{
|
[]string{
|
||||||
"0000020000000000020000000000000000000000000000000000000000000001",
|
"0000020000000000020000000000000000000000000000000000000000000001",
|
||||||
"0000000200000000000000000000000000000000000000000000000000000000",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user