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.

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