forked from gullcomb/cubicaltt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Resolver.hs
377 lines (323 loc) · 13.7 KB
/
Resolver.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
{-# LANGUAGE TupleSections #-}
-- | Convert the concrete syntax into the syntax of cubical TT.
module Resolver where
import Control.Applicative
import Control.Monad
import Control.Monad.Reader
import Control.Monad.Except
import Control.Monad.Identity
import Data.List
import Data.Map (Map,(!))
import qualified Data.Map as Map
import Exp.Abs
import CTT (Ter,Ident,Loc(..),mkApps,mkWheres)
import qualified CTT
import Connections (negFormula,andFormula,orFormula)
import qualified Connections as C
-- | Useful auxiliary functions
-- Applicative cons
(<:>) :: Applicative f => f a -> f [a] -> f [a]
a <:> b = (:) <$> a <*> b
-- Un-something functions
unVar :: Exp -> Maybe Ident
unVar (Var (AIdent (_,x))) = Just x
unVar _ = Nothing
unWhere :: ExpWhere -> Exp
unWhere (Where e ds) = Let ds e
unWhere (NoWhere e) = e
-- Tail recursive form to transform a sequence of applications
-- App (App (App u v) ...) w into (u, [v, …, w])
-- (cleaner than the previous version of unApps)
unApps :: Exp -> [Exp] -> (Exp, [Exp])
unApps (App u v) ws = unApps u (v : ws)
unApps u ws = (u, ws)
-- Turns an expression of the form App (... (App id1 id2) ... idn)
-- into a list of idents
appsToIdents :: Exp -> Maybe [Ident]
appsToIdents = mapM unVar . uncurry (:) . flip unApps []
-- Transform a sequence of applications
-- (((u v1) .. vn) phi1) .. phim into (u,[v1,..,vn],[phi1,..,phim])
unAppsFormulas :: Exp -> [Formula]-> (Exp,[Exp],[Formula])
unAppsFormulas (AppFormula u phi) phis = unAppsFormulas u (phi:phis)
unAppsFormulas u phis = (x,xs,phis)
where (x,xs) = unApps u []
-- Flatten a tele
flattenTele :: [Tele] -> [(Ident,Exp)]
flattenTele tele =
[ (unAIdent i,typ) | Tele id ids typ <- tele, i <- id:ids ]
-- Flatten a PTele
flattenPTele :: [PTele] -> Resolver [(Ident,Exp)]
flattenPTele [] = return []
flattenPTele (PTele exp typ : xs) = case appsToIdents exp of
Just ids -> do
pt <- flattenPTele xs
return $ map (,typ) ids ++ pt
Nothing -> throwError "malformed ptele"
-------------------------------------------------------------------------------
-- | Resolver and environment
data SymKind = Variable | Constructor | PConstructor | Name
deriving (Eq,Show)
-- local environment for constructors
data Env = Env { envModule :: String,
variables :: [(Ident,SymKind)] }
deriving (Eq,Show)
type Resolver a = ReaderT Env (ExceptT String Identity) a
emptyEnv :: Env
emptyEnv = Env "" []
runResolver :: Resolver a -> Either String a
runResolver x = runIdentity $ runExceptT $ runReaderT x emptyEnv
updateModule :: String -> Env -> Env
updateModule mod e = e{envModule = mod}
insertIdent :: (Ident,SymKind) -> Env -> Env
insertIdent (n,var) e
| n == "_" = e
| otherwise = e{variables = (n,var) : variables e}
insertIdents :: [(Ident,SymKind)] -> Env -> Env
insertIdents = flip $ foldr insertIdent
insertName :: AIdent -> Env -> Env
insertName (AIdent (_,x)) = insertIdent (x,Name)
insertNames :: [AIdent] -> Env -> Env
insertNames = flip $ foldr insertName
insertVar :: Ident -> Env -> Env
insertVar x = insertIdent (x,Variable)
insertVars :: [Ident] -> Env -> Env
insertVars = flip $ foldr insertVar
insertAIdent :: AIdent -> Env -> Env
insertAIdent (AIdent (_,x)) = insertIdent (x,Variable)
insertAIdents :: [AIdent] -> Env -> Env
insertAIdents = flip $ foldr insertAIdent
getLoc :: (Int,Int) -> Resolver Loc
getLoc l = Loc <$> asks envModule <*> pure l
unAIdent :: AIdent -> Ident
unAIdent (AIdent (_,x)) = x
resolveName :: AIdent -> Resolver C.Name
resolveName (AIdent (l,x)) = do
modName <- asks envModule
vars <- asks variables
case lookup x vars of
Just Name -> return $ C.Name x
_ -> throwError $ "Cannot resolve name " ++ x ++ " at position " ++
show l ++ " in module " ++ modName
resolveVar :: AIdent -> Resolver Ter
resolveVar (AIdent (l,x)) = do
modName <- asks envModule
vars <- asks variables
case lookup x vars of
Just Variable -> return $ CTT.Var x
Just Constructor -> return $ CTT.Con x []
Just PConstructor ->
throwError $ "The path constructor " ++ x ++ " is used as a" ++
" variable at " ++ show l ++ " in " ++ modName ++
" (path constructors should have their type in" ++
" curly braces as first argument)"
Just Name ->
throwError $ "Name " ++ x ++ " used as a variable at position " ++
show l ++ " in module " ++ modName
_ -> throwError $ "Cannot resolve variable " ++ x ++ " at position " ++
show l ++ " in module " ++ modName
lam :: (Ident,Exp) -> Resolver Ter -> Resolver Ter
lam (a,t) e = CTT.Lam a <$> resolveExp t <*> local (insertVar a) e
lams :: [(Ident,Exp)] -> Resolver Ter -> Resolver Ter
lams = flip $ foldr lam
plam :: AIdent -> Resolver Ter -> Resolver Ter
plam i e = CTT.PLam (C.Name (unAIdent i)) <$> local (insertName i) e
plams :: [AIdent] -> Resolver Ter -> Resolver Ter
plams [] _ = throwError "Empty plam abstraction"
plams xs e = foldr plam e xs
bind :: (Ter -> Ter) -> (Ident,Exp) -> Resolver Ter -> Resolver Ter
bind f (x,t) e = f <$> lam (x,t) e
binds :: (Ter -> Ter) -> [(Ident,Exp)] -> Resolver Ter -> Resolver Ter
binds f = flip $ foldr $ bind f
resolveApps :: Exp -> [Exp] -> Resolver Ter
resolveApps x xs = mkApps <$> resolveExp x <*> mapM resolveExp xs
resolveExp :: Exp -> Resolver Ter
resolveExp e = case e of
U -> return CTT.U
Var x -> resolveVar x
App t s -> resolveApps x xs
where (x,xs) = unApps t [s]
Sigma ptele b -> do
tele <- flattenPTele ptele
binds CTT.Sigma tele (resolveExp b)
Pi ptele b -> do
tele <- flattenPTele ptele
binds CTT.Pi tele (resolveExp b)
Fun a b -> bind CTT.Pi ("_",a) (resolveExp b)
Lam ptele t -> do
tele <- flattenPTele ptele
lams tele (resolveExp t)
Fst t -> CTT.Fst <$> resolveExp t
Snd t -> CTT.Snd <$> resolveExp t
Pair t0 ts -> do
e <- resolveExp t0
es <- mapM resolveExp ts
return $ foldr1 CTT.Pair (e:es)
Split t brs -> do
t' <- resolveExp t
brs' <- mapM resolveBranch brs
l@(Loc n (i,j)) <- getLoc (case brs of
OBranch (AIdent (l,_)) _ _:_ -> l
PBranch (AIdent (l,_)) _ _ _:_ -> l
_ -> (0,0))
return $ CTT.Split (n ++ "_L" ++ show i ++ "_C" ++ show j) l t' brs'
Let decls e -> do
(rdecls,names) <- resolveDecls decls
mkWheres rdecls <$> local (insertIdents names) (resolveExp e)
PLam is e -> plams is (resolveExp e)
Hole (HoleIdent (l,_)) -> CTT.Hole <$> getLoc l
AppFormula t phi ->
let (x,xs,phis) = unAppsFormulas e []
in case x of
PCon n a ->
CTT.PCon (unAIdent n) <$> resolveExp a <*> mapM resolveExp xs
<*> mapM resolveFormula phis
_ -> CTT.AppFormula <$> resolveExp t <*> resolveFormula phi
PathP a u v -> CTT.PathP <$> resolveExp a <*> resolveExp u <*> resolveExp v
Comp u v ts -> CTT.Comp <$> resolveExp u <*> resolveExp v <*> resolveSystem ts
Fill u v ts -> CTT.Fill <$> resolveExp u <*> resolveExp v <*> resolveSystem ts
Trans u v -> CTT.Comp <$> resolveExp u <*> resolveExp v <*> pure Map.empty
Glue u ts -> CTT.Glue <$> resolveExp u <*> resolveSystem ts
GlueElem u ts -> CTT.GlueElem <$> resolveExp u <*> resolveSystem ts
UnGlueElem u ts -> CTT.UnGlueElem <$> resolveExp u <*> resolveSystem ts
_ -> do
modName <- asks envModule
throwError ("Could not resolve " ++ show e ++ " in module " ++ modName)
resolveWhere :: ExpWhere -> Resolver Ter
resolveWhere = resolveExp . unWhere
resolveSystem :: System -> Resolver (C.System Ter)
resolveSystem (System ts) = do
ts' <- sequence [ (,) <$> resolveFace alpha <*> resolveExp u
| Side alpha u <- ts ]
let alphas = map fst ts'
unless (nub alphas == alphas) $
throwError $ "system contains same face multiple times: " ++
C.showListSystem ts'
-- Note: the symbols in alpha are in scope in u, but they mean 0 or 1
return $ Map.fromList ts'
resolveFace :: [Face] -> Resolver C.Face
resolveFace alpha =
Map.fromList <$> sequence [ (,) <$> resolveName i <*> resolveDir d
| Face i d <- alpha ]
resolveDir :: Dir -> Resolver C.Dir
resolveDir Dir0 = return 0
resolveDir Dir1 = return 1
resolveFormula :: Formula -> Resolver C.Formula
resolveFormula (Dir d) = C.Dir <$> resolveDir d
resolveFormula (Atom i) = C.Atom <$> resolveName i
resolveFormula (Neg phi) = negFormula <$> resolveFormula phi
resolveFormula (Conj phi _ psi) =
andFormula <$> resolveFormula phi <*> resolveFormula psi
resolveFormula (Disj phi psi) =
orFormula <$> resolveFormula phi <*> resolveFormula psi
resolveBranch :: Branch -> Resolver CTT.Branch
resolveBranch (OBranch (AIdent (_,lbl)) args e) = do
re <- local (insertAIdents args) $ resolveWhere e
return $ CTT.OBranch lbl (map unAIdent args) re
resolveBranch (PBranch (AIdent (_,lbl)) args is e) = do
re <- local (insertNames is . insertAIdents args) $ resolveWhere e
let names = map (C.Name . unAIdent) is
return $ CTT.PBranch lbl (map unAIdent args) names re
resolveTele :: [(Ident,Exp)] -> Resolver CTT.Tele
resolveTele [] = return []
resolveTele ((i,d):t) =
((i,) <$> resolveExp d) <:> local (insertVar i) (resolveTele t)
resolveLabel :: [(Ident,SymKind)] -> Label -> Resolver CTT.Label
resolveLabel _ (OLabel n vdecl) =
CTT.OLabel (unAIdent n) <$> resolveTele (flattenTele vdecl)
resolveLabel cs (PLabel n vdecl is sys) = do
let tele' = flattenTele vdecl
ts = map fst tele'
names = map (C.Name . unAIdent) is
n' = unAIdent n
cs' = delete (n',PConstructor) cs
CTT.PLabel n' <$> resolveTele tele' <*> pure names
<*> local (insertNames is . insertIdents cs' . insertVars ts)
(resolveSystem sys)
-- Resolve a non-mutual declaration; returns resolver for type and
-- body separately
resolveNonMutualDecl :: Decl -> (Ident,Resolver CTT.Ter
,Resolver CTT.Ter,[(Ident,SymKind)])
resolveNonMutualDecl d = case d of
DeclDef (AIdent (_,f)) tele t body ->
let tele' = flattenTele tele
a = binds CTT.Pi tele' (resolveExp t)
d = lams tele' (local (insertVar f) $ resolveWhere body)
in (f,a,d,[(f,Variable)])
DeclData x tele sums -> resolveDeclData x tele sums null
DeclHData x tele sums ->
resolveDeclData x tele sums (const False) -- always pick HSum
DeclSplit (AIdent (l,f)) tele t brs ->
let tele' = flattenTele tele
vars = map fst tele'
a = binds CTT.Pi tele' (resolveExp t)
d = do
loc <- getLoc l
ty <- local (insertVars vars) $ resolveExp t
brs' <- local (insertVars (f:vars)) (mapM resolveBranch brs)
lams tele' (return $ CTT.Split f loc ty brs')
in (f,a,d,[(f,Variable)])
DeclUndef (AIdent (l,f)) tele t ->
let tele' = flattenTele tele
a = binds CTT.Pi tele' (resolveExp t)
d = CTT.Undef <$> getLoc l <*> a
in (f,a,d,[(f,Variable)])
-- Helper function to resolve data declarations. The predicate p is
-- used to decide if we should use Sum or HSum.
resolveDeclData :: AIdent -> [Tele] -> [Label] -> ([(Ident,SymKind)] -> Bool) ->
(Ident, Resolver Ter, Resolver Ter, [(Ident, SymKind)])
resolveDeclData (AIdent (l,f)) tele sums p =
let tele' = flattenTele tele
a = binds CTT.Pi tele' (return CTT.U)
cs = [ (unAIdent lbl,Constructor) | OLabel lbl _ <- sums ]
pcs = [ (unAIdent lbl,PConstructor) | PLabel lbl _ _ _ <- sums ]
sum = if p pcs then CTT.Sum else CTT.HSum
d = lams tele' $ local (insertVar f) $
sum <$> getLoc l <*> pure f
<*> mapM (resolveLabel (cs ++ pcs)) sums
in (f,a,d,(f,Variable):cs ++ pcs)
resolveRTele :: [Ident] -> [Resolver CTT.Ter] -> Resolver CTT.Tele
resolveRTele [] _ = return []
resolveRTele (i:is) (t:ts) = do
a <- t
as <- local (insertVar i) (resolveRTele is ts)
return ((i,a):as)
-- Resolve a declaration
resolveDecl :: Decl -> Resolver (CTT.Decls,[(Ident,SymKind)])
resolveDecl d = case d of
DeclMutual decls -> do
let (fs,ts,bs,nss) = unzip4 $ map resolveNonMutualDecl decls
ns = concat nss -- TODO: some sanity checks? Duplicates!?
when (nub (map fst ns) /= concatMap (map fst) nss) $
throwError ("Duplicated constructor or ident: " ++ show nss)
as <- resolveRTele fs ts
-- The bodies know about all the names and constructors in the
-- mutual block
ds <- sequence $ map (local (insertIdents ns)) bs
let ads = zipWith (\ (x,y) z -> (x,(y,z))) as ds
return (CTT.MutualDecls ads,ns)
DeclOpaque i -> do
resolveVar i
return (CTT.OpaqueDecl (unAIdent i), [])
DeclTransparent i -> do
resolveVar i
return (CTT.TransparentDecl (unAIdent i), [])
DeclTransparentAll -> return (CTT.TransparentAllDecl, [])
_ -> do let (f,typ,body,ns) = resolveNonMutualDecl d
a <- typ
d <- body
return (CTT.MutualDecls [(f,(a,d))],ns)
resolveDecls :: [Decl] -> Resolver ([CTT.Decls],[(Ident,SymKind)])
resolveDecls [] = return ([],[])
resolveDecls (d:ds) = do
(rtd,names) <- resolveDecl d
(rds,names') <- local (insertIdents names) $ resolveDecls ds
return (rtd : rds, names' ++ names)
resolveModule :: Module -> Resolver ([CTT.Decls],[(Ident,SymKind)])
resolveModule (Module (AIdent (_,n)) _ decls) =
local (updateModule n) $ resolveDecls decls
resolveModules :: [Module] -> Resolver ([CTT.Decls],[(Ident,SymKind)])
resolveModules [] = return ([],[])
resolveModules (mod:mods) = do
(rmod, names) <- resolveModule mod
(rmods,names') <- local (insertIdents names) $ resolveModules mods
return (rmod ++ rmods, names' ++ names)