1 {-# LANGUAGE PatternGuards, DeriveDataTypeable #-}
8 import Data.Generics hiding (typeOf)
9 import Data.Generics.Schemes
11 data TypedExpr = TypedExpr
14 } deriving (Eq, Typeable, Data)
16 typedLeft, typedRight :: Expr -> Typ -> TypedExpr
17 typedLeft e t = TypedExpr e (instType False t)
18 typedRight e t = TypedExpr e (instType True t)
23 | Conc [Expr] -- Conc [] is Id
24 | Lambda TypedExpr Expr
27 deriving (Eq, Typeable, Data)
31 | And [BoolExpr] -- And [] is True
32 | AllZipWith TypedExpr TypedExpr BoolExpr Expr Expr
33 | Condition [TypedExpr] BoolExpr BoolExpr
34 | UnpackPair TypedExpr TypedExpr TypedExpr BoolExpr
35 | TypeVarInst Int BoolExpr
36 deriving (Eq, Typeable, Data)
40 equal te1 te2 | typeOf te1 /= typeOf te2 = error "Type mismatch in equal"
41 | otherwise = Equal (unTypeExpr te1) (unTypeExpr te2)
43 unpackPair = UnpackPair
45 allZipWith :: TypedExpr -> TypedExpr -> BoolExpr -> TypedExpr -> TypedExpr -> BoolExpr
46 allZipWith v1 v2 rel e1 e2 | Just v1' <- defFor v1 rel =
47 e1 `equal` amap (lambda v2 v1') e2
48 | Just v2' <- defFor v2 rel =
49 amap (lambda v1 v2') e1 `equal` e2
51 AllZipWith v1 v2 rel (unTypeExpr e1) (unTypeExpr e2)
53 amap tf tl | Arrow t1 t2 <- typeOf tf
56 = let tMap = TypedExpr Map (Arrow (Arrow t1 t2) (Arrow (List t1) (List t2)))
57 in app (app tMap tf) tl
58 amap tf tl | otherwise = error "Type error in map"
61 aand (Condition vars beTrue concl) be = Condition vars beTrue (aand concl be)
62 aand (And xs) (And ys) = And (xs ++ ys)
63 aand (And xs) y = And (xs ++ [y])
64 aand x (And ys) = And ([x] ++ ys)
65 aand x y = And ([x,y])
69 -- | Is any var (or part of var) defined in cond, and can be replaced in concl?
70 condition :: [TypedExpr] -> BoolExpr -> BoolExpr -> BoolExpr
71 condition vars cond concl | ((vars',cond',concl'):_) <- mapMaybe try vars
72 = condition vars' cond' concl'
74 = Condition vars cond concl
75 where try v = do subst <- findReplacer v cond --Maybe Monad
76 return (delete v vars, subst cond, subst concl)
78 -- | Replaces a Term in a BoolExpr
79 replaceTermBE :: Expr -> Expr -> BoolExpr -> BoolExpr
80 replaceTermBE d r = go
81 where go (e1 `Equal` e2) | d == e1 && r == e2 = beTrue
82 | d == e2 && r == e1 = beTrue
83 | otherwise = go' e1 `Equal` go' e2
84 go (And es) = foldr aand beTrue (map go es)
85 go (AllZipWith v1 v2 be e1 e2)
86 = AllZipWith v1 v2 (go be) (go' e1) (go' e2)
87 go (Condition vs cond concl)
88 = condition vs (go cond) (go concl)
89 go (UnpackPair v1 v2 e be)
90 = unpackPair v1 v2 (go' e) (go be)
91 go (TypeVarInst _ _) = error "TypeVarInst not expected here"
92 go' :: Data a => a -> a
95 replaceExpr :: Data a => Expr -> Expr -> a -> a
96 replaceExpr d r = everywhere (mkT go)
97 where go e | e == d = r
100 -- | Is inside the term a definition for the variable?
101 findReplacer :: TypedExpr -> BoolExpr -> Maybe (BoolExpr -> BoolExpr)
102 findReplacer tv be = findReplacer' (unTypeExpr tv) be
104 -- | Find a definition, and return a substitution
105 findReplacer' :: Expr -> BoolExpr -> Maybe (BoolExpr -> BoolExpr)
106 -- For combined types, look up the components
107 findReplacer' (Pair x y) e | Just (delX) <- findReplacer' x e
108 , Just (delY) <- findReplacer' y e
110 -- Find the definition
111 findReplacer' e (e1 `Equal` e2) | e == e1 = Just (replaceTermBE e e2)
112 | e == e2 = Just (replaceTermBE e e1)
113 findReplacer' e (And es) = listToMaybe (mapMaybe (findReplacer' e) es)
114 -- assuming no two definitions can exist
115 findReplacer' _ _ = Nothing
117 -- | Is inside the term a definition for the variable?
118 defFor :: TypedExpr -> BoolExpr -> Maybe (TypedExpr)
119 defFor tv be | Just (e') <- defFor' (unTypeExpr tv) be
120 = Just (TypedExpr e' (typeOf tv))
121 | otherwise = Nothing
123 -- | Find a definition, and return it along the definition remover
124 defFor' :: Expr -> BoolExpr -> Maybe (Expr)
125 defFor' e (e1 `Equal` e2) | e == e1 = Just (e2)
126 | e == e2 = Just (e1)
127 defFor' e (And es) | [d] <- mapMaybe (defFor' e) es -- exactly one definition
129 defFor' _ _ = Nothing
131 app te1 te2 | Arrow t1 t2 <- typeOf te1
134 = TypedExpr (app' (unTypeExpr te1) (unTypeExpr te2)) t2
135 where app' Map (Conc []) = Conc []
138 app te1 te2 | otherwise = error $ "Type mismatch in app: " ++
139 show te1 ++ " " ++ show te2
141 unCond v (Equal l r) | (Just l') <- isApplOn (unTypeExpr v) l
142 , (Just r') <- isApplOn (unTypeExpr v) r =
143 if v `occursIn` l' || v `occursIn` r'
144 then Condition [v] beTrue (Equal l' r')
146 unCond v e = Condition [v] beTrue e
148 lambda tv e = TypedExpr inner (Arrow (typeOf tv) (typeOf e))
149 where inner | (Just e') <- isApplOn (unTypeExpr tv) (unTypeExpr e)
150 , not (unTypeExpr tv `occursIn` e')
153 | otherwise = Lambda tv (unTypeExpr e)
155 conc f (Conc fs) = Conc (f:fs)
159 isApplOn e e' | e == e' = Nothing
160 isApplOn e (App f e') | e == e' = Just (Conc [f])
161 isApplOn e (App f e') | (Just inner) <- isApplOn e e' = Just (conc f inner)
162 isApplOn _ _ = Nothing
164 hasVar v (Var v') = v == v'
165 hasVar v (App e1 e2) = hasVar v e1 && hasVar v e2
166 hasVar v (Conc es) = any (hasVar v) es
167 hasVar v (Lambda _ e) = hasVar v e
170 e `occursIn` e' = not (null (listify (==e) e'))
172 isTuple (TPair _ _) = True
185 instance Show Expr where
186 showsPrec d (Var s) = showString s
187 showsPrec d (App e1 e2) = showParen (d>10) $
188 showsPrec 10 e1 . showChar ' ' . showsPrec 11 e2
189 showsPrec d (Conc []) = showString "id"
190 showsPrec d (Conc [e]) = showsPrec d e
191 showsPrec d (Conc es) = showParen (d>9) $
192 showIntercalate (showString " . ") (map (showsPrec 10) es)
193 showsPrec d (Lambda tv e) = showParen True $
198 showsPrec _ (Pair e1 e2) = showParen True $
202 showsPrec _ Map = showString "map"
204 showIntercalate i [] = id
205 showIntercalate i [x] = x
206 showIntercalate i (x:xs) = x . i . showIntercalate i xs
208 instance Show TypedExpr where
209 showsPrec d (TypedExpr e t) =
213 showString (showTypePrec 0 t)
215 instance Show BoolExpr where
216 show (Equal e1 e2) = showsPrec 9 e1 $
219 show (And []) = show "True"
220 show (And bes) = intercalate " && " $ map show bes
221 show (AllZipWith v1 v2 be e1 e2) =
225 showsPrec 11 v1 "" ++
227 showsPrec 11 v2 "" ++
232 showsPrec 11 e1 "" ++
235 show (Condition tvars be1 be2) =
237 intercalate ", " (map show tvars) ++
239 (if be1 /= beTrue then indent 2 (show be1) ++ "==>\n" else "") ++
241 show (UnpackPair v1 v2 e be) =
250 show (TypeVarInst i be) =
264 indent n = unlines . map (replicate n ' ' ++) . lines
266 showTypePrec :: Int -> Typ -> String
267 showTypePrec _ Int = "Int"
268 showTypePrec _ (TVar (TypVar i)) = "a"++show i
269 showTypePrec _ (TVar (TypInst i b)) | not b = "t" ++ show (2*i-1)
270 | b = "t" ++ show (2*i)
271 showTypePrec d (Arrow t1 t2) = paren (d>9) $
272 showTypePrec 10 t1 ++ " -> " ++ showTypePrec 9 t2
273 showTypePrec d (List t) = "[" ++ showTypePrec 0 t ++ "]"
274 showTypePrec d (TEither t1 t2) = "Either " ++ showTypePrec 11 t1 ++
275 " " ++ showTypePrec 11 t2
276 showTypePrec d (TPair t1 t2) = "(" ++ showTypePrec 0 t1 ++
277 "," ++ showTypePrec 0 t2 ++ ")"
279 paren b p = if b then "(" ++ p ++ ")" else p