{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE Safe #-}
module Copilot.Theorem.Misc.SExpr where
import Text.PrettyPrint.HughesPJ as PP hiding (char, Str)
import Control.Monad
data SExpr a = Atom a
| List [SExpr a]
blank :: SExpr String
blank = String -> SExpr String
forall a. a -> SExpr a
Atom String
""
atom :: a -> SExpr a
atom = a -> SExpr a
forall a. a -> SExpr a
Atom
unit :: SExpr a
unit = [SExpr a] -> SExpr a
forall a. [SExpr a] -> SExpr a
List []
singleton :: a -> SExpr a
singleton a
a = [SExpr a] -> SExpr a
forall a. [SExpr a] -> SExpr a
List [a -> SExpr a
forall a. a -> SExpr a
Atom a
a]
list :: [SExpr a] -> SExpr a
list = [SExpr a] -> SExpr a
forall a. [SExpr a] -> SExpr a
List
node :: a -> [SExpr a] -> SExpr a
node a
a [SExpr a]
l = [SExpr a] -> SExpr a
forall a. [SExpr a] -> SExpr a
List (a -> SExpr a
forall a. a -> SExpr a
Atom a
a SExpr a -> [SExpr a] -> [SExpr a]
forall a. a -> [a] -> [a]
: [SExpr a]
l)
instance Show (SExpr String) where
show :: SExpr String -> String
show = Doc -> String
PP.render (Doc -> String) -> (SExpr String -> Doc) -> SExpr String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SExpr String -> Doc
show'
where
show' :: SExpr String -> Doc
show' (Atom String
s) = String -> Doc
text String
s
show' (List [SExpr String]
ts) = Doc -> Doc
parens (Doc -> Doc) -> ([SExpr String] -> Doc) -> [SExpr String] -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Doc] -> Doc
hsep ([Doc] -> Doc)
-> ([SExpr String] -> [Doc]) -> [SExpr String] -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SExpr String -> Doc) -> [SExpr String] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map SExpr String -> Doc
show' ([SExpr String] -> Doc) -> [SExpr String] -> Doc
forall a b. (a -> b) -> a -> b
$ [SExpr String]
ts
indent :: Doc -> Doc
indent = Int -> Doc -> Doc
nest Int
1
toString :: (SExpr a -> Bool)
-> (a -> String)
-> SExpr a
-> String
toString :: forall a. (SExpr a -> Bool) -> (a -> String) -> SExpr a -> String
toString SExpr a -> Bool
shouldIndent a -> String
printAtom SExpr a
expr =
Doc -> String
PP.render ((SExpr a -> Bool) -> (a -> String) -> SExpr a -> Doc
forall a. (SExpr a -> Bool) -> (a -> String) -> SExpr a -> Doc
toDoc SExpr a -> Bool
shouldIndent a -> String
printAtom SExpr a
expr)
toDoc :: (SExpr a -> Bool)
-> (a -> String)
-> SExpr a
-> Doc
toDoc :: forall a. (SExpr a -> Bool) -> (a -> String) -> SExpr a -> Doc
toDoc SExpr a -> Bool
shouldIndent a -> String
printAtom SExpr a
expr = case SExpr a
expr of
Atom a
a -> String -> Doc
text (a -> String
printAtom a
a)
List [SExpr a]
l -> Doc -> Doc
parens ((Doc -> SExpr a -> Doc) -> Doc -> [SExpr a] -> Doc
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Doc -> SExpr a -> Doc
renderItem Doc
empty [SExpr a]
l)
where
renderItem :: Doc -> SExpr a -> Doc
renderItem Doc
doc SExpr a
s
| SExpr a -> Bool
shouldIndent SExpr a
s =
Doc
doc Doc -> Doc -> Doc
$$ Doc -> Doc
indent ((SExpr a -> Bool) -> (a -> String) -> SExpr a -> Doc
forall a. (SExpr a -> Bool) -> (a -> String) -> SExpr a -> Doc
toDoc SExpr a -> Bool
shouldIndent a -> String
printAtom SExpr a
s)
| Bool
otherwise =
Doc
doc Doc -> Doc -> Doc
<+> (SExpr a -> Bool) -> (a -> String) -> SExpr a -> Doc
forall a. (SExpr a -> Bool) -> (a -> String) -> SExpr a -> Doc
toDoc SExpr a -> Bool
shouldIndent a -> String
printAtom SExpr a
s