You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vm.go 1.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package intcode
  2. // VirtualMachine is an IntCode virtual machine.
  3. type VirtualMachine struct {
  4. ip int
  5. modes uint8
  6. opcodes [100]interface{}
  7. Memory []int
  8. Halted bool
  9. Input chan int
  10. Output chan int
  11. }
  12. // NewVirtualMachine creates a new IntCode virtual machine, initialised
  13. // to the given slice of memory.
  14. func NewVirtualMachine(memory []int) *VirtualMachine {
  15. return &VirtualMachine{
  16. ip: 0,
  17. Memory: memory,
  18. Halted: false,
  19. Input: make(chan int, 1),
  20. Output: make(chan int, 1),
  21. opcodes: [100]interface{}{
  22. 1: AddOpcode,
  23. 2: MulOpcode,
  24. 3: ReadOpCode,
  25. 4: WriteOpCode,
  26. 5: JumpIfTrueOpCode,
  27. 6: JumpIfFalseOpCode,
  28. 7: LessThanOpCode,
  29. 8: EqualsOpCode,
  30. 99: HaltOpcode,
  31. },
  32. }
  33. }
  34. func (vm *VirtualMachine) arg(pos int) int {
  35. mask := uint8(1) << uint8(pos)
  36. if vm.modes&mask == mask {
  37. return vm.Memory[vm.ip+1+pos]
  38. } else {
  39. return vm.Memory[vm.Memory[vm.ip+1+pos]]
  40. }
  41. }
  42. // Run repeatedly executes instructions until the VM halts.
  43. func (vm *VirtualMachine) Run() {
  44. for !vm.Halted {
  45. instruction := vm.Memory[vm.ip]
  46. opcode := instruction % 100
  47. vm.modes = 0
  48. mask := uint8(1)
  49. for i := instruction / 100; i > 0; i /= 10 {
  50. if i%10 == 1 {
  51. vm.modes = vm.modes | mask
  52. }
  53. mask = mask << 1
  54. }
  55. vm.opcodes[opcode].(OpcodeFunc)(vm)
  56. }
  57. close(vm.Input)
  58. close(vm.Output)
  59. }
  60. // Reset resets the memory to the given slice, and all other state back to its original value.
  61. func (vm *VirtualMachine) Reset(memory []int) {
  62. copy(vm.Memory, memory)
  63. vm.ip = 0
  64. vm.Halted = false
  65. vm.Input = make(chan int, 1)
  66. vm.Output = make(chan int, 1)
  67. }