visual-graphrewrite-0.3: GraphRewrite/Internal/RewriteApp.hs
module GraphRewrite.Internal.RewriteApp
( makeRewriteRules, invMakeExpr, makeRewriteSystem )
where
import Prelude hiding (exp)
import qualified Data.IntMap as I
import qualified Data.List as L
import GraphRewrite.Internal.RewriteTypes
import qualified GraphRewrite.Internal.SimpleHaskell as SH
makeRewriteSystem :: SH.SimpModule Int -> I.IntMap String -> RewriteSystem
makeRewriteSystem m nms = (makeRewriteRules m) { names = nms }
makeRewriteRules :: SH.SimpModule Int -> RewriteSystem
makeRewriteRules [] = defaultRS
makeRewriteRules (h:t) = case I.lookup hid (rules rest) of -- FIXME vv
Just rs -> defaultRS { rules = I.insert hid (extend rs h) (rules rest) }
Nothing -> defaultRS { rules = I.insert hid (extend [] h) (rules rest) }
where
hid = SH.name' h
rest = makeRewriteRules t
extend l (SH.FunBind as) = L.nub $ l ++ map makeRule as
extend l (SH.PatBind (SH.Var v) e) = extend l (SH.FunBind [(v, [], e)]) -- special case to handle variable bindings
extend l _ = l
makeRule :: SH.FunAlt Int -> Rule
makeRule (_, ps, e) = fixExpr $ Rule { patts = map makePat ps,
exp = makeExpr e,
graph = makeGraph (e:ps) }
makePat :: SH.Expr Int -> Expr
makePat (SH.AsPat _ e) = makeExpr e
makePat x = makeExpr x
makeExpr :: SH.Expr Int -> Expr
makeExpr (SH.Var v) = SHole v
makeExpr (SH.Cons c) = SCons c
makeExpr (SH.Lit l) = SLit l
makeExpr (SH.Let _ e) = makeRefExpr e
makeExpr (SH.Apply ((SH.Cons c):t)) = SApp (SCons c) (map makeExpr t)
makeExpr (SH.Apply ((SH.Var v):t)) = SApp (SFun (length t) v) (map makeExpr t) -- ez vajon igy jo?
makeExpr (SH.Apply (h@(SH.Apply (_:_)):t)) = SApp (fst la) (snd la)
where
la = liftApp $ makeExpr h
liftApp (SApp (SFun a f) l) = (SFun (a + (length t)) f, l ++ (map makeExpr t))
liftApp (SApp (SCons c) l) = (SCons c, l ++ (map makeExpr t))
makeRefExpr :: SH.Expr Int -> Expr
makeRefExpr = holeToRef . makeExpr
where
holeToRef (SHole h) = SRef h
holeToRef (SApp e es) = SApp (holeToRef e) (map holeToRef es)
holeToRef e = e
fixExpr :: Rule -> Rule
fixExpr r@(Rule {exp = e, graph = g}) = r { exp = doFix e }
where
doFix x@(SHole h) = case I.lookup h g of
Just _ -> SRef h
_ -> x
doFix (SApp e es) = SApp (doFix e) (map doFix es)
doFix x = x
makeGraph :: [SH.Expr Int] -> Graph
makeGraph (p:ps) = case p of
SH.AsPat a e -> I.insert a (makeExpr e) (makeGraph ps)
SH.Let ((SH.PatBind p pe):ds) e -> let patid = read (exprID $ makePat p) :: Int in
I.insert patid (makeRefExpr pe) (makeGraph ((SH.Let ds e):ps))
SH.Let [] _ -> makeGraph ps --redundant
SH.Let ((SH.FunBind _):_) _ -> error "makeGraph error: FunBinds unsupported in Let"
_ -> makeGraph ps
makeGraph [] = I.empty
invMakeExpr :: Expr -> SH.Expr Int
invMakeExpr (SCons c) = SH.Cons c
invMakeExpr (SLit l) = SH.Lit l
invMakeExpr (SFun _ f) = SH.Var f
invMakeExpr (SHole v) = SH.Lit ("THIS IS A BUG - " ++ show v)
invMakeExpr (SApp x xs) = SH.Apply (invMakeExpr x : map invMakeExpr xs)