home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 2
/
DATAFILE_PDCD2.iso
/
utilities
/
_gofer
/
!Gofer
/
archives
/
Demos
/
Cse
/
gs
/
csexpr
next >
Wrap
Text File
|
1993-02-12
|
11KB
|
379 lines
-- 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 program doesn't use constructor classes, although it could
-- obviously be modified to fit into that framework.
--
-- This programs should be loaded after `stateMonad': For example:
-- ? :l stateMonad.gs csexpr.gs
-- ? 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 ]
|
+-[+ ]-+-[+ ]-+-