@ -30,17 +30,30 @@ The virtual machine has two registers, @tt{a} and @tt{b}, that both start at 0.
Although the virtual machine has the equivalent of functions & variables, the jump instructions add a complication. We can't just evaluate the instructions top to bottom. We have to maintain a list of all the instructions, and a pointer to where we are, so if we get a jump instruction, we can move to the right place.
Because we have to repeatedly update the values of the register, it'll be more convenient to use a hash table (which is designed for this purpose).
Because we have to repeatedly update the values of the register, it'll be more convenient to use a hash table. Overall, the solution follows the general pattern of @secref{Day_7}.
Notice also that we're encasing the lines of the VM program in @racket[thunk*]. This creates a function wrapper around each instruction so that its evaluation is delayed until we explicitly ask for it. The @racket[inst] transformer turns the lines of the program into equivalent operations on our register hash table. All these functions return a number that indicates the offset of the next instruction (if it's not a jump instruction, then this value is just 1).
@ -49,55 +62,48 @@ Because we have to repeatedly update the values of the register, it'll be more c
(define (jmpf reg num pred)
(if (pred (hash-ref registers reg)) num 1))
(define-syntax (ins stx)
(define-syntax (inst stx)
(syntax-case stx (jmp jio jie)
[(_ jio reg num)
#'(jmpf 'reg num (λ(x) (= 1 x)))]
#'(jmpf 'reg num (curry = 1))]
[(_ jie reg num)
#'(jmpf 'reg num even?)]
[(_ jmp num)
#'num]
[(_ op reg)
#'(op 'reg)]
[else #'(void)]))
(define-syntax (parse-instructions stx)
(syntax-case stx ()
[(_ input-str)
#'(let* ([str (string-replace input-str "," "")]
[lines (string-split str "\n")]
[datums)
42)]))
#'(op 'reg)]))
(convert-input-to-instruction-functions)
]
With the instructions set up as functions, running the program is easy. We start at index 0 and evaluate the first instruction in our list (which will possibly update one of the registers). The result is the offset for the next instruction. We continue until our index exceeds the number of instructions available.