{-# Language Safe #-}
module Intcode
(
intcodeToList,
Machine, (!), new, set, memoryList,
Effect(..), run,
effectList,
Step(..), step,
IntcodeFault(..),
runIO, hRunIO,
) where
import Control.Exception (Exception(..), throw, throwIO)
import Data.Char (chr, ord)
import System.IO (Handle, hGetChar, hPutChar, hPutStrLn, stdin, stdout)
import Intcode.Machine (Machine(..), (!), memoryList, new, set)
import Intcode.Step (Step(..), step)
runIO :: Effect -> IO ()
runIO :: Effect -> IO ()
runIO = Handle -> Handle -> Effect -> IO ()
hRunIO Handle
stdin Handle
stdout
hRunIO ::
Handle ->
Handle ->
Effect ->
IO ()
hRunIO :: Handle -> Handle -> Effect -> IO ()
hRunIO Handle
inH Handle
outH = Effect -> IO ()
go
where
go :: Effect -> IO ()
go (Output Int
o Effect
e)
| Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
o, Int
o Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0x80 = Handle -> Char -> IO ()
hPutChar Handle
outH (Int -> Char
chr (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
o)) IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Effect -> IO ()
go Effect
e
| Bool
otherwise = Handle -> String -> IO ()
hPutStrLn Handle
outH (String
"<<" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
o String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
">>") IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Effect -> IO ()
go Effect
e
go (Input Int -> Effect
f) = Effect -> IO ()
go (Effect -> IO ()) -> (Char -> Effect) -> Char -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Effect
f (Int -> Effect) -> (Char -> Int) -> Char -> Effect
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int) -> (Char -> Int) -> Char -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
ord (Char -> IO ()) -> IO Char -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Handle -> IO Char
hGetChar Handle
inH
go Effect
Halt = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
go Effect
Fault = IntcodeFault -> IO ()
forall e a. Exception e => e -> IO a
throwIO IntcodeFault
IntcodeFault
intcodeToList ::
[Int] ->
[Int] ->
[Int]
intcodeToList :: [Int] -> [Int] -> [Int]
intcodeToList = Effect -> [Int] -> [Int]
effectList (Effect -> [Int] -> [Int])
-> ([Int] -> Effect) -> [Int] -> [Int] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Machine -> Effect
run (Machine -> Effect) -> ([Int] -> Machine) -> [Int] -> Effect
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> Machine
new
effectList ::
Effect ->
[Int] ->
[Int]
effectList :: Effect -> [Int] -> [Int]
effectList Effect
effect [Int]
inputs =
case Effect
effect of
Effect
Fault -> IntcodeFault -> [Int]
forall a e. Exception e => e -> a
throw IntcodeFault
IntcodeFault
Effect
Halt -> []
Output Int
o Effect
e -> Int
o Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: Effect -> [Int] -> [Int]
effectList Effect
e [Int]
inputs
Input Int -> Effect
f ->
case [Int]
inputs of
Int
x:[Int]
xs -> Effect -> [Int] -> [Int]
effectList (Int -> Effect
f Int
x) [Int]
xs
[] -> IntcodeFault -> [Int]
forall a e. Exception e => e -> a
throw IntcodeFault
IntcodeFault
data Effect
= Output !Int Effect
| Input (Int -> Effect)
| Halt
| Fault
deriving Int -> Effect -> String -> String
[Effect] -> String -> String
Effect -> String
(Int -> Effect -> String -> String)
-> (Effect -> String)
-> ([Effect] -> String -> String)
-> Show Effect
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Effect -> String -> String
showsPrec :: Int -> Effect -> String -> String
$cshow :: Effect -> String
show :: Effect -> String
$cshowList :: [Effect] -> String -> String
showList :: [Effect] -> String -> String
Show
run :: Machine -> Effect
run :: Machine -> Effect
run Machine
mach =
case Machine -> Step
step Machine
mach of
Step Machine
mach' -> Machine -> Effect
run Machine
mach'
StepOut Int
out Machine
mach' -> Int -> Effect -> Effect
Output Int
out (Machine -> Effect
run Machine
mach')
StepIn Int -> Machine
f -> (Int -> Effect) -> Effect
Input (Machine -> Effect
run (Machine -> Effect) -> (Int -> Machine) -> Int -> Effect
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Machine
f)
Step
StepHalt -> Effect
Halt
Step
StepFault -> Effect
Fault
data IntcodeFault = IntcodeFault
deriving (IntcodeFault -> IntcodeFault -> Bool
(IntcodeFault -> IntcodeFault -> Bool)
-> (IntcodeFault -> IntcodeFault -> Bool) -> Eq IntcodeFault
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: IntcodeFault -> IntcodeFault -> Bool
== :: IntcodeFault -> IntcodeFault -> Bool
$c/= :: IntcodeFault -> IntcodeFault -> Bool
/= :: IntcodeFault -> IntcodeFault -> Bool
Eq, Eq IntcodeFault
Eq IntcodeFault =>
(IntcodeFault -> IntcodeFault -> Ordering)
-> (IntcodeFault -> IntcodeFault -> Bool)
-> (IntcodeFault -> IntcodeFault -> Bool)
-> (IntcodeFault -> IntcodeFault -> Bool)
-> (IntcodeFault -> IntcodeFault -> Bool)
-> (IntcodeFault -> IntcodeFault -> IntcodeFault)
-> (IntcodeFault -> IntcodeFault -> IntcodeFault)
-> Ord IntcodeFault
IntcodeFault -> IntcodeFault -> Bool
IntcodeFault -> IntcodeFault -> Ordering
IntcodeFault -> IntcodeFault -> IntcodeFault
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: IntcodeFault -> IntcodeFault -> Ordering
compare :: IntcodeFault -> IntcodeFault -> Ordering
$c< :: IntcodeFault -> IntcodeFault -> Bool
< :: IntcodeFault -> IntcodeFault -> Bool
$c<= :: IntcodeFault -> IntcodeFault -> Bool
<= :: IntcodeFault -> IntcodeFault -> Bool
$c> :: IntcodeFault -> IntcodeFault -> Bool
> :: IntcodeFault -> IntcodeFault -> Bool
$c>= :: IntcodeFault -> IntcodeFault -> Bool
>= :: IntcodeFault -> IntcodeFault -> Bool
$cmax :: IntcodeFault -> IntcodeFault -> IntcodeFault
max :: IntcodeFault -> IntcodeFault -> IntcodeFault
$cmin :: IntcodeFault -> IntcodeFault -> IntcodeFault
min :: IntcodeFault -> IntcodeFault -> IntcodeFault
Ord, Int -> IntcodeFault -> String -> String
[IntcodeFault] -> String -> String
IntcodeFault -> String
(Int -> IntcodeFault -> String -> String)
-> (IntcodeFault -> String)
-> ([IntcodeFault] -> String -> String)
-> Show IntcodeFault
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> IntcodeFault -> String -> String
showsPrec :: Int -> IntcodeFault -> String -> String
$cshow :: IntcodeFault -> String
show :: IntcodeFault -> String
$cshowList :: [IntcodeFault] -> String -> String
showList :: [IntcodeFault] -> String -> String
Show, ReadPrec [IntcodeFault]
ReadPrec IntcodeFault
Int -> ReadS IntcodeFault
ReadS [IntcodeFault]
(Int -> ReadS IntcodeFault)
-> ReadS [IntcodeFault]
-> ReadPrec IntcodeFault
-> ReadPrec [IntcodeFault]
-> Read IntcodeFault
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS IntcodeFault
readsPrec :: Int -> ReadS IntcodeFault
$creadList :: ReadS [IntcodeFault]
readList :: ReadS [IntcodeFault]
$creadPrec :: ReadPrec IntcodeFault
readPrec :: ReadPrec IntcodeFault
$creadListPrec :: ReadPrec [IntcodeFault]
readListPrec :: ReadPrec [IntcodeFault]
Read)
instance Exception IntcodeFault where
displayException :: IntcodeFault -> String
displayException IntcodeFault
_ = String
"intcode machine fault"