home *** CD-ROM | disk | FTP | other *** search
- -- This is a program to illustrate a simple form of common subexpression
- -- elimination ... essentially turning trees into DAGs. Uses two state
- -- monads (more precisely, same monad but different state types).
- --
- -- This programs should be loaded after `stateMonad': For example:
- -- ? :l stateMonad csexpr
- -- ? test
- --
- -- The output for this `test' is included at the end of the file.
- --
- -- Mark P. Jones, 1992
- --
-
- -- Data type definitions: ----------------------------------------------------
-
- data GenTree a = Node a [GenTree a]
- type LabGraph a = [ (Label, a, [Label]) ]
- type Label = Int
-
- -- Add distinct (integer) labels to each node of a tree: ---------------------
-
- labelTree :: GenTree a -> GenTree (Label,a)
- labelTree t = label t `startingWith` 0
- where label (Node x xs) = incr `bind` \n ->
- mmapl label xs `bind` \ts ->
- return (Node (n,x) ts)
-
- -- Convert tree after labelling each node to a labelled graph: ---------------
-
- ltGraph :: GenTree (Label,a) -> LabGraph a
- ltGraph (Node (n,x) xs) = (n, x, map labelOf xs) : concat (map ltGraph xs)
- where labelOf (Node (n,x) xs) = n
-
- -- Build tree from labelled graph: -------------------------------------------
-
- unGraph :: LabGraph a -> GenTree a
- unGraph ((n,x,cs):ts) = Node x (map (unGraph . find) cs)
- where find c = dropWhile (\(d,_,_) -> c/=d) ts
-
-
- -- Build tree but avoid duplicating shared parts: ----------------------------
-
- unGraph' :: LabGraph String -> GenTree (Int,String)
- unGraph' lg = ung lg `startingWith` []
- where ung ((n,x,cs):ts) = mif (visited n)
- (return (Node (n,"<>") []))
- (mmapl (ung . find) cs `bind` \ts ->
- return (Node (n,x) ts))
- where find c = dropWhile (\(d,_,_) -> c/=d) ts
-
- visited :: Label -> SM [Label] Bool
- visited n = fetch `bind` \us ->
- if n `elem` us then return True
- else set (n:us) `bind` \_ ->
- return False
-
- -- Find (and eliminate) repeated subtrees in a labelled graph: ---------------
- -- Described as a transformation on labelled graphs: During the calculation
- -- we use a pair (r,lg) :: (Label->Label, LabGraph a) where lg contains the
- -- simplified portion of the graph calculated so far and r is a renaming (or
- -- replacement?) which maps node labels in the original graph to the approp.
- -- labels in the new graph.
-
- findCommon :: Eq a => LabGraph a -> LabGraph a
- findCommon = snd . foldr sim (id,[])
- where sim (n,s,cs) (r,lg) = (r, [(n,s,rcs)]++lg), if null ms
- = ((n +-> head ms) r, lg), otherwise
- where ms = [m | (m,s',cs')<-lg, s==s', cs'==rcs]
- rcs = map r cs
-
- infix +-> -- overide function at single point
- (+->) :: Eq a => a -> b -> (a -> b) -> (a -> b)
- (x +-> fx) f y = if x==y then fx else f y
-
- -- Common subexpression elimination: -----------------------------------------
-
- cse :: Eq a => GenTree a -> LabGraph a
- cse = findCommon . ltGraph . labelTree
-
- -- Pretty printers: ----------------------------------------------------------
-
- instance Text (GenTree String) where
- showsPrec d (Node x ts)
- | null ts = showString x
- | otherwise = showChar '(' . showString x
- . showChar ' '
- . (foldr1 (\x y -> x . showChar ' ' . y)
- (map shows ts))
- . showChar ')'
-
- drawTree :: GenTree String -> String
- drawTree = unlines . draw
- draw (Node x ts) = grp (s1 ++ pad width x ++ "]") (space (width+3)) (stLoop ts)
- where stLoop [] = [""]
- stLoop [t] = grp s2 " " (draw t)
- stLoop (t:ts) = grp s3 s4 (draw t) ++ [s4] ++ rsLoop ts
-
- rsLoop [t] = grp s5 " " (draw t)
- rsLoop (t:ts) = grp s6 s4 (draw t) ++ [s4] ++ rsLoop ts
-
- grp fst rst = zipWith (++) (fst:repeat rst)
-
- -- Define the strings used to print tree diagrams:
- [s1,s2,s3,s4,s5,s6] | pcGraphics = ["\196[", "\196\196", "\196\194",
- " \179", " \192", " \195"]
- | otherwise = ["-[", "--", "-+",
- " |", " `", " +"]
-
- pad n x = take n (x ++ repeat ' ')
- width = 4
- pcGraphics = False
-
- showGraph :: LabGraph a -> String
- showGraph [] = "[]\n"
- showGraph xs = "[" ++ loop (map show' xs)
- where loop [x] = x ++ "]\n"
- loop (x:xs) = x ++ ",\n " ++ loop xs
-
- -- Examples: -----------------------------------------------------------------
-
- plus x y = Node "+" [x,y]
- mult x y = Node "*" [x,y]
- prod xs = Node "X" xs
- zero = Node "0" []
- a = Node "a" []
- b = Node "b" []
- c = Node "c" []
- d = Node "d" []
-
- examples = [example0, example1, example2, example3, example4, example5]
- example0 = a
- example1 = plus a a
- example2 = plus (mult a b) (mult a b)
- example3 = plus (mult (plus a b) c) (plus a b)
- example4 = prod (scanl plus zero [a,b,c,d])
- example5 = prod (scanr plus zero [a,b,c,d])
-
- test = appendChan "stdout" -- writeFile "csoutput"
- (unlines (map (\t -> let c = cse t
- in copy 78 '-' ++
- "\nExpression:\n" ++ show t ++
- "\n\nTree:\n" ++ drawTree t ++
- "\nLabelled graph:\n" ++ showGraph c ++
- "\nSimplified tree:\n" ++ showCse c)
- examples))
- exit
- done
- where
- showCse = drawTree
- . mapGenTree (\(n,s) -> show n++":"++s)
- . unGraph'
- mapGenTree f (Node x ts) = Node (f x) (map (mapGenTree f) ts)
-
- {-----------------------------------------------------------------------------
- Expression:
- a
-
- Tree:
- -[a ]
-
- Labelled graph:
- [(0,"a",[])]
-
- Simplified tree:
- -[0:a ]
-
- ------------------------------------------------------------------------------
- Expression:
- (+ a a)
-
- Tree:
- -[+ ]-+-[a ]
- |
- `-[a ]
-
- Labelled graph:
- [(0,"+",[2, 2]),
- (2,"a",[])]
-
- Simplified tree:
- -[0:+ ]-+-[2:a ]
- |
- `-[2:<>]
-
- ------------------------------------------------------------------------------
- Expression:
- (+ (* a b) (* a b))
-
- Tree:
- -[+ ]-+-[* ]-+-[a ]
- | |
- | `-[b ]
- |
- `-[* ]-+-[a ]
- |
- `-[b ]
-
- Labelled graph:
- [(0,"+",[4, 4]),
- (4,"*",[5, 6]),
- (5,"a",[]),
- (6,"b",[])]
-
- Simplified tree:
- -[0:+ ]-+-[4:* ]-+-[5:a ]
- | |
- | `-[6:b ]
- |
- `-[4:<>]
-
- ------------------------------------------------------------------------------
- Expression:
- (+ (* (+ a b) c) (+ a b))
-
- Tree:
- -[+ ]-+-[* ]-+-[+ ]-+-[a ]
- | | |
- | | `-[b ]
- | |
- | `-[c ]
- |
- `-[+ ]-+-[a ]
- |
- `-[b ]
-
- Labelled graph:
- [(0,"+",[1, 6]),
- (1,"*",[6, 5]),
- (5,"c",[]),
- (6,"+",[7, 8]),
- (7,"a",[]),
- (8,"b",[])]
-
- Simplified tree:
- -[0:+ ]-+-[1:* ]-+-[6:+ ]-+-[7:a ]
- | | |
- | | `-[8:b ]
- | |
- | `-[5:c ]
- |
- `-[6:<>]
-
- ------------------------------------------------------------------------------
- Expression:
- (X 0 (+ 0 a) (+ (+ 0 a) b) (+ (+ (+ 0 a) b) c) (+ (+ (+ (+ 0 a) b) c) d))
-
- Tree:
- -[X ]-+-[0 ]
- |
- +-[+ ]-+-[0 ]
- | |
- | `-[a ]
- |
- +-[+ ]-+-[+ ]-+-[0 ]
- | | |
- | | `-[a ]
- | |
- | `-[b ]
- |
- +-[+ ]-+-[+ ]-+-[+ ]-+-[0 ]
- | | | |
- | | | `-[a ]
- | | |
- | | `-[b ]
- | |
- | `-[c ]
- |
- `-[+ ]-+-[+ ]-+-[+ ]-+-[+ ]-+-[0 ]
- | | | |
- | | | `-[a ]
- | | |
- | | `-[b ]
- | |
- | `-[c ]
- |
- `-[d ]
-
- Labelled graph:
- [(0,"X",[21, 20, 19, 18, 17]),
- (17,"+",[18, 25]),
- (18,"+",[19, 24]),
- (19,"+",[20, 23]),
- (20,"+",[21, 22]),
- (21,"0",[]),
- (22,"a",[]),
- (23,"b",[]),
- (24,"c",[]),
- (25,"d",[])]
-
- Simplified tree:
- -[0:X ]-+-[21:0]
- |
- +-[20:+]-+-[21:<]
- | |
- | `-[22:a]
- |
- +-[19:+]-+-[20:<]
- | |
- | `-[23:b]
- |
- +-[18:+]-+-[19:<]
- | |
- | `-[24:c]
- |
- `-[17:+]-+-[18:<]
- |
- `-[25:d]
-
-
- ------------------------------------------------------------------------------
- Expression:
- (X (+ a (+ b (+ c (+ d 0)))) (+ b (+ c (+ d 0))) (+ c (+ d 0)) (+ d 0) 0)
-
- Tree:
- -[X ]-+-[+ ]-+-[a ]
- | |
- | `-[+ ]-+-[b ]
- | |
- | `-[+ ]-+-[c ]
- | |
- | `-[+ ]-+-[d ]
- | |
- | `-[0 ]
- |
- +-[+ ]-+-[b ]
- | |
- | `-[+ ]-+-[c ]
- | |
- | `-[+ ]-+-[d ]
- | |
- | `-[0 ]
- |
- +-[+ ]-+-[c ]
- | |
- | `-[+ ]-+-[d ]
- | |
- | `-[0 ]
- |
- +-[+ ]-+-[d ]
- | |
- | `-[0 ]
- |
- `-[0 ]
-
- Labelled graph:
- [(0,"X",[1, 10, 17, 22, 25]),
- (1,"+",[2, 10]),
- (2,"a",[]),
- (10,"+",[11, 17]),
- (11,"b",[]),
- (17,"+",[18, 22]),
- (18,"c",[]),
- (22,"+",[23, 25]),
- (23,"d",[]),
- (25,"0",[])]
-
- Simplified tree:
- -[0:X ]-+-[1:+ ]-+-[2:a ]
- | |
- | `-[10:+]-+-[11:b]
- | |
- | `-[17:+]-+-[18:c]
- | |
- | `-[22:+]-+-[23:d]
- | |
- | `-[25:0]
- |
- +-[10:<]
- |
- +-[17:<]
- |
- +-[22:<]
- |
- `-[25:<]
-
- -}----------------------------------------------------------------------------
-