zot-0.0.2: src/Zot.hs
module Zot ( main, mainFile ) where
import Control.Monad ( foldM )
data Fun = Fun ( Fun -> IO Fun ) | Zero | One
mkFun :: ( Fun -> Fun ) -> Fun
mkFun f = Fun $ return . f
instance Show Fun where
show Zero = "0"
show One = "1"
show ( Fun _ ) = "function"
showList fs = ( concatMap show fs ++ )
instance Read Fun where
readsPrec _ ( '0' : rest ) = [ ( Zero, rest ) ]
readsPrec _ ( '1' : rest ) = [ ( One, rest ) ]
readsPrec _ _ = error "read Fun failed"
readList str = [ readl str ]
where
readl "" = ( [ ], "" )
readl ( '0' : cs ) = let ( r, rest ) = readl cs in
( Zero : r, rest )
readl ( '1' : cs ) = let ( r, rest ) = readl cs in
( One : r, rest )
readl _ = error "read [ Fun ] failed"
( $$ ) :: Fun -> Fun -> IO Fun
( $$ ) ( Fun f ) = f
( $$ ) Zero = ( zero $$ )
( $$ ) One = ( one $$ )
infixl 6 >$$
( >$$ ) :: IO Fun -> Fun -> IO Fun
f >$$ a = f >>= ( $$ a )
infixr 8 $$<
( $$< ) :: Fun -> IO Fun -> IO Fun
f $$< a = ( f $$ ) =<< a
infixl 7 >$$<
( >$$< ) :: IO Fun -> IO Fun -> IO Fun
f >$$< a = f >>= ( $$< a )
cont :: Fun -> Fun
cont = Fun . flip ( $$ )
s, k, i :: Fun
s = mkFun $ \x -> mkFun $ \y -> Fun $ \z -> x $$ z >$$< y $$ z
k = mkFun $ mkFun . const
i = mkFun id
empty, zero, one :: Fun
empty = cont i
zero = cont $ Fun $ \f -> f $$ s >$$ k
one = mkFun $ \c -> cont $ mkFun $ \l -> cont $ Fun $ \r -> c $$< l $$ r
pr :: Fun
pr = Fun $ \x -> interrogate x >$$ Zero >$$ One >>= putStr . show >> return pr
interrogate :: Fun -> IO Fun
interrogate f = f $$ i >$$ i >$$ i >$$ k
output :: IO Fun
output = k $$< k $$< k $$< k $$< k $$< k $$ i
readZot :: String -> IO Fun
readZot = foldM ( $$ ) empty . read . filter ( `elem` "01" )
interpret :: String -> IO ()
interpret src = readZot ( removeComment src ) >$$< output >$$ pr >> putStrLn ""
where
removeComment = concatMap ( takeWhile ( /= '#' ) ) . lines
main :: IO ()
main = getContents >>= interpret
mainFile :: String -> IO ()
mainFile fn = do
prg <- readFile fn
arg <- getContents
interpret $ prg ++ arg