0 | module Language.Reflection.Types
5 | import Data.Vect.Quantifiers
6 | import Language.Reflection
7 | import Language.Reflection.Syntax
9 | %language ElabReflection
30 | freshNames : String -> (n : Nat) -> Vect n Name
34 | go : Nat -> (k : Nat) -> Vect k Name
36 | go m (S k) = (UN $
Basic $
s ++ show m) :: go (S m) k
39 | implicits : Foldable t => t Name -> List Arg
40 | implicits = map erasedImplicit . toList
47 | -> {0 p : a -> Type}
48 | -> {auto _ : Applicative f}
49 | -> ((v : a) -> f (p v))
52 | tryAll g [] = pure []
53 | tryAll g (x :: xs) = [| g x :: tryAll g xs |]
60 | data MissingInfo : PiInfo TTImp -> Type where
61 | Auto : MissingInfo AutoImplicit
62 | Implicit : MissingInfo ImplicitArg
63 | Deflt : MissingInfo (DefImplicit t)
66 | Uninhabited (MissingInfo ExplicitArg) where
67 | uninhabited Auto
impossible
68 | uninhabited Implicit
impossible
69 | uninhabited Deflt
impossible
77 | data AppArg : Arg -> Type where
79 | NamedApp : (n : Name) -> TTImp -> AppArg (MkArg c p (Just n) t)
82 | AutoApp : TTImp -> AppArg (MkArg c AutoImplicit n t)
85 | Regular : TTImp -> AppArg (MkArg c ExplicitArg n t)
88 | Missing : MissingInfo p -> AppArg (MkArg c p n t)
91 | (.ttimp) : AppArg a -> TTImp
92 | (.ttimp) (NamedApp nm s) = s
93 | (.ttimp) (Regular s) = s
94 | (.ttimp) (AutoApp s) = s
95 | (.ttimp) (Missing x) = implicitFalse
99 | appArg : TTImp -> AppArg a -> TTImp
100 | appArg t (NamedApp nm s) = namedApp t nm s
101 | appArg t (AutoApp s) = autoApp t s
102 | appArg t (Regular s) = app t s
103 | appArg t (Missing _) = t
107 | 0 AppArgs : Vect n Arg -> Type
108 | AppArgs = All AppArg
110 | unappVia : (TTImp -> Maybe (a, TTImp)) -> TTImp -> Maybe (a,TTImp)
111 | unappVia f s = case f s of
113 | Nothing => case s of
114 | IApp fc t u => map (\t' => IApp fc t' u) <$> unappVia f t
115 | INamedApp fc t nm u => map (\t' => INamedApp fc t' nm u) <$> unappVia f t
116 | IAutoApp fc t u => map (\t' => IAutoApp fc t' u) <$> unappVia f t
120 | named : (n : Name) -> TTImp -> Maybe (AppArg (MkArg c p (Just n) t), TTImp)
123 | INamedApp fc t nm u =>
124 | if n == nm then Just (NamedApp n u, t) else Nothing
128 | getAuto : TTImp -> Maybe (AppArg (MkArg c AutoImplicit n t), TTImp)
129 | getAuto = unappVia $
\case
130 | IAutoApp fc t u => Just (AutoApp u, t)
134 | regular : TTImp -> Maybe (AppArg (MkArg c ExplicitArg n t), TTImp)
135 | regular = unappVia $
\case
136 | IApp fc t u => Just (Regular u, t)
139 | unnamed : (p : PiInfo TTImp) -> TTImp -> Maybe (AppArg (MkArg c p n t), TTImp)
140 | unnamed ExplicitArg s = regular s
141 | unnamed ImplicitArg s = Just (Missing Implicit, s)
142 | unnamed (DefImplicit x) s = Just (Missing Deflt, s)
143 | unnamed AutoImplicit s = getAuto s <|> Just (Missing Auto, s)
148 | getArg : (arg : Arg) -> TTImp -> Maybe (AppArg arg , TTImp)
149 | getArg (MkArg _ pi Nothing _) s = unnamed pi s
150 | getArg (MkArg _ pi (Just n) _) s = named n s <|> unnamed pi s
152 | argErr : Arg -> String
153 | argErr (MkArg _ _ (Just n) _) = "Missing explicit argument: \{n}"
154 | argErr (MkArg _ _ Nothing t) =
155 | "Missing unnamed, explicit argument of type: \{show t}"
160 | getArgs : (vs : Vect n Arg) -> TTImp -> Res (AppArgs vs, TTImp)
161 | getArgs (x :: xs) s =
162 | let Right (vs,s2) := getArgs xs s | Left err => Left err
163 | Just (v,s3) := getArg x s2 | Nothing => Left $
argErr x
164 | in Right (v :: vs, s3)
165 | getArgs [] s = Right ([], s)
174 | record Con (n : Nat) (vs : Vect n Arg) where
178 | args : Vect arty Arg
179 | typeArgs : AppArgs vs
181 | public export %inline
182 | Named (Con n vs) where
187 | isConstant : Con n vs -> Bool
188 | isConstant c = all isErased c.args
197 | bindCon : (c : Con n vs) -> Vect c.arty Name -> TTImp
198 | bindCon c ns = go c.nameVar (map piInfo c.args) ns
201 | go : TTImp -> Vect k (PiInfo TTImp) -> Vect k Name -> TTImp
203 | go t (ExplicitArg :: xs) (n :: ns) = go (t `app` bindVar n) xs ns
204 | go t (_ :: xs) (n :: ns) = go t xs ns
208 | applyCon : (c : Con n vs) -> Vect c.arty Name -> TTImp
209 | applyCon c ns = go c.nameVar (map piInfo c.args) ns
212 | go : TTImp -> Vect k (PiInfo TTImp) -> Vect k Name -> TTImp
214 | go t (ExplicitArg :: xs) (n :: ns) = go (t `app` var n) xs ns
215 | go t (_ :: xs) (n :: ns) = go t xs ns
220 | getCon : Elaboration m => (vs : Vect n Arg) -> Name -> m (Con n vs)
222 | (n',tt) <- lookupName n
223 | let (args,tpe) := unPi tt
224 | (
arty ** vargs)
:= (
length args ** Vect.fromList args)
225 | case getArgs vs tpe of
226 | Right (vs, IVar _ _) => pure $
(MkCon n' arty vargs vs)
227 | Right (vs, _) => fail "Unexpected type for constructor \{n}"
228 | Left err => fail "Unexpected type for constructor \{n}: \{err}"
238 | record TypeInfo where
239 | constructor MkTypeInfo
242 | args : Vect arty Arg
243 | argNames : Vect arty Name
244 | cons : List (Con arty args)
246 | public export %inline
247 | Named TypeInfo where
251 | namedArg : (a : Arg) -> Maybe Name
252 | namedArg (MkArg _ _ (Just n) _) = Just n
253 | namedArg _ = Nothing
257 | (.explicitArgs) : TypeInfo -> List Name
258 | (.explicitArgs) p = go Lin p.args p.argNames
261 | go : SnocList Name -> Vect k Arg -> Vect k Name -> List Name
262 | go sn [] [] = sn <>> []
263 | go sn (MkArg _ ExplicitArg _ _ :: xs) (n :: ns) = go (sn :< n) xs ns
264 | go sn (_ :: xs) (n :: ns) = go sn xs ns
269 | (.applied) : TypeInfo -> TTImp
270 | (.applied) p = go p.nameVar p.args p.argNames
273 | go : TTImp -> Vect n Arg -> Vect n Name -> TTImp
275 | go t (MkArg _ AutoImplicit _ _ :: xs) (_ :: nms) = go t xs nms
276 | go t (MkArg _ _ (Just no) _ :: xs) (nm :: nms) =
277 | go (namedApp t no (var nm)) xs nms
278 | go t (MkArg _ _ Nothing _ :: xs) (nm :: nms) =
279 | go (t `app` var nm) xs nms
283 | public export %inline
284 | (.implicits) : TypeInfo -> List Arg
285 | (.implicits) p = go Lin p.args
288 | toArg : Maybe Name -> TTImp -> Arg
289 | toArg mn (IHole _ _) = MkArg M0 ImplicitArg mn implicitFalse
290 | toArg mn t = MkArg M0 ImplicitArg mn t
292 | go : SnocList Arg -> Vect k Arg -> List Arg
293 | go sn [] = sn <>> []
294 | go sn (MkArg _ ExplicitArg mn t :: xs) = go (sn :< toArg mn t) xs
295 | go sn (MkArg _ ImplicitArg mn t :: xs) = go (sn :< toArg mn t) xs
296 | go sn (_ :: xs) = go sn xs
302 | isEnum : TypeInfo -> Bool
303 | isEnum ti = all isConstant $
ti.cons
307 | isNil : Con n vs -> Bool
308 | isNil (MkCon n _ as _) = isNil n && all (not . isExplicit) as
313 | isCons : Con n vs -> Bool
314 | isCons (MkCon n _ as _) = isCons n && count isExplicit as == 2
318 | isLin : Con n vs -> Bool
319 | isLin (MkCon n _ as _) = isLin n && all (not . isExplicit) as
324 | isSnoc : Con n vs -> Bool
325 | isSnoc (MkCon n _ as _) = isSnoc n && count isExplicit as == 2
330 | isNewtype : TypeInfo -> Bool
331 | isNewtype (MkTypeInfo _ _ _ _ [c]) = count (not . isErased) c.args == 1
332 | isNewtype _ = False
338 | isListLike : TypeInfo -> Bool
339 | isListLike (MkTypeInfo _ _ _ _ [x,y]) = isNil x && isCons y || isCons x && isNil y
340 | isListLike _ = False
346 | isSnocListLike : TypeInfo -> Bool
347 | isSnocListLike (MkTypeInfo _ _ _ _ [x,y]) =
348 | isLin x && isSnoc y || isSnoc x && isLin y
349 | isSnocListLike _ = False
354 | isErased : TypeInfo -> Bool
355 | isErased (MkTypeInfo _ _ _ _ [c]) = isConstant c
362 | getInfo' : Elaboration m => Name -> m TypeInfo
364 | (n',tt) <- lookupName n
365 | (args,IType _) <- pure $
unPi tt
366 | | (_,_) => fail "Type declaration does not end in IType: \{show tt}"
368 | let (
arty ** vargs)
:= (
length args ** Vect.fromList args)
369 | Just nargs <- pure $
traverse name vargs
370 | | Nothing => fail "\{n'} has unnamed type arguments"
371 | conNames <- getCons n'
372 | cons <- traverse (getCon vargs) conNames
373 | pure (MkTypeInfo n' arty vargs nargs cons)
377 | getInfo : Name -> Elab TypeInfo
385 | singleCon : Name -> Elab Name
387 | (MkTypeInfo _ _ _ _ [c]) <- getInfo' n
388 | | _ => fail "\{n} is not a single-constructor data type"
396 | data ParamTag : Nat -> Type where
401 | data ParamPattern : (typeArgs, params : Nat) -> Type where
402 | Nil : ParamPattern 0 0
403 | (::) : ParamTag k -> ParamPattern m n -> ParamPattern (S m) (k + n)
406 | paramsOnly : (k : Nat) -> ParamPattern k k
408 | paramsOnly (S k) = P :: paramsOnly k
411 | indicesOnly : (k : Nat) -> ParamPattern k 0
413 | indicesOnly (S k) = I :: indicesOnly k
416 | extractParams : ParamPattern n k -> (vs : Vect n a) -> Vect k a
417 | extractParams [] [] = []
418 | extractParams (I :: ps) (x :: xs) = extractParams ps xs
419 | extractParams (P :: ps) (x :: xs) = x :: extractParams ps xs
424 | data PArg : (n : Nat) -> Type where
425 | PPar : Fin n -> PArg n
426 | PVar : Name -> PArg n
427 | PLam : Count -> PiInfo TTImp -> Maybe Name -> PArg n -> PArg n -> PArg n
428 | PApp : (x,y : PArg n) -> PArg n
429 | PNamedApp : PArg n -> Name -> PArg n -> PArg n
430 | PAutoApp : PArg n -> PArg n -> PArg n
431 | PWithApp : PArg n -> PArg n -> PArg n
432 | PSearch : Nat -> PArg n
433 | PPrim : Constant -> PArg n
434 | PDelayed : LazyReason -> PArg n -> PArg n
436 | PHole : String -> PArg n
441 | PPar x == PPar y = x == y
442 | PVar x == PVar y = x == y
443 | PApp x y == PApp v w = x == v && y == w
444 | PLam c p m u v == PLam d q n x y =
445 | c == d && p == q && m == n && u == x && v == y
446 | PNamedApp x m y == PNamedApp v n w = x == v && m == n && y == w
447 | PAutoApp x y == PAutoApp v w = x == v && y == w
448 | PWithApp x y == PWithApp v w = x == v && y == w
449 | PSearch c == PSearch d = c == d
450 | PPrim c == PPrim d = c == d
451 | PDelayed lr x == PDelayed lr2 y = lr == lr2 && x == y
452 | PType == PType = True
453 | PHole c == PHole d = c == d
459 | pvar : Named a => Vect n a -> (bound : List Name) -> Name -> PArg n
460 | pvar xs bound nm = case findIndex (\v => nm == v.getName) xs of
461 | Just ix => if nm `elem` bound then PVar nm else PPar ix
467 | parg : Named a => Vect n a -> (bound : List Name) -> TTImp -> Res (PArg n)
468 | parg xs b (IVar _ nm) = Right $
pvar xs b nm
469 | parg xs b (IApp _ s t) = PApp <$> parg xs b s <*> parg xs b t
470 | parg xs b (INamedApp _ s n t) = PNamedApp <$> parg xs b s <*> pure n <*> parg xs b t
471 | parg xs b (IAutoApp _ s t) = PAutoApp <$> parg xs b s <*> parg xs b t
472 | parg xs b (IWithApp _ s t) = PWithApp <$> parg xs b s <*> parg xs b t
473 | parg xs b (IDelayed _ lr s) = PDelayed lr <$> parg xs b s
474 | parg xs b (IPrimVal _ c) = Right $
PPrim c
475 | parg xs b (IType _) = Right PType
476 | parg xs b (ISearch _ n) = Right $
PSearch n
477 | parg xs b (IHole _ n) = Right $
PHole n
478 | parg xs b (ILam _ c p n x y) =
479 | [| PLam (pure c) (pure p) (pure n) (parg xs b x) (parg xs (toList n ++ b) y) |]
481 | Left "\{show t} is not a valid constructor argument type"
487 | ttimp : Vect n Name -> PArg n -> TTImp
488 | ttimp ns (PPar x) = var (index x ns)
489 | ttimp ns (PVar nm) = var nm
490 | ttimp ns (PApp x y) = ttimp ns x `app` ttimp ns y
491 | ttimp ns (PNamedApp x n y) = INamedApp EmptyFC (ttimp ns x) n (ttimp ns y)
492 | ttimp ns (PAutoApp x y) = IAutoApp EmptyFC (ttimp ns x) (ttimp ns y)
493 | ttimp ns (PWithApp x y) = IWithApp EmptyFC (ttimp ns x) (ttimp ns y)
494 | ttimp ns (PPrim c) = primVal c
495 | ttimp ns (PDelayed lr x) = IDelayed EmptyFC lr (ttimp ns x)
496 | ttimp ns (PSearch n) = ISearch EmptyFC n
497 | ttimp ns PType = IType EmptyFC
498 | ttimp ns (PHole n) = IHole EmptyFC n
499 | ttimp ns (PLam c p n x y) = ILam EmptyFC c p n (ttimp ns x) (ttimp ns y)
508 | paramArgs : PArg n -> List (PArg n)
509 | paramArgs (PPar x) = [PPar x]
510 | paramArgs (PVar nm) = []
511 | paramArgs p@(PApp (PPar _) y) = [p]
512 | paramArgs p@(PAutoApp (PPar _) y) = [p]
513 | paramArgs p@(PWithApp (PPar _) y) = [p]
514 | paramArgs p@(PNamedApp (PPar _) n y) = [p]
515 | paramArgs (PLam _ _ _ _ y) = paramArgs y
516 | paramArgs (PApp x y) = nub $
paramArgs x ++ paramArgs y
517 | paramArgs (PAutoApp x y) = nub $
paramArgs x ++ paramArgs y
518 | paramArgs (PWithApp x y) = nub $
paramArgs x ++ paramArgs y
519 | paramArgs (PNamedApp x n y) = nub $
paramArgs x ++ paramArgs y
520 | paramArgs (PPrim c) = []
521 | paramArgs (PDelayed lr x) = paramArgs x
522 | paramArgs PType = []
523 | paramArgs (PSearch _) = []
524 | paramArgs (PHole _) = []
528 | {0 vs : Vect n Arg}
529 | -> ParamPattern n k
531 | -> Res (Vect k Name)
532 | paramNames [] [] = Right []
533 | paramNames (I :: ps) (v :: vs) = paramNames ps vs
534 | paramNames (P :: ps) (v :: vs) = case v.ttimp of
535 | IVar _ nm => (nm ::) <$> paramNames ps vs
536 | t => Left "\{show t} is not a parameter"
540 | data ConArg : (n : Nat) -> Type where
541 | ParamArg : Fin n -> TTImp -> ConArg n
542 | CArg : Maybe Name -> Count -> PiInfo TTImp -> PArg n -> ConArg n
545 | isExplicit : ConArg n -> Bool
546 | isExplicit (CArg mnm rig ExplicitArg x) = True
547 | isExplicit _ = False
550 | conArg : Vect n Name -> Arg -> Res (ConArg n)
551 | conArg ns (MkArg M0 ImplicitArg (Just nm) t) = case findIndex (nm ==) ns of
552 | Just ix => Right $
ParamArg ix t
553 | Nothing => CArg (Just nm) M0 ImplicitArg <$> parg ns Nil t
554 | conArg ns (MkArg c pi nm t) = CArg nm c pi <$> parg ns Nil t
558 | paramArgs : ConArg n -> List (PArg n)
559 | paramArgs (ParamArg _ _) = []
560 | paramArgs (CArg _ _ _ t) = paramArgs t
563 | record ParamCon (n : Nat) where
564 | constructor MkParamCon
567 | args : Vect arty (ConArg n)
571 | paramArgs : ParamCon n -> List (PArg n)
572 | paramArgs c = nub $
toList c.args >>= paramArgs
575 | Named (ParamCon n) where
579 | paramCon : ParamPattern n k -> Con n vs -> Res (ParamCon k)
580 | paramCon ps (MkCon name arty args typeArgs) = do
581 | params <- paramNames ps typeArgs
582 | conArgs <- traverse (conArg params) args
583 | pure $
MkParamCon name arty conArgs
586 | record ParamTypeInfo where
587 | constructor MkParamTypeInfo
593 | pattern : ParamPattern info.arty numParams
596 | paramNames : Vect numParams Name
599 | cons : List (ParamCon numParams)
609 | pargs : List (PArg numParams)
612 | Named ParamTypeInfo where
613 | p.getName = p.info.name
616 | paramType : (ti : TypeInfo) -> ParamPattern ti.arty k -> Res ParamTypeInfo
617 | paramType ti@(MkTypeInfo nm n vs ns cs) ps = do
618 | cons <- traverse (paramCon ps) cs
619 | pure $
MkParamTypeInfo ti ps (extractParams ps ns) cons (nub $
cons >>= paramArgs)
626 | constraints : ParamTypeInfo -> (iname : Name) -> List Arg
627 | constraints p iname = map (toCon p.paramNames) p.pargs
628 | where toCon : Vect k Name -> PArg k -> Arg
629 | toCon ns pa = MkArg MW AutoImplicit Nothing . (app $
var iname) $
632 | namespace ParamTypeInfo
636 | (.applied) : ParamTypeInfo -> TTImp
637 | (.applied) p = p.info.applied
641 | public export %inline
642 | (.implicits) : ParamTypeInfo -> List Arg
643 | (.implicits) p = p.info.implicits
646 | public export %inline
647 | allImplicits : (p : ParamTypeInfo) -> (iname : Name) -> List Arg
648 | allImplicits p iname = p.implicits ++ constraints p iname
656 | {auto _ : Elaboration m}
659 | getParamInfo' n = do
661 | case paramType ti (paramsOnly ti.arty) of
662 | Right pt => pure pt
663 | Left err => fail "Type \{n} is not supported: \{err}"
667 | getParamInfo : Name -> Elab ParamTypeInfo
668 | getParamInfo = getParamInfo'