12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- package intcode
-
- import (
- "fmt"
- "math"
- )
-
- // VirtualMachine is an IntCode virtual machine.
- type VirtualMachine struct {
- ip int
- opcodes map[int]OpcodeFunc
- Memory []int
- Halted bool
- Input chan int
- Output chan int
- }
-
- // NewVirtualMachine creates a new IntCode virtual machine, initialised
- // to the given slice of memory.
- func NewVirtualMachine(memory []int) *VirtualMachine {
- return &VirtualMachine{
- ip: 0,
- Memory: memory,
- Halted: false,
- Input: make(chan int, 100),
- Output: make(chan int, 100),
- opcodes: map[int]OpcodeFunc{
- 1: AddOpcode,
- 2: MulOpcode,
- 3: ReadOpCode,
- 4: WriteOpCode,
- 5: JumpIfTrueOpCode,
- 6: JumpIfFalseOpCode,
- 7: LessThanOpCode,
- 8: EqualsOpCode,
- 99: HaltOpcode,
- },
- }
- }
-
- // Run repeatedly executes instructions until the VM halts.
- func (vm *VirtualMachine) Run() {
- for !vm.Halted {
- instruction := vm.Memory[vm.ip]
- opcode := instruction % 100
-
- vm.opcodes[opcode](vm, func(pos int) int {
- mode := (instruction / int(math.Pow10(2+pos))) % 10
- switch mode {
- case 0:
- return vm.Memory[vm.Memory[vm.ip+1+pos]]
- case 1:
- return vm.Memory[vm.ip+1+pos]
- default:
- panic(fmt.Sprintf("Unknown parameter mode: %d", mode))
- }
- })
- }
- close(vm.Input)
- close(vm.Output)
- }
-
- // Reset resets the memory to the given slice, and all other state back to its original value.
- func (vm *VirtualMachine) Reset(memory []int) {
- copy(vm.Memory, memory)
- vm.ip = 0
- vm.Halted = false
- vm.Input = make(chan int, 100)
- vm.Output = make(chan int, 100)
- }
|