diff --git a/hal/instructions.go b/hal/instructions.go index 3e43777..4aa198e 100644 --- a/hal/instructions.go +++ b/hal/instructions.go @@ -1,6 +1,7 @@ package hal import ( + "fmt" "strings" ) @@ -9,20 +10,20 @@ type ProgrammedInstruction struct { Operand float64 } -func (pi *ProgrammedInstruction) Execute(module *Module) { +func (pi *ProgrammedInstruction) Execute(module *Module) error { if pi.Instruction.ExecuteWithOperand != nil { - pi.Instruction.ExecuteWithOperand(module, pi.Operand) + return pi.Instruction.ExecuteWithOperand(module, pi.Operand) } else if pi.Instruction.Execute != nil { - pi.Instruction.Execute(module) + return pi.Instruction.Execute(module) } else { - panic("instruction is not implemented") + return fmt.Errorf("instruction is not implemented") } } type Instruction struct { Name string - ExecuteWithOperand func(module *Module, operand float64) - Execute func(module *Module) + ExecuteWithOperand func(module *Module, operand float64) error + Execute func(module *Module) error } func FindInstructionByName(name string) *Instruction { @@ -43,29 +44,87 @@ var instructions = []*Instruction{ var InstructionStart = &Instruction{ Name: "START", - Execute: func(module *Module) { + Execute: func(module *Module) error { // actually not required module.isStopped = false + return nil }, } var InstructionStop = &Instruction{ Name: "STOP", - Execute: func(module *Module) { + Execute: func(module *Module) error { module.isStopped = true + return nil }, } var InstructionOut = &Instruction{ Name: "OUT", - ExecuteWithOperand: func(module *Module, operand float64) { + ExecuteWithOperand: func(module *Module, operand float64) error { + index := int(operand) + if len(module.IO) >= index { + return fmt.Errorf("index %d exceeds IO size of %d", index, len(module.IO)) + } module.IO[int64(operand)] = module.accumulator + return nil }, } var InstructionIn = &Instruction{ Name: "IN", - Execute: func(module *Module) { - // TODO implement + ExecuteWithOperand: func(module *Module, operand float64) error { + index := int(operand) + if len(module.IO) >= index { + return fmt.Errorf("index %d exceeds IO size of %d", index, len(module.IO)) + } + module.accumulator = module.IO[index] + return nil + }, +} + +var InstructionLoad = &Instruction{ + Name: "LOAD", + ExecuteWithOperand: func(module *Module, operand float64) error { + index := int(operand) + if len(module.register) >= index { + return fmt.Errorf("index %d exceeds register size of %d", index, len(module.IO)) + } + module.accumulator = module.register[index] + return nil + }, +} + +var InstructionLoadNum = &Instruction{ + Name: "LOADNUM", + ExecuteWithOperand: func(module *Module, operand float64) error { + module.accumulator = operand + return nil + }, +} + +var InstructionStore = &Instruction{ + Name: "STORE", + ExecuteWithOperand: func(module *Module, operand float64) error { + index := int(operand) + if len(module.register) >= index { + return fmt.Errorf("index %d exceeds register size of %d", index, len(module.IO)) + } + module.register[index] = module.accumulator + return nil + }, +} + +var InstructionJumpNeg = &Instruction{ + Name: "JUMPNEG", + ExecuteWithOperand: func(module *Module, operand float64) error { + index := int64(operand) + if _, ok := module.programStorage[index]; !ok { + return fmt.Errorf("index %d does not exist in program storage", index) + } + if module.accumulator < 0 { + return module.setProgramCounter(index) + } + return nil }, } diff --git a/hal/module.go b/hal/module.go index 04b1db8..f8597d4 100644 --- a/hal/module.go +++ b/hal/module.go @@ -14,16 +14,23 @@ type Module struct { isStopped bool } -func (h *Module) ProgramCounter() int64 { +func (h *Module) programCounter() int64 { return int64(h.register[0]) } +func (h *Module) setProgramCounter(counter int64) error { + h.register[0] = float64(counter) + if _, ok := h.programStorage[counter]; !ok { + return fmt.Errorf("index %d does not exist in program storage", counter) + } + return nil +} func (h *Module) increaseProgramCounter() { h.register[0]++ } func (h *Module) Step() { - instruction := h.programStorage[h.ProgramCounter()] + instruction := h.programStorage[h.programCounter()] h.increaseProgramCounter() if instruction == nil { return @@ -32,10 +39,10 @@ func (h *Module) Step() { } func (h *Module) Run() error { - for !h.isStopped && h.ProgramCounter() <= maxInstructions { + for !h.isStopped && h.programCounter() <= maxInstructions { h.Step() } - if h.ProgramCounter() > maxInstructions { + if h.programCounter() > maxInstructions { return fmt.Errorf("module exceeded max instructions without being stopped") } return nil