syntactic-1.2: src/Language/Syntactic/Constructs/Decoration.hs
-- | Construct for decorating expressions with additional information
module Language.Syntactic.Constructs.Decoration where
import Data.Tree
import Language.Syntactic
--------------------------------------------------------------------------------
-- * Decoration
--------------------------------------------------------------------------------
-- | Decorating symbols with additional information
--
-- One usage of 'Decor' is to decorate every node of a syntax tree. This is done
-- simply by changing
--
-- > AST dom sig
--
-- to
--
-- > AST (Decor info dom) sig
data Decor info expr sig
where
Decor
:: { decorInfo :: info (DenResult sig)
, decorExpr :: expr sig
}
-> Decor info expr sig
instance Constrained expr => Constrained (Decor info expr)
where
type Sat (Decor info expr) = Sat expr
exprDict (Decor _ a) = exprDict a
instance Project sub sup => Project sub (Decor info sup)
where
prj = prj . decorExpr
instance Equality expr => Equality (Decor info expr)
where
equal a b = decorExpr a `equal` decorExpr b
exprHash = exprHash . decorExpr
instance Render expr => Render (Decor info expr)
where
renderArgs args = renderArgs args . decorExpr
render = render . decorExpr
instance ToTree expr => ToTree (Decor info expr)
where
toTreeArgs args = toTreeArgs args . decorExpr
instance Eval expr => Eval (Decor info expr)
where
evaluate = evaluate . decorExpr
-- | Get the decoration of the top-level node
getInfo :: AST (Decor info dom) sig -> info (DenResult sig)
getInfo (Sym (Decor info _)) = info
getInfo (f :$ _) = getInfo f
-- | Update the decoration of the top-level node
updateDecor :: forall info dom a .
(info a -> info a) -> ASTF (Decor info dom) a -> ASTF (Decor info dom) a
updateDecor f = match update
where
update
:: (a ~ DenResult sig)
=> Decor info dom sig
-> Args (AST (Decor info dom)) sig
-> ASTF (Decor info dom) a
update (Decor info a) args = appArgs (Sym sym) args
where
sym = Decor (f info) a
-- | Lift a function that operates on expressions with associated information to
-- operate on an 'Decor' expression. This function is convenient to use together
-- with e.g. 'queryNodeSimple' when the domain has the form
-- @(`Decor` info dom)@.
liftDecor :: (expr s -> info (DenResult s) -> b) -> (Decor info expr s -> b)
liftDecor f (Decor info a) = f a info
-- | Collect the decorations of all nodes
collectInfo :: (forall sig . info sig -> b) -> AST (Decor info dom) sig -> [b]
collectInfo coll (Sym (Decor info _)) = [coll info]
collectInfo coll (f :$ a) = collectInfo coll f ++ collectInfo coll a
-- | Rendering of decorated syntax trees
toTreeDecor :: forall info dom a . (Render info, ToTree dom) =>
ASTF (Decor info dom) a -> Tree String
toTreeDecor a = mkTree [] a
where
mkTree :: [Tree String] -> AST (Decor info dom) sig -> Tree String
mkTree args (Sym (Decor info expr)) = Node infoStr [toTreeArgs args expr]
where
infoStr = "<<" ++ render info ++ ">>"
mkTree args (f :$ a) = mkTree (mkTree [] a : args) f
-- | Show an decorated syntax tree using ASCII art
showDecor :: (Render info, ToTree dom) => ASTF (Decor info dom) a -> String
showDecor = drawTree . toTreeDecor
-- | Print an decorated syntax tree using ASCII art
drawDecor :: (Render info, ToTree dom) => ASTF (Decor info dom) a -> IO ()
drawDecor = putStrLn . showDecor
-- | Strip decorations from an 'AST'
stripDecor :: AST (Decor info dom) sig -> AST dom sig
stripDecor (Sym (Decor _ a)) = Sym a
stripDecor (f :$ a) = stripDecor f :$ stripDecor a