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.

ops.go 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package intcode
  2. // opcodeFunc is a function that describes an opcode implemented in the VM.
  3. type opcodeFunc = func(vm *VirtualMachine, arg1, arg2, arg3 *int)
  4. var opcodes = [100]opcodeFunc{
  5. 1: addOpcode,
  6. 2: mulOpcode,
  7. 3: readOpCode,
  8. 4: writeOpCode,
  9. 5: jumpIfTrueOpCode,
  10. 6: jumpIfFalseOpCode,
  11. 7: lessThanOpCode,
  12. 8: equalsOpCode,
  13. 9: relativeBaseOffsetOpCode,
  14. 99: haltOpcode,
  15. }
  16. var opcodeArity = [100]int{
  17. 1: 3,
  18. 2: 3,
  19. 3: 1,
  20. 4: 1,
  21. 5: 2,
  22. 6: 2,
  23. 7: 3,
  24. 8: 3,
  25. 9: 1,
  26. 99: 0,
  27. }
  28. // addOpcode takes the values specified by args 1 and 2, adds them together, and stores at the memory address given
  29. // by arg 3.
  30. func addOpcode(vm *VirtualMachine, arg1, arg2, arg3 *int) {
  31. *arg3 = *arg1 + *arg2
  32. vm.ip += 4
  33. }
  34. // mulOpcode takes the values specified by args 1 and 2, multiplies them together, and stores at the memory address
  35. // given by arg 3.
  36. func mulOpcode(vm *VirtualMachine, arg1, arg2, arg3 *int) {
  37. *arg3 = *arg1 * *arg2
  38. vm.ip += 4
  39. }
  40. // readOpCode reads a value from the input stream and stores it at the memory address given by arg 1.
  41. func readOpCode(vm *VirtualMachine, arg1, _, _ *int) {
  42. if vm.inputIndex < len(vm.input) {
  43. // Read from pre-provided values
  44. *arg1 = vm.input[vm.inputIndex]
  45. vm.inputIndex++
  46. } else {
  47. *arg1 = <-vm.Input
  48. }
  49. vm.ip += 2
  50. }
  51. // writeOpCode writes the value specified by the first argument to the output stream.
  52. func writeOpCode(vm *VirtualMachine, arg1, _, _ *int) {
  53. if len(vm.input) > 0 {
  54. // Running to get the value of some input, provide the output and halt
  55. vm.output = arg1
  56. vm.Halted = true
  57. } else {
  58. vm.Output <- *arg1
  59. }
  60. vm.ip += 2
  61. }
  62. // jumpIfTrueOpCode checks if the first argument is not zero, and if so jumps to the second argument.
  63. func jumpIfTrueOpCode(vm *VirtualMachine, arg1, arg2, _ *int) {
  64. if *arg1 != 0 {
  65. vm.ip = *arg2
  66. } else {
  67. vm.ip += 3
  68. }
  69. }
  70. // jumpIfFalseOpCode checks if the first argument is zero, and if so jumps to the second argument.
  71. func jumpIfFalseOpCode(vm *VirtualMachine, arg1, arg2, _ *int) {
  72. if *arg1 == 0 {
  73. vm.ip = *arg2
  74. } else {
  75. vm.ip += 3
  76. }
  77. }
  78. // lessThanOpCode checks if the first argument is less than the second, and stores the result at the address given
  79. // by the third argument.
  80. func lessThanOpCode(vm *VirtualMachine, arg1, arg2, arg3 *int) {
  81. if *arg1 < *arg2 {
  82. *arg3 = 1
  83. } else {
  84. *arg3 = 0
  85. }
  86. vm.ip += 4
  87. }
  88. // equalsOpCode checks if the first argument is equal to the second, and stores the result at the address given
  89. // by the third argument.
  90. func equalsOpCode(vm *VirtualMachine, arg1, arg2, arg3 *int) {
  91. if *arg1 == *arg2 {
  92. *arg3 = 1
  93. } else {
  94. *arg3 = 0
  95. }
  96. vm.ip += 4
  97. }
  98. // relativeBaseOffsetOpCode increases the relative base by the given argument.
  99. func relativeBaseOffsetOpCode(vm *VirtualMachine, arg1, _, _ *int) {
  100. vm.rb += *arg1
  101. vm.ip += 2
  102. }
  103. // haltOpcode halts the VM and takes no arguments.
  104. func haltOpcode(vm *VirtualMachine, _, _, _ *int) {
  105. vm.Halted = true
  106. }