{-# LANGUAGE CPP #-}
#ifndef MIN_VERSION_GLASGOW_HASKELL
#define MIN_VERSION_GLASGOW_HASKELL(a,b,c,d) 0
#endif
#if MIN_VERSION_GLASGOW_HASKELL(7,10,0,0)
#else
{-# LANGUAGE OverlappingInstances #-}
#endif
module Language.Syntactic.Decoration where
import Data.Tree (Tree (..))
import Data.Tree.View
import Language.Syntactic.Syntax
import Language.Syntactic.Traversal
import Language.Syntactic.Interpretation
import Language.Syntactic.Sugar
data (expr :&: info) sig
where
(:&:)
:: { decorExpr :: expr sig
, decorInfo :: info (DenResult sig)
}
-> (expr :&: info) sig
instance Symbol sym => Symbol (sym :&: info)
where
symSig = symSig . decorExpr
instance (NFData1 sym, NFData1 info) => NFData1 (sym :&: info)
where
liftRnf r (s :&: i) = liftRnf r s `seq` liftRnf (`seq` ()) i
instance {-# OVERLAPPING #-} Project sub sup => Project sub (sup :&: info)
where
prj = prj . decorExpr
instance Equality expr => Equality (expr :&: info)
where
equal a b = decorExpr a `equal` decorExpr b
hash = hash . decorExpr
instance Render expr => Render (expr :&: info)
where
renderSym = renderSym . decorExpr
renderArgs args = renderArgs args . decorExpr
instance StringTree expr => StringTree (expr :&: info)
where
stringTreeSym args = stringTreeSym args . decorExpr
mapDecor
:: (sym1 sig -> sym2 sig)
-> (info1 (DenResult sig) -> info2 (DenResult sig))
-> ((sym1 :&: info1) sig -> (sym2 :&: info2) sig)
mapDecor fs fi (s :&: i) = fs s :&: fi i
getDecor :: AST (sym :&: info) sig -> info (DenResult sig)
getDecor (Sym (_ :&: info)) = info
getDecor (f :$ _) = getDecor f
updateDecor :: forall info sym a .
(info a -> info a) -> ASTF (sym :&: info) a -> ASTF (sym :&: info) a
updateDecor f = match update
where
update
:: (a ~ DenResult sig)
=> (sym :&: info) sig
-> Args (AST (sym :&: info)) sig
-> ASTF (sym :&: info) a
update (a :&: info) args = appArgs (Sym sym) args
where
sym = a :&: (f info)
liftDecor :: (expr s -> info (DenResult s) -> b) -> ((expr :&: info) s -> b)
liftDecor f (a :&: info) = f a info
stripDecor :: AST (sym :&: info) sig -> AST sym sig
stripDecor (Sym (a :&: _)) = Sym a
stripDecor (f :$ a) = stripDecor f :$ stripDecor a
stringTreeDecor :: forall info sym a . StringTree sym =>
(forall a . info a -> String) -> ASTF (sym :&: info) a -> Tree String
stringTreeDecor showInfo a = mkTree [] a
where
mkTree :: [Tree String] -> AST (sym :&: info) sig -> Tree String
mkTree args (Sym (expr :&: info)) = Node infoStr [stringTreeSym args expr]
where
infoStr = "<<" ++ showInfo info ++ ">>"
mkTree args (f :$ a) = mkTree (mkTree [] a : args) f
showDecorWith :: StringTree sym => (forall a . info a -> String) -> ASTF (sym :&: info) a -> String
showDecorWith showInfo = showTree . stringTreeDecor showInfo
drawDecorWith :: StringTree sym => (forall a . info a -> String) -> ASTF (sym :&: info) a -> IO ()
drawDecorWith showInfo = putStrLn . showDecorWith showInfo
writeHtmlDecorWith :: forall info sym a. (StringTree sym)
=> (forall b. info b -> String) -> FilePath -> ASTF (sym :&: info) a -> IO ()
writeHtmlDecorWith showInfo file a = writeHtmlTree Nothing file $ mkTree [] a
where
mkTree :: [Tree NodeInfo] -> AST (sym :&: info) sig -> Tree NodeInfo
mkTree args (f :$ a) = mkTree (mkTree [] a : args) f
mkTree args (Sym (expr :&: info)) =
Node (NodeInfo InitiallyExpanded (renderSym expr) (showInfo info)) args
smartSymDecor
:: ( Signature sig
, f ~ SmartFun (sup :&: info) sig
, sig ~ SmartSig f
, (sup :&: info) ~ SmartSym f
, sub :<: sup
)
=> info (DenResult sig) -> sub sig -> f
smartSymDecor d = smartSym' . (:&: d) . inj
sugarSymDecor
:: ( Signature sig
, fi ~ SmartFun (sup :&: info) sig
, sig ~ SmartSig fi
, (sup :&: info) ~ SmartSym fi
, SyntacticN f fi
, sub :<: sup
)
=> info (DenResult sig) -> sub sig -> f
sugarSymDecor i = sugarN . smartSymDecor i