0 | module TTImp.Elab.Binders
7 | import Idris.REPL.Opts
10 | import TTImp.Elab.Check
11 | import TTImp.Elab.Delayed
14 | import Libraries.Data.IntMap
22 | dropName : Name -> NestedNames vars -> NestedNames vars
23 | dropName n nest = { names $= drop } nest
25 | drop : List (Name, a) -> List (Name, a)
28 | = if x == n then drop xs
29 | else (x, y) :: drop xs
31 | checkPiInfo : {vars : _} ->
32 | {auto c : Ref Ctxt Defs} ->
33 | {auto m : Ref MD Metadata} ->
34 | {auto u : Ref UST UState} ->
35 | {auto e : Ref EST (EState vars)} ->
36 | {auto s : Ref Syn SyntaxInfo} ->
37 | {auto o : Ref ROpts REPLOpts} ->
38 | RigCount -> ElabInfo -> NestedNames vars -> Env Term vars ->
39 | PiInfo RawImp -> (expTy : Maybe (Glued vars)) ->
40 | Core (PiInfo (Term vars))
41 | checkPiInfo rig elabinfo nest env Explicit exp = pure Explicit
42 | checkPiInfo rig elabinfo nest env Implicit exp = pure Implicit
43 | checkPiInfo rig elabinfo nest env AutoImplicit exp = pure AutoImplicit
44 | checkPiInfo rig elabinfo nest env (DefImplicit t) exp
45 | = do (tv, _) <- check rig elabinfo nest env t exp
46 | pure (DefImplicit tv)
49 | checkPi : {vars : _} ->
50 | {auto c : Ref Ctxt Defs} ->
51 | {auto m : Ref MD Metadata} ->
52 | {auto u : Ref UST UState} ->
53 | {auto e : Ref EST (EState vars)} ->
54 | {auto s : Ref Syn SyntaxInfo} ->
55 | {auto o : Ref ROpts REPLOpts} ->
56 | RigCount -> ElabInfo ->
57 | NestedNames vars -> Env Term vars ->
59 | RigCount -> PiInfo RawImp -> (n : Name) ->
60 | (argTy : RawImp) -> (retTy : RawImp) ->
61 | (expTy : Maybe (Glued vars)) ->
62 | Core (Term vars, Glued vars)
63 | checkPi rig elabinfo nest env fc rigf info n argTy retTy expTy
64 | = do let pirig = getRig (elabMode elabinfo)
66 | (tyv, tyt) <- check pirig elabinfo nest env argTy
67 | (Just (gType fc tyu))
68 | info' <- checkPiInfo rigf elabinfo nest env info (Just (gnf env tyv))
69 | let env' : Env Term (n :: _) = Pi fc rigf info' tyv :: env
70 | let nest' = weaken (dropName n nest)
73 | inScope fc env' (\e' =>
74 | check {e=e'} pirig elabinfo nest' env' retTy (Just (gType fc scu)))
77 | checkExp rig elabinfo env fc (Bind fc n (Pi (getFC argTy) rigf info' tyv) scopev) (gType fc piu) expTy
81 | getRig : ElabMode -> RigCount
82 | getRig (InLHS _) = rig
85 | findLamRig : {auto c : Ref Ctxt Defs} ->
86 | Maybe (Glued vars) -> Core RigCount
87 | findLamRig Nothing = pure top
88 | findLamRig (Just expty)
89 | = do tynf <- getNF expty
91 | NBind _ _ (Pi _ c _ _) sc => pure c
94 | inferLambda : {vars : _} ->
95 | {auto c : Ref Ctxt Defs} ->
96 | {auto m : Ref MD Metadata} ->
97 | {auto u : Ref UST UState} ->
98 | {auto e : Ref EST (EState vars)} ->
99 | {auto s : Ref Syn SyntaxInfo} ->
100 | {auto o : Ref ROpts REPLOpts} ->
101 | RigCount -> ElabInfo ->
102 | NestedNames vars -> Env Term vars ->
104 | RigCount -> PiInfo RawImp -> (n : Name) ->
105 | (argTy : RawImp) -> (scope : RawImp) ->
106 | (expTy : Maybe (Glued vars)) ->
107 | Core (Term vars, Glued vars)
108 | inferLambda rig elabinfo nest env fc rigl info n argTy scope expTy
109 | = do rigb_in <- findLamRig expTy
110 | let rigb = rigb_in `glb` rigl
112 | (tyv, tyt) <- check erased elabinfo nest env argTy (Just (gType fc u))
113 | info' <- checkPiInfo rigl elabinfo nest env info (Just (gnf env tyv))
114 | let env' : Env Term (n :: _) = Lam fc rigb info' tyv :: env
115 | let nest' = weaken (dropName n nest)
116 | (scopev, scopet) <- inScope fc env' (\e' =>
117 | check {e=e'} rig elabinfo
118 | nest' env' scope Nothing)
119 | let lamty = gnf env (Bind fc n (Pi fc rigb info' tyv) !(getTerm scopet))
120 | logGlue "elab.binder" 5 "Inferred lambda type" lamty
122 | (logGlueNF "elab.binder" 5 "Expected lambda type" env) expTy
123 | checkExp rig elabinfo env fc
124 | (Bind fc n (Lam fc rigb info' tyv) scopev)
127 | getTyNF : {vars : _} ->
128 | {auto c : Ref Ctxt Defs} ->
129 | Env Term vars -> Term vars -> Core (Term vars)
130 | getTyNF env x@(Bind {}) = pure x
132 | = do defs <- get Ctxt
133 | xnf <- nf defs env x
134 | empty <- clearDefs defs
135 | quote empty env xnf
141 | isResolved : IntMap Constraint -> (constraintId : Int) -> Bool
142 | isResolved constraints key
143 | = case lookup key constraints of
144 | Just Resolved => True
148 | checkLambda : {vars : _} ->
149 | {auto c : Ref Ctxt Defs} ->
150 | {auto m : Ref MD Metadata} ->
151 | {auto u : Ref UST UState} ->
152 | {auto e : Ref EST (EState vars)} ->
153 | {auto s : Ref Syn SyntaxInfo} ->
154 | {auto o : Ref ROpts REPLOpts} ->
155 | RigCount -> ElabInfo ->
156 | NestedNames vars -> Env Term vars ->
158 | RigCount -> PiInfo RawImp -> (n : Name) ->
159 | (argTy : RawImp) -> (scope : RawImp) ->
160 | (expTy : Maybe (Glued vars)) ->
161 | Core (Term vars, Glued vars)
162 | checkLambda rig_in elabinfo nest env fc rigl info n argTy scope Nothing
163 | = let rig = if isErased rig_in then erased else linear in
164 | inferLambda rig elabinfo nest env fc rigl info n argTy scope Nothing
165 | checkLambda rig_in elabinfo nest env fc rigl info n argTy scope (Just expty_in)
166 | = do let rig = if isErased rig_in then erased else linear
167 | let solvemode = case elabMode elabinfo of
170 | solveConstraints solvemode Normal
171 | expty <- getTerm expty_in
172 | exptynf <- getTyNF env expty
175 | Bind bfc bn (Pi fc' c _ pty) psc =>
177 | (tyv, tyt) <- check erased elabinfo nest env
178 | argTy (Just (gType fc u))
179 | info' <- checkPiInfo rigl elabinfo nest env info (Just (gnf env tyv))
180 | let originalPiType = Bind fc bn (Pi fc' c info' pty) psc
181 | let rigb = rigl `glb` c
182 | let env' : Env Term (n :: _) = Lam fc rigb info' tyv :: env
183 | lambdaUnifyResult <- convert fc elabinfo env (gnf env tyv) (gnf env pty)
184 | let nest' = weaken (dropName n nest)
185 | pscnf <- normaliseHoles defs env' $
compat psc
186 | (scopev, scopet) <-
187 | inScope fc env' (\e' =>
188 | check {e=e'} rig elabinfo nest' env' scope
189 | (Just $
gnf env' pscnf))
190 | let elaboratedPiType = Bind fc n (Pi fc' rigb info' tyv) !(getTerm scopet)
191 | logTermNF "elab.binder" 10 "Lambda type" env exptynf
192 | logGlueNF "elab.binder" 10 "Got scope type" env' scopet
197 | log "metadata.names" 7 "checkLambda is adding ↓"
198 | addNameType fc n env pty
203 | throw (CantConvert fc (gamma defs) env
206 | let lamTerm = Bind fc n (Lam fc' rigb info' tyv) scopev
207 | let lamType = gnf env elaboratedPiType
208 | let lambdaConstraints = constraints lambdaUnifyResult
210 | allCs <- constraints <$> get UST
211 | let prunedConstraints = filter (not . isResolved allCs) lambdaConstraints
212 | if null prunedConstraints
213 | then pure (lamTerm, lamType)
214 | else do ctm <- newConstant fc rig env lamTerm lamTerm prunedConstraints
215 | pure (ctm, lamType)
216 | _ => inferLambda rig elabinfo nest env fc rigl info n argTy scope (Just expty_in)
218 | weakenExp : {x, vars : _} ->
219 | Env Term (x :: vars) ->
220 | Maybe (Glued vars) -> Core (Maybe (Glued (x :: vars)))
221 | weakenExp env Nothing = pure Nothing
222 | weakenExp env (Just gtm)
223 | = do tm <- getTerm gtm
224 | pure (Just (gnf env (weaken tm)))
227 | checkLet : {vars : _} ->
228 | {auto c : Ref Ctxt Defs} ->
229 | {auto m : Ref MD Metadata} ->
230 | {auto u : Ref UST UState} ->
231 | {auto e : Ref EST (EState vars)} ->
232 | {auto s : Ref Syn SyntaxInfo} ->
233 | {auto o : Ref ROpts REPLOpts} ->
234 | RigCount -> ElabInfo ->
235 | NestedNames vars -> Env Term vars ->
236 | FC -> (lhsFC : FC) -> RigCount -> (n : Name) ->
237 | (nTy : RawImp) -> (nVal : RawImp) -> (scope : RawImp) ->
238 | (expTy : Maybe (Glued vars)) ->
239 | Core (Term vars, Glued vars)
240 | checkLet rigc_in elabinfo nest env fc lhsFC rigl n nTy nVal scope expty {vars}
241 | = do let rigc = if isErased rigc_in then erased else linear
243 | (tyv, tyt) <- check erased elabinfo nest env nTy (Just (gType fc u))
248 | (valv, valt, rigb) <- handle
249 | (do c <- runDelays (==CaseBlock) $
check (rigl |*| rigc)
250 | ({ preciseInf := True } elabinfo)
251 | nest env nVal (Just (gnf env tyv))
252 | pure (fst c, snd c, rigl |*| rigc))
253 | (\err => case linearErr err of
256 | (do c <- runDelays (==CaseBlock) $
check linear elabinfo
257 | nest env nVal (Just (gnf env tyv))
258 | pure (fst c, snd c, linear))
259 | (do c <- check (rigl |*| rigc)
261 | nest env nVal (Just (gnf env tyv))
262 | pure (fst c, snd c, rigMult rigl rigc))
264 | _ => do c <- check (rigl |*| rigc)
266 | nest env nVal (Just (gnf env tyv))
267 | pure (fst c, snd c, rigl |*| rigc))
268 | let env' : Env Term (n :: _) = Lam fc rigb Explicit tyv :: env
269 | let nest' = weaken (dropName n nest)
270 | expScope <- weakenExp env' expty
271 | (scopev, gscopet) <-
272 | inScope fc env' (\e' =>
273 | check {e=e'} rigc elabinfo nest' env' scope expScope)
274 | scopet <- getTerm gscopet
281 | log "metadata.names" 7 $
"checkLet is adding ↓"
282 | addNameType lhsFC n env tyv
284 | pure (Bind fc n (Let fc rigb valv tyv) scopev,
285 | gnf env (Bind fc n (Let fc rigb valv tyv) scopet))
287 | linearErr : Error -> Maybe RigCount
288 | linearErr (LinearMisuse _ _ r _) = Just r
289 | linearErr (InType _ _ e) = linearErr e
290 | linearErr (InCon _ e) = linearErr e
291 | linearErr (InLHS _ _ e) = linearErr e
292 | linearErr (InRHS _ _ e) = linearErr e
293 | linearErr _ = Nothing