-- 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. -- --
-- >>> 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: -- --
-- >>> 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.
--
-- -- >>> 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]