1
{-# OPTIONS -fglasgow-exts -fallow-undecidable-instances -fno-warn-incomplete-patterns #-}
4
module DeBruijnLazy4 where
6
import Prelude hiding (mapM)
8
import Control.Monad.State hiding (mapM)
9
import Control.Applicative
10
import Data.Traversable
14
import Data.Map (Map, (!))
16
import qualified Data.Map as Map
17
import qualified Data.Set as Set
19
import qualified Syntax as S
20
import Syntax ( AppView(..), Pat(..), appView )
25
data ExpR s = Var Int [Exp s]
30
type Exp s = Ptr s (ExpR s)
36
| Split (NameMap (Case s))
39
type NameMap = Map Name
43
appsR :: ExpR s -> [Exp s] -> ExpR s
45
appsR (Var n es) es' = Var n $ es ++ es'
46
appsR (Con c es) es' = Con c $ es ++ es'
47
appsR (Def c es) es' = Def c $ es ++ es'
48
appsR (Lam e es) es' = Lam e $ es ++ es'
50
apps :: Exp s -> [Exp s] -> M s (Exp s)
56
var n es = alloc (Var n es)
57
con c es = alloc (Con c es)
58
def c es = alloc (Def c es)
59
lam e es = alloc (Lam e es)
61
type Sig s = NameMap (Case s)
64
getNames :: a -> Set S.Name
66
instance Names S.Exp where
67
getNames e = case e of
69
S.Def c -> Set.singleton c
70
S.Con c -> Set.singleton c
72
S.App u v -> Set.union (getNames u) (getNames v)
74
instance Names S.Pat where
75
getNames p = case p of
78
ConP c ps -> Set.insert c $ getNames ps
80
instance Names S.Clause where
81
getNames (S.Clause ps v) = getNames (ps, v)
83
instance Names a => Names (Map k a) where
84
getNames = getNames . Map.elems
86
instance Names a => Names [a] where
87
getNames = Set.unions . map getNames
89
instance (Names a, Names b) => Names (a, b) where
90
getNames (x, y) = Set.union (getNames x) (getNames y)
92
class Compile a c | a -> c where
95
instance Compile S.Sig (M s (Sig s, NameMap S.Name, Map S.Name Name)) where
97
sig' <- Map.fromList <$> mapM comp (Map.toList sig)
98
return (sig', nameMap, idMap)
100
ns = Set.toList $ Set.union (getNames sig) (Set.fromList $ Map.keys sig)
101
nameMap = Map.fromList $ zip [0..] ns
102
idMap = Map.fromList $ zip ns [0..]
105
cl' <- compile cl idMap
106
return (idMap ! c, cl')
108
instance Compile S.Exp (Map S.Name Name -> M s (Exp s)) where
109
compile e nmap = case appView e of
110
Apps (S.Var n) es -> var n =<< comps es
111
Apps (S.Con c) es -> con (nmap ! c) =<< comps es
112
Apps (S.Def c) es -> def (nmap ! c) =<< comps es
113
Apps (S.Lam v) es -> do
118
comps es = mapM (flip compile nmap) es
120
instance Compile [S.Clause] (Map S.Name Name -> M s (Case s)) where
122
np <- nextPatterns cs
124
Right [v] -> return $ Done v
125
Right [] -> error $ "no rhs: " ++ show cs
126
Right (_:_) -> error $ "overlapping patterns: " ++ show cs
127
Left pcs -> case conOrVar pcs of
128
Left cs -> Bind <$> compile cs nmap
129
Right ccs -> Split <$> mapM (flip compile nmap) (Map.fromList ccs)
131
patterns (S.Clause ps _) = ps
132
body (S.Clause _ v) = compile v nmap
133
next (S.Clause (p:ps) v) = (p, S.Clause ps v)
134
next _ = error $ "bad clauses: " ++ show cs
136
nextPatterns :: [S.Clause] -> M s (Either [(Pat, S.Clause)] [Exp s])
138
| all null pss = Right <$> mapM body cs
139
| otherwise = return $ Left $ map next cs
141
pss = map patterns cs
143
conOrVar :: [(Pat, S.Clause)] -> Either [S.Clause] [(Name, [S.Clause])]
145
| all (isVar . fst) cs = Left $ map snd cs
146
| all (isCon . fst) cs = Right $
148
$ groupBy ((==) `on` conName `on` fst)
149
$ sortBy (compare `on` conName `on` fst)
151
| otherwise = error $ "bad clauses: " ++ show cs
153
splitCon :: [(Pat, S.Clause)] -> (Name, [S.Clause])
154
splitCon cs = ( nmap ! conName (fst $ head cs)
158
amendClause (ConP _ ps, S.Clause qs v) = S.Clause (ps ++ qs) v
164
isCon (ConP _ _) = True
167
conName (ConP c _ ) = c
168
conArgs (ConP c vs) = vs
170
decompile :: NameMap S.Name -> Exp s -> M s S.Exp
171
decompile nmap e = do
174
Var n es -> S.apps (S.Var n) <$> mapM dec es
175
Con c es -> S.apps (S.Con (nmap ! c)) <$> mapM dec es
176
Def c es -> S.apps (S.Def (nmap ! c)) <$> mapM dec es
180
return $ S.Lam e `S.apps` es
186
data Condition = Broken | Pristine
188
instance Monoid Condition where
190
mappend Broken _ = Broken
191
mappend Pristine c = c
193
type RaiseM s = StateT Condition (M s)
195
needRepairs :: a -> (b -> RaiseM s a) -> RaiseM s b -> RaiseM s a
196
needRepairs original repair takeApart = do
200
Pristine -> return original
201
Broken -> repair parts
203
localRepairs :: RaiseM s a -> RaiseM s a
211
raiseFrom :: Int -> Int -> Exp s -> RaiseM s (Exp s)
212
raiseFrom n k e = localRepairs $ do
216
| m < n -> needRepairs e (lift . var m) $ mapM (raiseFrom n k) es
219
lift . var (m + k) =<< mapM (raiseFrom n k) es
220
Con c es -> needRepairs e (lift . con c) $ mapM (raiseFrom n k) es
221
Def c es -> needRepairs e (lift . def c) $ mapM (raiseFrom n k) es
222
Lam b es -> needRepairs e (lift . uncurry lam) $ do
223
b <- raiseFrom (n + 1) k b
224
es <- mapM (raiseFrom n k) es
227
raise :: Int -> Exp s -> M s (Exp s)
228
raise n e = evalStateT (raiseFrom 0 n e) Pristine
230
subst :: [Exp s] -> Exp s -> M s (Exp s)
234
Var m es -> apps (us !! m) =<< mapM (subst us) es
235
Con c es -> con c =<< mapM (subst us) es
236
Def c es -> def c =<< mapM (subst us) es
239
us' <- mapM (raise 1) us
240
e <- subst (vz : us') t
241
es <- mapM (subst us) es
244
matchDef :: Int -> Sig s -> Case s -> [Exp s] -> M s (Maybe (Exp s))
245
matchDef ctx sig c vs = match c [] vs
247
match (Done v) sub vs = {-# SCC "matchDone" #-} Just <$> (flip apps vs =<< subst sub v)
248
match _ sub [] = return Nothing
249
match (Skip c) sub (v:vs) = match c sub vs
250
match (Bind c) sub (v:vs) = match c (v : sub) vs
251
match (Split m) sub (v:vs) = do
252
v' <- {-# SCC "matchWHNF" #-} whnf ctx sig v
254
Con c ws -> case {-# SCC "conLookup" #-} Map.lookup c m of
255
Just c' -> match c' sub (ws ++ vs)
256
Nothing -> return Nothing
259
iota :: Int -> Sig s -> Name -> [Exp s] -> M s (ExpR s)
260
iota ctx sig c vs = case {-# SCC "lookupDef" #-} Map.lookup c sig of
261
Nothing -> return $ Con c vs
263
mv <- matchDef ctx sig cs vs
265
Nothing -> return $ Con c vs
266
Just v -> whnf ctx sig v
268
top :: Int -> Exp s -> M s [Exp s]
269
top n v = (v :) <$> mapM (flip var []) [0..n - 1]
271
whnf :: Int -> Sig s -> Exp s -> M s (ExpR s)
272
whnf ctx sig v = onThunk v $ \v -> case v of
273
Var n vs -> return $ Var n vs
274
Con c vs -> return $ Con c vs
275
Def c vs -> iota ctx sig c vs
278
whnf ctx sig =<< flip apps vs =<< subst sub u
279
Lam u [] -> return $ Lam u []
281
eval' :: Int -> Sig s -> Exp s -> M s ()
284
onThunk v $ \v -> case v of
285
Lam u [] -> eval' (ctx + 1) sig u >> return v
286
Var n vs -> mapM (eval' ctx sig) vs >> return v
287
Con c vs -> mapM (eval' ctx sig) vs >> return v
288
Def c vs -> mapM (eval' ctx sig) vs >> return v
291
eval :: S.Sig -> S.Exp -> S.Exp
292
eval sig e = runHeap (do
293
(sig', nmap, imap) <- compile sig