Copyright | (c) Eric Mertens 2019 |
---|---|
License | ISC |
Maintainer | emertens@gmail.com |
Safe Haskell | Trustworthy |
Language | Haskell2010 |
This Intcode interpreter is defined across multiple Advent of Code days:
- https://adventofcode.com/2019/day/2
- https://adventofcode.com/2019/day/5
- https://adventofcode.com/2019/day/7
- https://adventofcode.com/2019/day/9
This implementation works with the following passes:
- Parse input text file into a list of numbers
- Execute op codes to single-step input/output effects.
- Execute single-stop effects into big-step effects.
- Optional: Evaluate the effect as a function from a list of inputs to list of outputs
Common use modes:
- List functions:
intCodeToList
- Effect interpretation:
new
,run
,Effect
Synopsis
- intCodeToList :: [Int] -> [Int] -> [Int]
- runIO :: Effect -> IO ()
- data Machine = Machine {}
- (!) :: Machine -> Int -> Int
- new :: [Int] -> Machine
- set :: Int -> Int -> Machine -> Machine
- memoryList :: Machine -> [Int]
- data Effect
- run :: Machine -> Effect
- (>>>) :: Effect -> Effect -> Effect
- effectList :: Effect -> [Int] -> [Int]
- followedBy :: Effect -> Effect -> Effect
- feedInput :: [Int] -> Effect -> Effect
- data Step
- step :: Machine -> Step
- data Mode
- data Opcode a
- decode :: Int -> Maybe (Opcode Mode)
- data IntcodeFault = IntcodeFault
Simple interface
Run a given memory image as a list transducer.
Use effectList
when you want to provide a specific Effect
.
Throws: IntcodeFault
when machine faults or too few inputs are provided.
>>>
intCodeToList [3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9] <$> [[0],[10]]
[[0],[1]]
>>>
intCodeToList [3,3,1105,-1,9,1101,0,0,12,4,12,99,1] <$> [[0],[10]]
[[0],[1]]
>>>
:{
>>>
intCodeToList
>>>
[3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
>>>
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,
>>>
999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99]
>>>
<$> [[7],[8],[9]]
>>>
:}
[[999],[1000],[1001]]
runIO :: Effect -> IO () Source #
Run intcode program using stdio.
>>>
runIO (run (new [104,72,104,101,104,108,104,108,104,111,104,33,104,10,99]))
Hello!
Machine state
Construct machine from a list of initial values starting at address 0. Program counter and relative base start at 0.
Update the value stored at a given location in memory.
memoryList :: Machine -> [Int] Source #
Generate a list representation of memory starting from zero. This can get big for sparsely filled memory using large addresses. Returned values start at position 0.
>>>
memoryList (set 8 10 (new [1,2,3]))
[1,2,3,0,0,0,0,0,10]
Effects
Possible effects from running a machine
run :: Machine -> Effect Source #
Big-step semantics of virtual machine.
>>>
run (new [1102,34915192,34915192,7,4,7,99,0])
Output 1219070632396864 Halt
>>>
run (new [3,1,99])
Input <function>
(>>>) :: Effect -> Effect -> Effect infixl 9 Source #
Compose two effects together. Outputs from first argument are used as inputs to the second effect. Composed effect halts when the second machine halts.
>>>
let mult n = Input (\i -> Output (i*n) Halt)
>>>
let add n = Input (\i -> Output (i+n) Halt)
>>>
effectList (mult 3 >>> add 1) [4]
[13]
Evaluate a program's effect as a function from a list of inputs to a list of outputs.
Throws: IntcodeFault
when machine faults or too few inputs are provided.
followedBy :: Effect -> Effect -> Effect Source #
Run first effect until it halts, then run the second effect.
>>>
Output 1 Halt `followedBy` Output 2 Halt
Output 1 (Output 2 Halt)
Provide an input to the first occurence of an input request in a program effect. It is considered a fault if a program terminates before using the input.
>>>
let mult n = Input (\i -> Output (i*n) Halt)
>>>
feedInput [6] (mult 5)
Output 30 Halt
Small-step
Result of small-step semantics.
Opcodes
Opcodes parameterized over argument representations.
Add !a !a !a | addition: |
Mul !a !a !a | multiplication: |
Inp !a | input: |
Out !a | output: |
Jnz !a !a | jump-if-true: |
Jz !a !a | jump-if-false: |
Lt !a !a !a | less-than: |
Eq !a !a !a | equals: |
Arb !a | adjust-rel-base: |
Hlt | halt |
Instances
Functor Opcode Source # | |
Foldable Opcode Source # | |
Defined in Intcode fold :: Monoid m => Opcode m -> m # foldMap :: Monoid m => (a -> m) -> Opcode a -> m # foldr :: (a -> b -> b) -> b -> Opcode a -> b # foldr' :: (a -> b -> b) -> b -> Opcode a -> b # foldl :: (b -> a -> b) -> b -> Opcode a -> b # foldl' :: (b -> a -> b) -> b -> Opcode a -> b # foldr1 :: (a -> a -> a) -> Opcode a -> a # foldl1 :: (a -> a -> a) -> Opcode a -> a # elem :: Eq a => a -> Opcode a -> Bool # maximum :: Ord a => Opcode a -> a # minimum :: Ord a => Opcode a -> a # | |
Traversable Opcode Source # | Arguments visited from left to right. |
Eq a => Eq (Opcode a) Source # | |
Ord a => Ord (Opcode a) Source # | |
Read a => Read (Opcode a) Source # | |
Show a => Show (Opcode a) Source # | |
Decode an instruction to determine the opcode and parameter modes.
>>>
decode 1002
Just (Mul Abs Imm Abs)
Exceptions
data IntcodeFault Source #
Error when a machine fails to step.
Instances
Eq IntcodeFault Source # | |
Defined in Intcode (==) :: IntcodeFault -> IntcodeFault -> Bool # (/=) :: IntcodeFault -> IntcodeFault -> Bool # | |
Ord IntcodeFault Source # | |
Defined in Intcode compare :: IntcodeFault -> IntcodeFault -> Ordering # (<) :: IntcodeFault -> IntcodeFault -> Bool # (<=) :: IntcodeFault -> IntcodeFault -> Bool # (>) :: IntcodeFault -> IntcodeFault -> Bool # (>=) :: IntcodeFault -> IntcodeFault -> Bool # max :: IntcodeFault -> IntcodeFault -> IntcodeFault # min :: IntcodeFault -> IntcodeFault -> IntcodeFault # | |
Read IntcodeFault Source # | |
Defined in Intcode readsPrec :: Int -> ReadS IntcodeFault # readList :: ReadS [IntcodeFault] # | |
Show IntcodeFault Source # | |
Defined in Intcode showsPrec :: Int -> IntcodeFault -> ShowS # show :: IntcodeFault -> String # showList :: [IntcodeFault] -> ShowS # | |
Exception IntcodeFault Source # | |
Defined in Intcode |