-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Advent of Code 2019 intcode interpreter -- -- Implementation of the Intcode virtual machine as defined by Advent of -- Code https://adventofcode.com/2019. -- -- This implementation provides an efficient, pure implementation of the -- interpreter and exposes multiple levels of abstraction to make it easy -- to use in a variety of situations. @package intcode @version 0.3.0.0 -- | The module implements the representation of the intcode machine state. -- -- The Machine type stores the initial memory image in an array -- and only stores changes to that initial image. This allows for more -- efficient comparisons of machine states for equality when there are -- few changes to memory. -- -- This implementation of the machine supports negative memory addresses. -- These are defined not to be used in the Advent of Code problems. -- -- This implementation stores machine-sized Int values in memory. module Intcode.Machine -- | Machine state is comprised of the program counter, relative base -- pointer, and memory. -- -- -- -- Updates to memory are stored separately from the initial values which -- can enable equality comparisons to be relatively efficient. This -- efficiency comes from being able to compare the inital memory using -- only pointer equality when two machines are created by the same call -- to new. data Machine Machine :: !Int -> !Int -> !IntMap Int -> {-# UNPACK #-} !PrimArray Int -> Machine -- | program counter [pc] :: Machine -> !Int -- | relative base pointer [relBase] :: Machine -> !Int -- | memory updates [memUpdates] :: Machine -> !IntMap Int -- | initial memory [memInitial] :: Machine -> {-# UNPACK #-} !PrimArray Int -- | Construct machine from a list of initial values starting at address 0. -- Program counter and relative base start at 0. new :: [Int] -> Machine -- | Set program counter to a new address. jmp :: Int -> Machine -> Machine -- | Add offset to relative base pointer. addRelBase :: Int -> Machine -> Machine -- | Memory lookup. (!) :: Machine -> Int -> Int -- | Store value at given memory position. set :: Int -> Int -> Machine -> Machine -- | 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]
--   
memoryList :: Machine -> [Int] instance GHC.Show.Show Intcode.Machine.Machine instance GHC.Classes.Ord Intcode.Machine.Machine instance GHC.Classes.Eq Intcode.Machine.Machine -- | This module provides a representation of the intcode machine's -- opcodes. -- -- Opcodes are parameterized over their parameters. This allows the -- implementation to store both parameter modes and resolved parameter -- pointers in the same constructors. module Intcode.Opcode -- | Opcodes parameterized over argument representations. data Opcode a -- | addition: c = a + b Add :: !a -> !a -> !a -> Opcode a -- | multiplication: c = a * b Mul :: !a -> !a -> !a -> Opcode a -- | input: a = input() Inp :: !a -> Opcode a -- | output: output(a) Out :: !a -> Opcode a -- | jump-if-true: if a then goto b Jnz :: !a -> !a -> Opcode a -- | jump-if-false: if !a then goto b Jz :: !a -> !a -> Opcode a -- | less-than: c = a < b Lt :: !a -> !a -> !a -> Opcode a -- | equals: c = a == b Eq :: !a -> !a -> !a -> Opcode a -- | adjust-rel-base: rel += a Arb :: !a -> Opcode a -- | halt Hlt :: Opcode a -- | Parameter modes data Mode -- | absolute position Abs :: Mode -- | immediate Imm :: Mode -- | relative position Rel :: Mode -- | Decode an instruction to determine the opcode and parameter modes. -- --
--   >>> decode 1002
--   Just (Mul Abs Imm Abs)
--   
decode :: Int -> Maybe (Opcode Mode) instance Data.Foldable.Foldable Intcode.Opcode.Opcode instance GHC.Base.Functor Intcode.Opcode.Opcode instance GHC.Show.Show a => GHC.Show.Show (Intcode.Opcode.Opcode a) instance GHC.Read.Read a => GHC.Read.Read (Intcode.Opcode.Opcode a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Intcode.Opcode.Opcode a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Intcode.Opcode.Opcode a) instance GHC.Show.Show Intcode.Opcode.Mode instance GHC.Read.Read Intcode.Opcode.Mode instance GHC.Classes.Ord Intcode.Opcode.Mode instance GHC.Classes.Eq Intcode.Opcode.Mode instance Data.Traversable.Traversable Intcode.Opcode.Opcode -- | Intcode is a virtual machine environment defined to have some -- arithmetic, conditional jumps, and simple input and output facilities. -- -- The instruction set is designed with independently selectable address -- modes for each of its input and output parameters. The architecture is -- designed to be simple to implement while powerful enough to write -- interesting programs efficiently. The addition of a relative base -- pointer makes it easy to implement function calls in the language. -- -- This Intcode architecture is defined across multiple Advent of Code -- 2019 tasks: 2, 5, 7, and 9 -- -- Common use modes: -- -- -- -- Submodules: -- -- module Intcode -- | 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]]
--   
intcodeToList :: [Int] -> [Int] -> [Int] -- | Machine state is comprised of the program counter, relative base -- pointer, and memory. -- -- -- -- Updates to memory are stored separately from the initial values which -- can enable equality comparisons to be relatively efficient. This -- efficiency comes from being able to compare the inital memory using -- only pointer equality when two machines are created by the same call -- to new. data Machine -- | Memory lookup. (!) :: Machine -> Int -> Int -- | Construct machine from a list of initial values starting at address 0. -- Program counter and relative base start at 0. new :: [Int] -> Machine -- | Store value at given memory position. set :: Int -> Int -> Machine -> Machine -- | 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]
--   
memoryList :: Machine -> [Int] -- | Possible effects from running a machine data Effect -- | Output an integer Output :: !Int -> Effect -> Effect -- | Input an integer Input :: (Int -> Effect) -> Effect -- | Halt execution Halt :: Effect -- | Execution failure Fault :: Effect -- | Big-step semantics of virtual machine. The implementation details of -- Machine are abstracted away and the program behavior can be -- observed by interpreting the various Effect constructors. -- --
--   >>> run (new [1102,34915192,34915192,7,4,7,99,0])
--   Output 1219070632396864 Halt
--   
-- --
--   >>> run (new [3,1,99])
--   Input <function>
--   
run :: Machine -> Effect -- | 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]
--   
(>>>) :: Effect -> Effect -> Effect infixl 9 >>> -- | Run first effect until it halts, then run the second effect. -- --
--   >>> Output 1 Halt `followedBy` Output 2 Halt
--   Output 1 (Output 2 Halt)
--   
-- --
--   >>> Output 1 Halt `followedBy` Fault
--   Output 1 Fault
--   
-- --
--   >>> Fault `followedBy` undefined
--   Fault
--   
followedBy :: Effect -> Effect -> Effect -- | Provide an input to the first occurrence of an input request in a -- program effect. It is considered a fault if a program terminates -- before using the input. -- --
--   >>> feedInput [5,6] (Input (\x -> Input (\y -> Output (x*y) Halt)))
--   Output 30 Halt
--   
-- --
--   >>> feedInput [7] Halt
--   Fault
--   
feedInput :: [Int] -> Effect -> Effect -- | 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. effectList :: Effect -> [Int] -> [Int] -- | Result of small-step semantics. data Step -- | no effect Step :: !Machine -> Step -- | output StepOut :: !Int -> !Machine -> Step -- | input StepIn :: (Int -> Machine) -> Step -- | halt StepHalt :: Step -- | bad instruction StepFault :: Step -- | Small-step semantics of virtual machine. step :: Machine -> Step -- | Error when a machine fails to decode an instruction. data IntcodeFault IntcodeFault :: IntcodeFault -- | Run intcode program using stdio. Non-ASCII outputs are printed as -- integers. -- -- Note that input and output is affected by handle buffering modes. -- --
--   >>> runIO (run (new [104,72,104,101,104,108,104,108,104,111,104,33,104,10,99]))
--   Hello!
--   
-- --
--   >>> runIO (run (new [104,-50,104,1000,99]))
--   <<-50>>
--   <<1000>>
--   
runIO :: Effect -> IO () -- | runIO generalized to an arbitrary input and output handle. hRunIO :: Handle -> Handle -> Effect -> IO () instance GHC.Read.Read Intcode.IntcodeFault instance GHC.Show.Show Intcode.IntcodeFault instance GHC.Classes.Ord Intcode.IntcodeFault instance GHC.Classes.Eq Intcode.IntcodeFault instance GHC.Show.Show Intcode.Step instance GHC.Show.Show Intcode.Effect instance GHC.Exception.Type.Exception Intcode.IntcodeFault -- | This module implements a parser for the simple comma, separated format -- used in the Advent of Code input files. module Intcode.Parse -- | Parse a list of comma separated integers. -- --
--   >>> parseInts "1, - 2, 3,-4"
--   Just [1,-2,3,-4]
--   
-- --
--   >>> parseInts " "
--   Just []
--   
-- --
--   >>> parseInts "1,2,3,x"
--   Nothing
--   
parseInts :: String -> Maybe [Int]