on 4e4b7df help sign in
Idris-dev/src/Idris/Reflection.hs
1210 lines 55 kB history raw
1{-| Code related to Idris's reflection system. This module contains
2quoters and unquoters along with some supporting datatypes.
3-}
4{-# LANGUAGE PatternGuards, CPP #-}
5{-# OPTIONS_GHC -fwarn-incomplete-patterns -fwarn-unused-imports #-}
6module Idris.Reflection where
8#if __GLASGOW_HASKELL__ < 710
9import Control.Applicative ((<$>), (<*>), pure)
10import Prelude hiding (mapM)
11import Data.Traversable (mapM)
12#endif
13import Control.Monad (liftM, liftM2, liftM4)
14import Control.Monad.State.Strict (lift)
15import Data.Maybe (catMaybes)
16import Data.List ((\\), findIndex)
17import qualified Data.Text as T
19import Idris.Core.Elaborate (claim, fill, focus, getNameFrom, initElaborator,
20 movelast, runElab, solve)
21import Idris.Core.Evaluate (Def(TyDecl), initContext, lookupDefExact, lookupTyExact)
22import Idris.Core.TT
24import Idris.AbsSyntaxTree (ArgOpt(..),ElabD, IState(tt_ctxt, idris_implicits,idris_datatypes, idris_patdefs),
25 PArg'(..), PArg, PTactic, PTactic'(..), PTerm(..), Fixity (..),
26 initEState, pairCon, pairTy)
27import Idris.Delaborate (delab)
30data RErasure = RErased | RNotErased deriving Show
32data RPlicity = RExplicit | RImplicit | RConstraint deriving Show
34data RFunArg = RFunArg { argName :: Name
35 , argTy :: Raw
36 , argPlicity :: RPlicity
37 , erasure :: RErasure
38 }
39 deriving Show
41data RTyDecl = RDeclare Name [RFunArg] Raw deriving Show
43data RTyConArg = RParameter RFunArg
44 | RIndex RFunArg
45 deriving Show
47data RCtorArg = RCtorParameter RFunArg | RCtorField RFunArg deriving Show
49data RDatatype = RDatatype Name [RTyConArg] Raw [(Name, [RCtorArg], Raw)] deriving Show
51data RConstructorDefn = RConstructor Name [RFunArg] Raw
53data RDataDefn = RDefineDatatype Name [RConstructorDefn]
55rArgOpts :: RErasure -> [ArgOpt]
56rArgOpts RErased = [InaccessibleArg]
57rArgOpts _ = []
59rFunArgToPArg :: RFunArg -> PArg
60rFunArgToPArg (RFunArg n _ RExplicit e) = PExp 0 (rArgOpts e) n Placeholder
61rFunArgToPArg (RFunArg n _ RImplicit e) = PImp 0 False (rArgOpts e) n Placeholder
62rFunArgToPArg (RFunArg n _ RConstraint e) = PConstraint 0 (rArgOpts e) n Placeholder
64data RFunClause a = RMkFunClause a a
65 | RMkImpossibleClause a
66 deriving Show
68data RFunDefn a = RDefineFun Name [RFunClause a] deriving Show
70-- | Prefix a name with the "Language.Reflection" namespace
71reflm :: String -> Name
72reflm n = sNS (sUN n) ["Reflection", "Language"]
74-- | Prefix a name with the "Language.Reflection.Elab" namespace
75tacN :: String -> Name
76tacN str = sNS (sUN str) ["Elab", "Reflection", "Language"]
78-- | Reify tactics from their reflected representation
79reify :: IState -> Term -> ElabD PTactic
80reify _ (P _ n _) | n == reflm "Intros" = return Intros
81reify _ (P _ n _) | n == reflm "Trivial" = return Trivial
82reify _ (P _ n _) | n == reflm "Instance" = return TCInstance
83reify _ (P _ n _) | n == reflm "Solve" = return Solve
84reify _ (P _ n _) | n == reflm "Compute" = return Compute
85reify _ (P _ n _) | n == reflm "Skip" = return Skip
86reify _ (P _ n _) | n == reflm "SourceFC" = return SourceFC
87reify _ (P _ n _) | n == reflm "Unfocus" = return Unfocus
88reify ist t@(App _ _ _)
89 | (P _ f _, args) <- unApply t = reifyApp ist f args
90reify _ t = fail ("Unknown tactic " ++ show t)
92reifyApp :: IState -> Name -> [Term] -> ElabD PTactic
93reifyApp ist t [l, r] | t == reflm "Try" = liftM2 Try (reify ist l) (reify ist r)
94reifyApp _ t [Constant (I i)]
95 | t == reflm "Search" = return (ProofSearch True True i Nothing [] [])
96reifyApp _ t [x]
97 | t == reflm "Refine" = do n <- reifyTTName x
98 return $ Refine n []
99reifyApp ist t [n, ty] | t == reflm "Claim" = do n' <- reifyTTName n
100 goal <- reifyTT ty
101 return $ Claim n' (delab ist goal)
102reifyApp ist t [l, r] | t == reflm "Seq" = liftM2 TSeq (reify ist l) (reify ist r)
103reifyApp ist t [Constant (Str n), x]
104 | t == reflm "GoalType" = liftM (GoalType n) (reify ist x)
105reifyApp _ t [n] | t == reflm "Intro" = liftM (Intro . (:[])) (reifyTTName n)
106reifyApp ist t [t'] | t == reflm "Induction" = liftM (Induction . delab ist) (reifyTT t')
107reifyApp ist t [t'] | t == reflm "Case" = liftM (CaseTac . delab ist) (reifyTT t')
108reifyApp ist t [t']
109 | t == reflm "ApplyTactic" = liftM (ApplyTactic . delab ist) (reifyTT t')
110reifyApp ist t [t']
111 | t == reflm "Reflect" = liftM (Reflect . delab ist) (reifyTT t')
112reifyApp ist t [t']
113 | t == reflm "ByReflection" = liftM (ByReflection . delab ist) (reifyTT t')
114reifyApp _ t [t']
115 | t == reflm "Fill" = liftM (Fill . PQuote) (reifyRaw t')
116reifyApp ist t [t']
117 | t == reflm "Exact" = liftM (Exact . delab ist) (reifyTT t')
118reifyApp ist t [x]
119 | t == reflm "Focus" = liftM Focus (reifyTTName x)
120reifyApp ist t [t']
121 | t == reflm "Rewrite" = liftM (Rewrite . delab ist) (reifyTT t')
122reifyApp ist t [n, t']
123 | t == reflm "LetTac" = do n' <- reifyTTName n
124 t'' <- reifyTT t'
125 return $ LetTac n' (delab ist t')
126reifyApp ist t [n, tt', t']
127 | t == reflm "LetTacTy" = do n' <- reifyTTName n
128 tt'' <- reifyTT tt'
129 t'' <- reifyTT t'
130 return $ LetTacTy n' (delab ist tt'') (delab ist t'')
131reifyApp ist t [errs]
132 | t == reflm "Fail" = fmap TFail (reifyReportParts errs)
133reifyApp _ f args = fail ("Unknown tactic " ++ show (f, args)) -- shouldn't happen
135reifyBool :: Term -> ElabD Bool
136reifyBool (P _ n _) | n == sNS (sUN "True") ["Bool", "Prelude"] = return True
137 | n == sNS (sUN "False") ["Bool", "Prelude"] = return False
138reifyBool tm = fail $ "Not a Boolean: " ++ show tm
140reifyInt :: Term -> ElabD Int
141reifyInt (Constant (I i)) = return i
142reifyInt tm = fail $ "Not an Int: " ++ show tm
144reifyPair :: (Term -> ElabD a) -> (Term -> ElabD b) -> Term -> ElabD (a, b)
145reifyPair left right (App _ (App _ (App _ (App _ (P _ n _) _) _) x) y)
146 | n == pairCon = liftM2 (,) (left x) (right y)
147reifyPair left right tm = fail $ "Not a pair: " ++ show tm
149reifyList :: (Term -> ElabD a) -> Term -> ElabD [a]
150reifyList getElt lst =
151 case unList lst of
152 Nothing -> fail "Couldn't reify a list"
153 Just xs -> mapM getElt xs
155reifyReportParts :: Term -> ElabD [ErrorReportPart]
156reifyReportParts errs =
157 case unList errs of
158 Nothing -> fail "Failed to reify errors"
159 Just errs' ->
160 let parts = mapM reifyReportPart errs' in
161 case parts of
162 Left err -> fail $ "Couldn't reify \"Fail\" tactic - " ++ show err
163 Right errs'' ->
164 return errs''
166-- | Reify terms from their reflected representation
167reifyTT :: Term -> ElabD Term
168reifyTT t@(App _ _ _)
169 | (P _ f _, args) <- unApply t = reifyTTApp f args
170reifyTT t@(P _ n _)
171 | n == reflm "Erased" = return $ Erased
172reifyTT t@(P _ n _)
173 | n == reflm "Impossible" = return $ Impossible
174reifyTT t = fail ("Unknown reflection term: " ++ show t)
176reifyTTApp :: Name -> [Term] -> ElabD Term
177reifyTTApp t [nt, n, x]
178 | t == reflm "P" = do nt' <- reifyTTNameType nt
179 n' <- reifyTTName n
180 x' <- reifyTT x
181 return $ P nt' n' x'
182reifyTTApp t [Constant (I i)]
183 | t == reflm "V" = return $ V i
184reifyTTApp t [n, b, x]
185 | t == reflm "Bind" = do n' <- reifyTTName n
186 b' <- reifyTTBinder reifyTT (reflm "TT") b
187 x' <- reifyTT x
188 return $ Bind n' b' x'
189reifyTTApp t [f, x]
190 | t == reflm "App" = do f' <- reifyTT f
191 x' <- reifyTT x
192 return $ App Complete f' x'
193reifyTTApp t [c]
194 | t == reflm "TConst" = liftM Constant (reifyTTConst c)
195reifyTTApp t [t', Constant (I i)]
196 | t == reflm "Proj" = do t'' <- reifyTT t'
197 return $ Proj t'' i
198reifyTTApp t [tt]
199 | t == reflm "TType" = liftM TType (reifyTTUExp tt)
200reifyTTApp t [tt]
201 | t == reflm "UType" = liftM UType (reifyUniverse tt)
202reifyTTApp t args = fail ("Unknown reflection term: " ++ show (t, args))
204reifyUniverse :: Term -> ElabD Universe
205reifyUniverse (P _ n _) | n == reflm "AllTypes" = return AllTypes
206 | n == reflm "UniqueType" = return UniqueType
207 | n == reflm "NullType" = return NullType
208reifyUniverse tm = fail ("Unknown reflection universe: " ++ show tm)
210-- | Reify raw terms from their reflected representation
211reifyRaw :: Term -> ElabD Raw
212reifyRaw t@(App _ _ _)
213 | (P _ f _, args) <- unApply t = reifyRawApp f args
214reifyRaw t@(P _ n _)
215 | n == reflm "RType" = return $ RType
216reifyRaw t = fail ("Unknown reflection raw term in reifyRaw: " ++ show t)
218reifyRawApp :: Name -> [Term] -> ElabD Raw
219reifyRawApp t [n]
220 | t == reflm "Var" = liftM Var (reifyTTName n)
221reifyRawApp t [n, b, x]
222 | t == reflm "RBind" = do n' <- reifyTTName n
223 b' <- reifyTTBinder reifyRaw (reflm "Raw") b
224 x' <- reifyRaw x
225 return $ RBind n' b' x'
226reifyRawApp t [f, x]
227 | t == reflm "RApp" = liftM2 RApp (reifyRaw f) (reifyRaw x)
228reifyRawApp t [c]
229 | t == reflm "RConstant" = liftM RConstant (reifyTTConst c)
230reifyRawApp t args = fail ("Unknown reflection raw term in reifyRawApp: " ++ show (t, args))
232reifyTTName :: Term -> ElabD Name
233reifyTTName t
234 | (P _ f _, args) <- unApply t = reifyTTNameApp f args
235reifyTTName t = fail ("Unknown reflection term name: " ++ show t)
237reifyTTNameApp :: Name -> [Term] -> ElabD Name
238reifyTTNameApp t [Constant (Str n)]
239 | t == reflm "UN" = return $ sUN n
240reifyTTNameApp t [n, ns]
241 | t == reflm "NS" = do n' <- reifyTTName n
242 ns' <- reifyTTNamespace ns
243 return $ sNS n' ns'
244reifyTTNameApp t [Constant (I i), Constant (Str n)]
245 | t == reflm "MN" = return $ sMN i n
246reifyTTNameApp t [sn]
247 | t == reflm "SN"
248 , (P _ f _, args) <- unApply sn = SN <$> reifySN f args
249 where reifySN :: Name -> [Term] -> ElabD SpecialName
250 reifySN t [Constant (I i), n1, n2]
251 | t == reflm "WhereN" = WhereN i <$> reifyTTName n1 <*> reifyTTName n2
252 reifySN t [Constant (I i), n]
253 | t == reflm "WithN" = WithN i <$> reifyTTName n
254 reifySN t [n, ss]
255 | t == reflm "InstanceN" =
256 case unList ss of
257 Nothing -> fail "Can't reify InstanceN strings"
258 Just ss' -> InstanceN <$> reifyTTName n <*>
259 pure [T.pack s | Constant (Str s) <- ss']
260 reifySN t [n, Constant (Str s)]
261 | t == reflm "ParentN" =
262 ParentN <$> reifyTTName n <*> pure (T.pack s)
263 reifySN t [n]
264 | t == reflm "MethodN" =
265 MethodN <$> reifyTTName n
266 reifySN t [fc, n]
267 | t == reflm "CaseN" =
268 CaseN <$> (FC' <$> reifyFC fc) <*> reifyTTName n
269 reifySN t [n]
270 | t == reflm "ElimN" =
271 ElimN <$> reifyTTName n
272 reifySN t [n]
273 | t == reflm "InstanceCtorN" =
274 InstanceCtorN <$> reifyTTName n
275 reifySN t [n1, n2]
276 | t == reflm "MetaN" =
277 MetaN <$> reifyTTName n1 <*> reifyTTName n2
278 reifySN t args = fail $ "Can't reify special name " ++ show t ++ show args
279reifyTTNameApp t args = fail ("Unknown reflection term name: " ++ show (t, args))
281reifyTTNamespace :: Term -> ElabD [String]
282reifyTTNamespace t@(App _ _ _)
283 = case unApply t of
284 (P _ f _, [Constant StrType])
285 | f == sNS (sUN "Nil") ["List", "Prelude"] -> return []
286 (P _ f _, [Constant StrType, Constant (Str n), ns])
287 | f == sNS (sUN "::") ["List", "Prelude"] -> liftM (n:) (reifyTTNamespace ns)
288 _ -> fail ("Unknown reflection namespace arg: " ++ show t)
289reifyTTNamespace t = fail ("Unknown reflection namespace arg: " ++ show t)
291reifyTTNameType :: Term -> ElabD NameType
292reifyTTNameType t@(P _ n _) | n == reflm "Bound" = return $ Bound
293reifyTTNameType t@(P _ n _) | n == reflm "Ref" = return $ Ref
294reifyTTNameType t@(App _ _ _)
295 = case unApply t of
296 (P _ f _, [Constant (I tag), Constant (I num)])
297 | f == reflm "DCon" -> return $ DCon tag num False -- FIXME: Uniqueness!
298 | f == reflm "TCon" -> return $ TCon tag num
299 _ -> fail ("Unknown reflection name type: " ++ show t)
300reifyTTNameType t = fail ("Unknown reflection name type: " ++ show t)
302reifyTTBinder :: (Term -> ElabD a) -> Name -> Term -> ElabD (Binder a)
303reifyTTBinder reificator binderType t@(App _ _ _)
304 = case unApply t of
305 (P _ f _, bt:args) | forget bt == Var binderType
306 -> reifyTTBinderApp reificator f args
307 _ -> fail ("Mismatching binder reflection: " ++ show t)
308reifyTTBinder _ _ t = fail ("Unknown reflection binder: " ++ show t)
310reifyTTBinderApp :: (Term -> ElabD a) -> Name -> [Term] -> ElabD (Binder a)
311reifyTTBinderApp reif f [t]
312 | f == reflm "Lam" = liftM Lam (reif t)
313reifyTTBinderApp reif f [t, k]
314 | f == reflm "Pi" = liftM2 (Pi Nothing) (reif t) (reif k)
315reifyTTBinderApp reif f [x, y]
316 | f == reflm "Let" = liftM2 Let (reif x) (reif y)
317reifyTTBinderApp reif f [t]
318 | f == reflm "Hole" = liftM Hole (reif t)
319reifyTTBinderApp reif f [t]
320 | f == reflm "GHole" = liftM (GHole 0 []) (reif t)
321reifyTTBinderApp reif f [x, y]
322 | f == reflm "Guess" = liftM2 Guess (reif x) (reif y)
323reifyTTBinderApp reif f [t]
324 | f == reflm "PVar" = liftM PVar (reif t)
325reifyTTBinderApp reif f [t]
326 | f == reflm "PVTy" = liftM PVTy (reif t)
327reifyTTBinderApp _ f args = fail ("Unknown reflection binder: " ++ show (f, args))
329reifyTTConst :: Term -> ElabD Const
330reifyTTConst (P _ n _) | n == reflm "StrType" = return $ StrType
331reifyTTConst (P _ n _) | n == reflm "VoidType" = return $ VoidType
332reifyTTConst (P _ n _) | n == reflm "Forgot" = return $ Forgot
333reifyTTConst t@(App _ _ _)
334 | (P _ f _, [arg]) <- unApply t = reifyTTConstApp f arg
335reifyTTConst t = fail ("Unknown reflection constant: " ++ show t)
337reifyTTConstApp :: Name -> Term -> ElabD Const
338reifyTTConstApp f aty
339 | f == reflm "AType" = fmap AType (reifyArithTy aty)
340reifyTTConstApp f (Constant c@(I _))
341 | f == reflm "I" = return $ c
342reifyTTConstApp f (Constant c@(BI _))
343 | f == reflm "BI" = return $ c
344reifyTTConstApp f (Constant c@(Fl _))
345 | f == reflm "Fl" = return $ c
346reifyTTConstApp f (Constant c@(Ch _))
347 | f == reflm "Ch" = return $ c
348reifyTTConstApp f (Constant c@(Str _))
349 | f == reflm "Str" = return $ c
350reifyTTConstApp f (Constant c@(B8 _))
351 | f == reflm "B8" = return $ c
352reifyTTConstApp f (Constant c@(B16 _))
353 | f == reflm "B16" = return $ c
354reifyTTConstApp f (Constant c@(B32 _))
355 | f == reflm "B32" = return $ c
356reifyTTConstApp f (Constant c@(B64 _))
357 | f == reflm "B64" = return $ c
358reifyTTConstApp f v@(P _ _ _) =
359 lift . tfail . Msg $
360 "Can't reify the variable " ++
361 show v ++
362 " as a constant, because its value is not statically known."
363reifyTTConstApp f arg = fail ("Unknown reflection constant: " ++ show (f, arg))
365reifyArithTy :: Term -> ElabD ArithTy
366reifyArithTy (App _ (P _ n _) intTy) | n == reflm "ATInt" = fmap ATInt (reifyIntTy intTy)
367reifyArithTy (P _ n _) | n == reflm "ATDouble" = return ATFloat
368reifyArithTy x = fail ("Couldn't reify reflected ArithTy: " ++ show x)
370reifyNativeTy :: Term -> ElabD NativeTy
371reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
372reifyNativeTy (P _ n _) | n == reflm "IT16" = return IT16
373reifyNativeTy (P _ n _) | n == reflm "IT32" = return IT32
374reifyNativeTy (P _ n _) | n == reflm "IT64" = return IT64
375reifyNativeTy x = fail $ "Couldn't reify reflected NativeTy " ++ show x
377reifyIntTy :: Term -> ElabD IntTy
378reifyIntTy (App _ (P _ n _) nt) | n == reflm "ITFixed" = fmap ITFixed (reifyNativeTy nt)
379reifyIntTy (P _ n _) | n == reflm "ITNative" = return ITNative
380reifyIntTy (P _ n _) | n == reflm "ITBig" = return ITBig
381reifyIntTy (P _ n _) | n == reflm "ITChar" = return ITChar
382reifyIntTy tm = fail $ "The term " ++ show tm ++ " is not a reflected IntTy"
384reifyTTUExp :: Term -> ElabD UExp
385reifyTTUExp t@(App _ _ _)
386 = case unApply t of
387 (P _ f _, [Constant (I i)]) | f == reflm "UVar" -> return $ UVar i
388 (P _ f _, [Constant (I i)]) | f == reflm "UVal" -> return $ UVal i
389 _ -> fail ("Unknown reflection type universe expression: " ++ show t)
390reifyTTUExp t = fail ("Unknown reflection type universe expression: " ++ show t)
392-- | Create a reflected call to a named function/constructor
393reflCall :: String -> [Raw] -> Raw
394reflCall funName args
395 = raw_apply (Var (reflm funName)) args
397-- | Lift a term into its Language.Reflection.TT representation
398reflect :: Term -> Raw
399reflect = reflectTTQuote []
401-- | Lift a term into its Language.Reflection.Raw representation
402reflectRaw :: Raw -> Raw
403reflectRaw = reflectRawQuote []
405claimTy :: Name -> Raw -> ElabD Name
406claimTy n ty = do n' <- getNameFrom n
407 claim n' ty
408 return n'
410intToReflectedNat :: Int -> Raw
411intToReflectedNat i = if i <= 0
412 then Var (natN "Z")
413 else RApp (Var (natN "S")) (intToReflectedNat (i - 1))
414 where natN :: String -> Name
415 natN n = sNS (sUN n) ["Nat", "Prelude"]
417reflectFixity :: Fixity -> Raw
418reflectFixity (Infixl p) = RApp (Var (tacN "Infixl")) (intToReflectedNat p)
419reflectFixity (Infixr p) = RApp (Var (tacN "Infixr")) (intToReflectedNat p)
420reflectFixity (InfixN p) = RApp (Var (tacN "InfixN")) (intToReflectedNat p)
421reflectFixity (PrefixN p) = RApp (Var (tacN "PrefixN")) (intToReflectedNat p)
423-- | Convert a reflected term to a more suitable form for pattern-matching.
424-- In particular, the less-interesting bits are elaborated to _ patterns. This
425-- happens to NameTypes, universe levels, names that are bound but not used,
426-- and the type annotation field of the P constructor.
427reflectTTQuotePattern :: [Name] -> Term -> ElabD ()
428reflectTTQuotePattern unq (P _ n _)
429 | n `elem` unq = -- the unquoted names have been claimed as TT already - just use them
430 do fill (Var n) ; solve
431 | otherwise =
432 do tyannot <- claimTy (sMN 0 "pTyAnnot") (Var (reflm "TT"))
433 movelast tyannot -- use a _ pattern here
434 nt <- getNameFrom (sMN 0 "nt")
435 claim nt (Var (reflm "NameType"))
436 movelast nt -- use a _ pattern here
437 n' <- getNameFrom (sMN 0 "n")
438 claim n' (Var (reflm "TTName"))
439 fill $ reflCall "P" [Var nt, Var n', Var tyannot]
440 solve
441 focus n'; reflectNameQuotePattern n
442reflectTTQuotePattern unq (V n)
443 = do fill $ reflCall "V" [RConstant (I n)]
444 solve
445reflectTTQuotePattern unq (Bind n b x)
446 = do x' <- claimTy (sMN 0 "sc") (Var (reflm "TT"))
447 movelast x'
448 b' <- getNameFrom (sMN 0 "binder")
449 claim b' (RApp (Var (sNS (sUN "Binder") ["Reflection", "Language"]))
450 (Var (sNS (sUN "TT") ["Reflection", "Language"])))
451 if n `elem` freeNames x
452 then do fill $ reflCall "Bind"
453 [reflectName n,
454 Var b',
455 Var x']
456 solve
457 else do any <- getNameFrom (sMN 0 "anyName")
458 claim any (Var (reflm "TTName"))
459 movelast any
460 fill $ reflCall "Bind"
461 [Var any,
462 Var b',
463 Var x']
464 solve
465 focus x'; reflectTTQuotePattern unq x
466 focus b'; reflectBinderQuotePattern reflectTTQuotePattern (Var $ reflm "TT") unq b
467reflectTTQuotePattern unq (App _ f x)
468 = do f' <- claimTy (sMN 0 "f") (Var (reflm "TT")) ; movelast f'
469 x' <- claimTy (sMN 0 "x") (Var (reflm "TT")) ; movelast x'
470 fill $ reflCall "App" [Var f', Var x']
471 solve
472 focus f'; reflectTTQuotePattern unq f
473 focus x'; reflectTTQuotePattern unq x
474reflectTTQuotePattern unq (Constant c)
475 = do fill $ reflCall "TConst" [reflectConstant c]
476 solve
477reflectTTQuotePattern unq (Proj t i)
478 = lift . tfail . InternalMsg $
479 "Phase error! The Proj constructor is for optimization only and should not have been reflected during elaboration."
480reflectTTQuotePattern unq Erased
481 = do erased <- claimTy (sMN 0 "erased") (Var (reflm "TT"))
482 movelast erased
483 fill $ (Var erased)
484reflectTTQuotePattern unq Impossible
485 = lift . tfail . InternalMsg $
486 "Phase error! The Impossible constructor is for optimization only and should not have been reflected during elaboration."
487reflectTTQuotePattern unq (TType exp)
488 = do ue <- getNameFrom (sMN 0 "uexp")
489 claim ue (Var (sNS (sUN "TTUExp") ["Reflection", "Language"]))
490 movelast ue
491 fill $ reflCall "TType" [Var ue]
492 solve
493reflectTTQuotePattern unq (UType u)
494 = do uH <- getNameFrom (sMN 0 "someUniv")
495 claim uH (Var (reflm "Universe"))
496 movelast uH
497 fill $ reflCall "UType" [Var uH]
498 solve
499 focus uH
500 fill (Var (reflm (case u of
501 NullType -> "NullType"
502 UniqueType -> "UniqueType"
503 AllTypes -> "AllTypes")))
504 solve
506reflectRawQuotePattern :: [Name] -> Raw -> ElabD ()
507reflectRawQuotePattern unq (Var n)
508 -- the unquoted names already have types, just use them
509 | n `elem` unq = do fill (Var n); solve
510 | otherwise = do fill (reflCall "Var" [reflectName n]); solve
511reflectRawQuotePattern unq (RBind n b sc) =
512 do scH <- getNameFrom (sMN 0 "sc")
513 claim scH (Var (reflm "Raw"))
514 movelast scH
515 bH <- getNameFrom (sMN 0 "binder")
516 claim bH (RApp (Var (reflm "Binder"))
517 (Var (reflm "Raw")))
518 if n `elem` freeNamesR sc
519 then do fill $ reflCall "RBind" [reflectName n,
520 Var bH,
521 Var scH]
522 solve
523 else do any <- getNameFrom (sMN 0 "anyName")
524 claim any (Var (reflm "TTName"))
525 movelast any
526 fill $ reflCall "RBind" [Var any, Var bH, Var scH]
527 solve
528 focus scH; reflectRawQuotePattern unq sc
529 focus bH; reflectBinderQuotePattern reflectRawQuotePattern (Var $ reflm "Raw") unq b
530 where freeNamesR (Var n) = [n]
531 freeNamesR (RBind n (Let t v) body) = concat [freeNamesR v,
532 freeNamesR body \\ [n],
533 freeNamesR t]
534 freeNamesR (RBind n b body) = freeNamesR (binderTy b) ++
535 (freeNamesR body \\ [n])
536 freeNamesR (RApp f x) = freeNamesR f ++ freeNamesR x
537 freeNamesR RType = []
538 freeNamesR (RUType _) = []
539 freeNamesR (RConstant _) = []
540reflectRawQuotePattern unq (RApp f x) =
541 do fH <- getNameFrom (sMN 0 "f")
542 claim fH (Var (reflm "Raw"))
543 movelast fH
544 xH <- getNameFrom (sMN 0 "x")
545 claim xH (Var (reflm "Raw"))
546 movelast xH
547 fill $ reflCall "RApp" [Var fH, Var xH]
548 solve
549 focus fH; reflectRawQuotePattern unq f
550 focus xH; reflectRawQuotePattern unq x
551reflectRawQuotePattern unq RType =
552 do fill (Var (reflm "RType"))
553 solve
554reflectRawQuotePattern unq (RUType univ) =
555 do uH <- getNameFrom (sMN 0 "universe")
556 claim uH (Var (reflm "Universe"))
557 movelast uH
558 fill $ reflCall "RUType" [Var uH]
559 solve
560 focus uH; fill (reflectUniverse univ); solve
561reflectRawQuotePattern unq (RConstant c) =
562 do cH <- getNameFrom (sMN 0 "const")
563 claim cH (Var (reflm "Constant"))
564 movelast cH
565 fill (reflCall "RConstant" [Var cH]); solve
566 focus cH
567 fill (reflectConstant c); solve
569reflectBinderQuotePattern :: ([Name] -> a -> ElabD ()) -> Raw -> [Name] -> Binder a -> ElabD ()
570reflectBinderQuotePattern q ty unq (Lam t)
571 = do t' <- claimTy (sMN 0 "ty") ty; movelast t'
572 fill $ reflCall "Lam" [ty, Var t']
573 solve
574 focus t'; q unq t
575reflectBinderQuotePattern q ty unq (Pi _ t k)
576 = do t' <- claimTy (sMN 0 "ty") ty; movelast t'
577 k' <- claimTy (sMN 0 "k") ty; movelast k';
578 fill $ reflCall "Pi" [ty, Var t', Var k']
579 solve
580 focus t'; q unq t
581reflectBinderQuotePattern q ty unq (Let x y)
582 = do x' <- claimTy (sMN 0 "ty") ty; movelast x';
583 y' <- claimTy (sMN 0 "v")ty; movelast y';
584 fill $ reflCall "Let" [ty, Var x', Var y']
585 solve
586 focus x'; q unq x
587 focus y'; q unq y
588reflectBinderQuotePattern q ty unq (NLet x y)
589 = do x' <- claimTy (sMN 0 "ty") ty; movelast x'
590 y' <- claimTy (sMN 0 "v") ty; movelast y'
591 fill $ reflCall "Let" [ty, Var x', Var y']
592 solve
593 focus x'; q unq x
594 focus y'; q unq y
595reflectBinderQuotePattern q ty unq (Hole t)
596 = do t' <- claimTy (sMN 0 "ty") ty; movelast t'
597 fill $ reflCall "Hole" [ty, Var t']
598 solve
599 focus t'; q unq t
600reflectBinderQuotePattern q ty unq (GHole _ _ t)
601 = do t' <- claimTy (sMN 0 "ty") ty; movelast t'
602 fill $ reflCall "GHole" [ty, Var t']
603 solve
604 focus t'; q unq t
605reflectBinderQuotePattern q ty unq (Guess x y)
606 = do x' <- claimTy (sMN 0 "ty") ty; movelast x'
607 y' <- claimTy (sMN 0 "v") ty; movelast y'
608 fill $ reflCall "Guess" [ty, Var x', Var y']
609 solve
610 focus x'; q unq x
611 focus y'; q unq y
612reflectBinderQuotePattern q ty unq (PVar t)
613 = do t' <- claimTy (sMN 0 "ty") ty; movelast t'
614 fill $ reflCall "PVar" [ty, Var t']
615 solve
616 focus t'; q unq t
617reflectBinderQuotePattern q ty unq (PVTy t)
618 = do t' <- claimTy (sMN 0 "ty") ty; movelast t'
619 fill $ reflCall "PVTy" [ty, Var t']
620 solve
621 focus t'; q unq t
623reflectUniverse :: Universe -> Raw
624reflectUniverse u =
625 (Var (reflm (case u of
626 NullType -> "NullType"
627 UniqueType -> "UniqueType"
628 AllTypes -> "AllTypes")))
630-- | Create a reflected TT term, but leave refs to the provided name intact
631reflectTTQuote :: [Name] -> Term -> Raw
632reflectTTQuote unq (P nt n t)
633 | n `elem` unq = Var n
634 | otherwise = reflCall "P" [reflectNameType nt, reflectName n, reflectTTQuote unq t]
635reflectTTQuote unq (V n)
636 = reflCall "V" [RConstant (I n)]
637reflectTTQuote unq (Bind n b x)
638 = reflCall "Bind" [reflectName n, reflectBinderQuote reflectTTQuote (reflm "TT") unq b, reflectTTQuote unq x]
639reflectTTQuote unq (App _ f x)
640 = reflCall "App" [reflectTTQuote unq f, reflectTTQuote unq x]
641reflectTTQuote unq (Constant c)
642 = reflCall "TConst" [reflectConstant c]
643reflectTTQuote unq (TType exp) = reflCall "TType" [reflectUExp exp]
644reflectTTQuote unq (UType u) = reflCall "UType" [reflectUniverse u]
645reflectTTQuote _ (Proj _ _) =
646 error "Phase error! The Proj constructor is for optimization only and should not have been reflected during elaboration."
647reflectTTQuote unq Erased = Var (reflm "Erased")
648reflectTTQuote _ Impossible =
649 error "Phase error! The Impossible constructor is for optimization only and should not have been reflected during elaboration."
651reflectRawQuote :: [Name] -> Raw -> Raw
652reflectRawQuote unq (Var n)
653 | n `elem` unq = Var n
654 | otherwise = reflCall "Var" [reflectName n]
655reflectRawQuote unq (RBind n b r) =
656 reflCall "RBind" [reflectName n, reflectBinderQuote reflectRawQuote (reflm "Raw") unq b, reflectRawQuote unq r]
657reflectRawQuote unq (RApp f x) =
658 reflCall "RApp" [reflectRawQuote unq f, reflectRawQuote unq x]
659reflectRawQuote unq RType = Var (reflm "RType")
660reflectRawQuote unq (RUType u) =
661 reflCall "RUType" [reflectUniverse u]
662reflectRawQuote unq (RConstant cst) = reflCall "RConstant" [reflectConstant cst]
664reflectNameType :: NameType -> Raw
665reflectNameType (Bound) = Var (reflm "Bound")
666reflectNameType (Ref) = Var (reflm "Ref")
667reflectNameType (DCon x y _)
668 = reflCall "DCon" [RConstant (I x), RConstant (I y)] -- FIXME: Uniqueness!
669reflectNameType (TCon x y)
670 = reflCall "TCon" [RConstant (I x), RConstant (I y)]
672reflectName :: Name -> Raw
673reflectName (UN s)
674 = reflCall "UN" [RConstant (Str (str s))]
675reflectName (NS n ns)
676 = reflCall "NS" [ reflectName n
677 , foldr (\ n s ->
678 raw_apply ( Var $ sNS (sUN "::") ["List", "Prelude"] )
679 [ RConstant StrType, RConstant (Str n), s ])
680 ( raw_apply ( Var $ sNS (sUN "Nil") ["List", "Prelude"] )
681 [ RConstant StrType ])
682 (map str ns)
683 ]
684reflectName (MN i n)
685 = reflCall "MN" [RConstant (I i), RConstant (Str (str n))]
686reflectName (SN sn) = raw_apply (Var (reflm "SN")) [reflectSpecialName sn]
687reflectName (SymRef _) = error "The impossible happened: symbol table ref survived IBC loading"
689reflectSpecialName :: SpecialName -> Raw
690reflectSpecialName (WhereN i n1 n2) =
691 reflCall "WhereN" [RConstant (I i), reflectName n1, reflectName n2]
692reflectSpecialName (WithN i n) = reflCall "WithN" [ RConstant (I i)
693 , reflectName n
694 ]
695reflectSpecialName (InstanceN inst ss) =
696 reflCall "InstanceN" [ reflectName inst
697 , mkList (RConstant StrType) $
698 map (RConstant . Str . T.unpack) ss
699 ]
700reflectSpecialName (ParentN n s) =
701 reflCall "ParentN" [reflectName n, RConstant (Str (T.unpack s))]
702reflectSpecialName (MethodN n) =
703 reflCall "MethodN" [reflectName n]
704reflectSpecialName (CaseN fc n) =
705 reflCall "CaseN" [reflectFC (unwrapFC fc), reflectName n]
706reflectSpecialName (ElimN n) =
707 reflCall "ElimN" [reflectName n]
708reflectSpecialName (InstanceCtorN n) =
709 reflCall "InstanceCtorN" [reflectName n]
710reflectSpecialName (MetaN parent meta) =
711 reflCall "MetaN" [reflectName parent, reflectName meta]
713-- | Elaborate a name to a pattern. This means that NS and UN will be intact.
714-- MNs corresponding to will care about the string but not the number. All
715-- others become _.
716reflectNameQuotePattern :: Name -> ElabD ()
717reflectNameQuotePattern n@(UN s)
718 = do fill $ reflectName n
719 solve
720reflectNameQuotePattern n@(NS _ _)
721 = do fill $ reflectName n
722 solve
723reflectNameQuotePattern (MN _ n)
724 = do i <- getNameFrom (sMN 0 "mnCounter")
725 claim i (RConstant (AType (ATInt ITNative)))
726 movelast i
727 fill $ reflCall "MN" [Var i, RConstant (Str $ T.unpack n)]
728 solve
729reflectNameQuotePattern _ -- for all other names, match any
730 = do nameHole <- getNameFrom (sMN 0 "name")
731 claim nameHole (Var (reflm "TTName"))
732 movelast nameHole
733 fill (Var nameHole)
734 solve
736reflectBinder :: Binder Term -> Raw
737reflectBinder = reflectBinderQuote reflectTTQuote (reflm "TT") []
739reflectBinderQuote :: ([Name] -> a -> Raw) -> Name -> [Name] -> Binder a -> Raw
740reflectBinderQuote q ty unq (Lam t)
741 = reflCall "Lam" [Var ty, q unq t]
742reflectBinderQuote q ty unq (Pi _ t k)
743 = reflCall "Pi" [Var ty, q unq t, q unq k]
744reflectBinderQuote q ty unq (Let x y)
745 = reflCall "Let" [Var ty, q unq x, q unq y]
746reflectBinderQuote q ty unq (NLet x y)
747 = reflCall "Let" [Var ty, q unq x, q unq y]
748reflectBinderQuote q ty unq (Hole t)
749 = reflCall "Hole" [Var ty, q unq t]
750reflectBinderQuote q ty unq (GHole _ _ t)
751 = reflCall "GHole" [Var ty, q unq t]
752reflectBinderQuote q ty unq (Guess x y)
753 = reflCall "Guess" [Var ty, q unq x, q unq y]
754reflectBinderQuote q ty unq (PVar t)
755 = reflCall "PVar" [Var ty, q unq t]
756reflectBinderQuote q ty unq (PVTy t)
757 = reflCall "PVTy" [Var ty, q unq t]
759mkList :: Raw -> [Raw] -> Raw
760mkList ty [] = RApp (Var (sNS (sUN "Nil") ["List", "Prelude"])) ty
761mkList ty (x:xs) = RApp (RApp (RApp (Var (sNS (sUN "::") ["List", "Prelude"])) ty)
762 x)
763 (mkList ty xs)
765reflectConstant :: Const -> Raw
766reflectConstant c@(I _) = reflCall "I" [RConstant c]
767reflectConstant c@(BI _) = reflCall "BI" [RConstant c]
768reflectConstant c@(Fl _) = reflCall "Fl" [RConstant c]
769reflectConstant c@(Ch _) = reflCall "Ch" [RConstant c]
770reflectConstant c@(Str _) = reflCall "Str" [RConstant c]
771reflectConstant c@(B8 _) = reflCall "B8" [RConstant c]
772reflectConstant c@(B16 _) = reflCall "B16" [RConstant c]
773reflectConstant c@(B32 _) = reflCall "B32" [RConstant c]
774reflectConstant c@(B64 _) = reflCall "B64" [RConstant c]
775reflectConstant (AType (ATInt ITNative)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITNative")]]
776reflectConstant (AType (ATInt ITBig)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITBig")]]
777reflectConstant (AType ATFloat) = reflCall "AType" [Var (reflm "ATDouble")]
778reflectConstant (AType (ATInt ITChar)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITChar")]]
779reflectConstant StrType = Var (reflm "StrType")
780reflectConstant (AType (ATInt (ITFixed IT8))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT8")]]]
781reflectConstant (AType (ATInt (ITFixed IT16))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT16")]]]
782reflectConstant (AType (ATInt (ITFixed IT32))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT32")]]]
783reflectConstant (AType (ATInt (ITFixed IT64))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT64")]]]
784reflectConstant VoidType = Var (reflm "VoidType")
785reflectConstant Forgot = Var (reflm "Forgot")
786reflectConstant WorldType = Var (reflm "WorldType")
787reflectConstant TheWorld = Var (reflm "TheWorld")
789reflectUExp :: UExp -> Raw
790reflectUExp (UVar i) = reflCall "UVar" [RConstant (I i)]
791reflectUExp (UVal i) = reflCall "UVal" [RConstant (I i)]
793-- | Reflect the environment of a proof into a List (TTName, Binder TT)
794reflectEnv :: Env -> Raw
795reflectEnv = foldr consToEnvList emptyEnvList
796 where
797 consToEnvList :: (Name, Binder Term) -> Raw -> Raw
798 consToEnvList (n, b) l
799 = raw_apply (Var (sNS (sUN "::") ["List", "Prelude"]))
800 [ envTupleType
801 , raw_apply (Var pairCon) [ (Var $ reflm "TTName")
802 , (RApp (Var $ reflm "Binder")
803 (Var $ reflm "TT"))
804 , reflectName n
805 , reflectBinder b
806 ]
807 , l
808 ]
810 emptyEnvList :: Raw
811 emptyEnvList = raw_apply (Var (sNS (sUN "Nil") ["List", "Prelude"]))
812 [envTupleType]
814reifyEnv :: Term -> ElabD Env
815reifyEnv = reifyList (reifyPair reifyTTName (reifyTTBinder reifyTT (reflm "TT")))
817-- | Reflect an error into the internal datatype of Idris -- TODO
818rawBool :: Bool -> Raw
819rawBool True = Var (sNS (sUN "True") ["Bool", "Prelude"])
820rawBool False = Var (sNS (sUN "False") ["Bool", "Prelude"])
822rawNil :: Raw -> Raw
823rawNil ty = raw_apply (Var (sNS (sUN "Nil") ["List", "Prelude"])) [ty]
825rawCons :: Raw -> Raw -> Raw -> Raw
826rawCons ty hd tl = raw_apply (Var (sNS (sUN "::") ["List", "Prelude"])) [ty, hd, tl]
828rawList :: Raw -> [Raw] -> Raw
829rawList ty = foldr (rawCons ty) (rawNil ty)
831rawPairTy :: Raw -> Raw -> Raw
832rawPairTy t1 t2 = raw_apply (Var pairTy) [t1, t2]
834rawPair :: (Raw, Raw) -> (Raw, Raw) -> Raw
835rawPair (a, b) (x, y) = raw_apply (Var pairCon) [a, b, x, y]
837-- | Idris tuples nest to the right
838rawTripleTy :: Raw -> Raw -> Raw -> Raw
839rawTripleTy a b c = rawPairTy a (rawPairTy b c)
841rawTriple :: (Raw, Raw, Raw) -> (Raw, Raw, Raw) -> Raw
842rawTriple (a, b, c) (x, y, z) = rawPair (a, rawPairTy b c) (x, rawPair (b, c) (y, z))
844reflectCtxt :: [(Name, Type)] -> Raw
845reflectCtxt ctxt = rawList (rawPairTy (Var $ reflm "TTName") (Var $ reflm "TT"))
846 (map (\ (n, t) -> (rawPair (Var $ reflm "TTName", Var $ reflm "TT")
847 (reflectName n, reflect t)))
848 ctxt)
850reflectErr :: Err -> Raw
851reflectErr (Msg msg) = raw_apply (Var $ reflErrName "Msg") [RConstant (Str msg)]
852reflectErr (InternalMsg msg) = raw_apply (Var $ reflErrName "InternalMsg") [RConstant (Str msg)]
853reflectErr (CantUnify b (t1,_) (t2,_) e ctxt i) =
854 raw_apply (Var $ reflErrName "CantUnify")
855 [ rawBool b
856 , reflect t1
857 , reflect t2
858 , reflectErr e
859 , reflectCtxt ctxt
860 , RConstant (I i)]
861reflectErr (InfiniteUnify n tm ctxt) =
862 raw_apply (Var $ reflErrName "InfiniteUnify")
863 [ reflectName n
864 , reflect tm
865 , reflectCtxt ctxt
866 ]
867reflectErr (CantConvert t t' ctxt) =
868 raw_apply (Var $ reflErrName "CantConvert")
869 [ reflect t
870 , reflect t'
871 , reflectCtxt ctxt
872 ]
873reflectErr (CantSolveGoal t ctxt) =
874 raw_apply (Var $ reflErrName "CantSolveGoal")
875 [ reflect t
876 , reflectCtxt ctxt
877 ]
878reflectErr (UnifyScope n n' t ctxt) =
879 raw_apply (Var $ reflErrName "UnifyScope")
880 [ reflectName n
881 , reflectName n'
882 , reflect t
883 , reflectCtxt ctxt
884 ]
885reflectErr (CantInferType str) =
886 raw_apply (Var $ reflErrName "CantInferType") [RConstant (Str str)]
887reflectErr (NonFunctionType t t') =
888 raw_apply (Var $ reflErrName "NonFunctionType") [reflect t, reflect t']
889reflectErr (NotEquality t t') =
890 raw_apply (Var $ reflErrName "NotEquality") [reflect t, reflect t']
891reflectErr (TooManyArguments n) = raw_apply (Var $ reflErrName "TooManyArguments") [reflectName n]
892reflectErr (CantIntroduce t) = raw_apply (Var $ reflErrName "CantIntroduce") [reflect t]
893reflectErr (NoSuchVariable n) = raw_apply (Var $ reflErrName "NoSuchVariable") [reflectName n]
894reflectErr (WithFnType t) = raw_apply (Var $ reflErrName "WithFnType") [reflect t]
895reflectErr (CantMatch t) = raw_apply (Var $ reflErrName "CantMatch") [reflect t]
896reflectErr (NoTypeDecl n) = raw_apply (Var $ reflErrName "NoTypeDecl") [reflectName n]
897reflectErr (NotInjective t1 t2 t3) =
898 raw_apply (Var $ reflErrName "NotInjective")
899 [ reflect t1
900 , reflect t2
901 , reflect t3
902 ]
903reflectErr (CantResolve _ t more)
904 = raw_apply (Var $ reflErrName "CantResolve") [reflect t, reflectErr more]
905reflectErr (InvalidTCArg n t) = raw_apply (Var $ reflErrName "InvalidTCArg") [reflectName n, reflect t]
906reflectErr (CantResolveAlts ss) =
907 raw_apply (Var $ reflErrName "CantResolveAlts")
908 [rawList (Var $ reflm "TTName") (map reflectName ss)]
909reflectErr (IncompleteTerm t) = raw_apply (Var $ reflErrName "IncompleteTerm") [reflect t]
910reflectErr (NoEliminator str t)
911 = raw_apply (Var $ reflErrName "NoEliminator") [RConstant (Str str),
912 reflect t]
913reflectErr (UniverseError fc ue old new tys) =
914 -- NB: loses information, but OK because this is not likely to be rewritten
915 Var $ reflErrName "UniverseError"
916reflectErr ProgramLineComment = Var $ reflErrName "ProgramLineComment"
917reflectErr (Inaccessible n) = raw_apply (Var $ reflErrName "Inaccessible") [reflectName n]
918reflectErr (UnknownImplicit n f) = raw_apply (Var $ reflErrName "UnknownImplicit") [reflectName n, reflectName f]
919reflectErr (NonCollapsiblePostulate n) = raw_apply (Var $ reflErrName "NonCollabsiblePostulate") [reflectName n]
920reflectErr (AlreadyDefined n) = raw_apply (Var $ reflErrName "AlreadyDefined") [reflectName n]
921reflectErr (ProofSearchFail e) = raw_apply (Var $ reflErrName "ProofSearchFail") [reflectErr e]
922reflectErr (NoRewriting tm) = raw_apply (Var $ reflErrName "NoRewriting") [reflect tm]
923reflectErr (ProviderError str) =
924 raw_apply (Var $ reflErrName "ProviderError") [RConstant (Str str)]
925reflectErr (LoadingFailed str err) =
926 raw_apply (Var $ reflErrName "LoadingFailed") [RConstant (Str str)]
927reflectErr x = raw_apply (Var (sNS (sUN "Msg") ["Errors", "Reflection", "Language"])) [RConstant . Str $ "Default reflection: " ++ show x]
929-- | Reflect a file context
930reflectFC :: FC -> Raw
931reflectFC fc = raw_apply (Var (reflm "FileLoc"))
932 [ RConstant (Str (fc_fname fc))
933 , raw_apply (Var pairCon) $
934 [intTy, intTy] ++
935 map (RConstant . I)
936 [ fst (fc_start fc)
937 , snd (fc_start fc)
938 ]
939 , raw_apply (Var pairCon) $
940 [intTy, intTy] ++
941 map (RConstant . I)
942 [ fst (fc_end fc)
943 , snd (fc_end fc)
944 ]
945 ]
946 where intTy = RConstant (AType (ATInt ITNative))
948reifyFC :: Term -> ElabD FC
949reifyFC tm
950 | (P (DCon _ _ _) cn _, [Constant (Str fn), st, end]) <- unApply tm
951 , cn == reflm "FileLoc" = FC fn <$> reifyPair reifyInt reifyInt st <*> reifyPair reifyInt reifyInt end
952 | otherwise = fail $ "Not a source location: " ++ show tm
954fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
955fromTTMaybe (App _ (App _ (P (DCon _ _ _) (NS (UN just) _) _) ty) tm)
956 | just == txt "Just" = Just tm
957fromTTMaybe x = Nothing
959reflErrName :: String -> Name
960reflErrName n = sNS (sUN n) ["Errors", "Reflection", "Language"]
962-- | Attempt to reify a report part from TT to the internal
963-- representation. Not in Idris or ElabD monads because it should be usable
964-- from either.
965reifyReportPart :: Term -> Either Err ErrorReportPart
966reifyReportPart (App _ (P (DCon _ _ _) n _) (Constant (Str msg))) | n == reflm "TextPart" =
967 Right (TextPart msg)
968reifyReportPart (App _ (P (DCon _ _ _) n _) ttn)
969 | n == reflm "NamePart" =
970 case runElab initEState (reifyTTName ttn) (initElaborator (sMN 0 "hole") initContext emptyContext 0 Erased) of
971 Error e -> Left . InternalMsg $
972 "could not reify name term " ++
973 show ttn ++
974 " when reflecting an error:" ++ show e
975 OK (n', _)-> Right $ NamePart n'
976reifyReportPart (App _ (P (DCon _ _ _) n _) tm)
977 | n == reflm "TermPart" =
978 case runElab initEState (reifyTT tm) (initElaborator (sMN 0 "hole") initContext emptyContext 0 Erased) of
979 Error e -> Left . InternalMsg $
980 "could not reify reflected term " ++
981 show tm ++
982 " when reflecting an error:" ++ show e
983 OK (tm', _) -> Right $ TermPart tm'
984reifyReportPart (App _ (P (DCon _ _ _) n _) tm)
985 | n == reflm "RawPart" =
986 case runElab initEState (reifyRaw tm) (initElaborator (sMN 0 "hole") initContext emptyContext 0 Erased) of
987 Error e -> Left . InternalMsg $
988 "could not reify reflected raw term " ++
989 show tm ++
990 " when reflecting an error: " ++ show e
991 OK (tm', _) -> Right $ RawPart tm'
992reifyReportPart (App _ (P (DCon _ _ _) n _) tm)
993 | n == reflm "SubReport" =
994 case unList tm of
995 Just xs -> do subParts <- mapM reifyReportPart xs
996 Right (SubReport subParts)
997 Nothing -> Left . InternalMsg $ "could not reify subreport " ++ show tm
998reifyReportPart x = Left . InternalMsg $ "could not reify " ++ show x
1000reifyErasure :: Term -> ElabD RErasure
1001reifyErasure (P (DCon _ _ _) n _)
1002 | n == tacN "Erased" = return RErased
1003 | n == tacN "NotErased" = return RNotErased
1004reifyErasure tm = fail $ "Can't reify " ++ show tm ++ " as erasure info."
1006reifyPlicity :: Term -> ElabD RPlicity
1007reifyPlicity (P (DCon _ _ _) n _)
1008 | n == tacN "Explicit" = return RExplicit
1009 | n == tacN "Implicit" = return RImplicit
1010 | n == tacN "Constraint" = return RConstraint
1011reifyPlicity tm = fail $ "Couldn't reify " ++ show tm ++ " as RPlicity."
1013reifyRFunArg :: Term -> ElabD RFunArg
1014reifyRFunArg (App _ (App _ (App _ (App _ (P (DCon _ _ _) n _) argN) argTy) argPl) argE)
1015 | n == tacN "MkFunArg" = liftM4 RFunArg
1016 (reifyTTName argN)
1017 (reifyRaw argTy)
1018 (reifyPlicity argPl)
1019 (reifyErasure argE)
1020reifyRFunArg aTm = fail $ "Couldn't reify " ++ show aTm ++ " as an RArg."
1022reifyTyDecl :: Term -> ElabD RTyDecl
1023reifyTyDecl (App _ (App _ (App _ (P (DCon _ _ _) n _) tyN) args) ret)
1024 | n == tacN "Declare" =
1025 do tyN' <- reifyTTName tyN
1026 args' <- case unList args of
1027 Nothing -> fail $ "Couldn't reify " ++ show args ++ " as an arglist."
1028 Just xs -> mapM reifyRFunArg xs
1029 ret' <- reifyRaw ret
1030 return $ RDeclare tyN' args' ret'
1031reifyTyDecl tm = fail $ "Couldn't reify " ++ show tm ++ " as a type declaration."
1033reifyFunDefn :: Term -> ElabD (RFunDefn Raw)
1034reifyFunDefn (App _ (App _ (App _ (P _ n _) (P _ t _)) fnN) clauses)
1035 | n == tacN "DefineFun" && t == reflm "Raw" =
1036 do fnN' <- reifyTTName fnN
1037 clauses' <- case unList clauses of
1038 Nothing -> fail $ "Couldn't reify " ++ show clauses ++ " as a clause list"
1039 Just cs -> mapM reifyC cs
1040 return $ RDefineFun fnN' clauses'
1041 where reifyC :: Term -> ElabD (RFunClause Raw)
1042 reifyC (App _ (App _ (App _ (P (DCon _ _ _) n _) (P _ t _)) lhs) rhs)
1043 | n == tacN "MkFunClause" && t == reflm "Raw" = liftM2 RMkFunClause
1044 (reifyRaw lhs)
1045 (reifyRaw rhs)
1046 reifyC (App _ (App _ (P (DCon _ _ _) n _) (P _ t _)) lhs)
1047 | n == tacN "MkImpossibleClause" && t == reflm "Raw" = fmap RMkImpossibleClause $ reifyRaw lhs
1048 reifyC tm = fail $ "Couldn't reify " ++ show tm ++ " as a clause."
1049reifyFunDefn tm = fail $ "Couldn't reify " ++ show tm ++ " as a function declaration."
1051reifyRConstructorDefn :: Term -> ElabD RConstructorDefn
1052reifyRConstructorDefn (App _ (App _ (App _ (P _ n _) cn) args) retTy)
1053 | n == tacN "Constructor", Just args' <- unList args
1054 = RConstructor <$> reifyTTName cn <*> mapM reifyRFunArg args' <*> reifyRaw retTy
1055reifyRConstructorDefn aTm = fail $ "Couldn't reify " ++ show aTm ++ " as an RConstructorDefn"
1057reifyRDataDefn :: Term -> ElabD RDataDefn
1058reifyRDataDefn (App _ (App _ (P _ n _) tyn) ctors)
1059 | n == tacN "DefineDatatype", Just ctors' <- unList ctors
1060 = RDefineDatatype <$> reifyTTName tyn <*> mapM reifyRConstructorDefn ctors'
1061reifyRDataDefn aTm = fail $ "Couldn't reify " ++ show aTm ++ " as an RDataDefn"
1063envTupleType :: Raw
1064envTupleType
1065 = raw_apply (Var pairTy) [ (Var $ reflm "TTName")
1066 , (RApp (Var $ reflm "Binder") (Var $ reflm "TT"))
1069reflectList :: Raw -> [Raw] -> Raw
1070reflectList ty [] = RApp (Var (sNS (sUN "Nil") ["List", "Prelude"])) ty
1071reflectList ty (x:xs) = RApp (RApp (RApp (Var (sNS (sUN "::") ["List", "Prelude"])) ty)
1072 x)
1073 (reflectList ty xs)
1075-- | Apply Idris's implicit info to get a signature. The [PArg] should
1076-- come from a lookup in idris_implicits on IState.
1077getArgs :: [PArg] -> Raw -> ([RFunArg], Raw)
1078getArgs [] r = ([], r)
1079getArgs (a:as) (RBind n (Pi _ ty _) sc) =
1080 let (args, res) = getArgs as sc
1081 erased = if InaccessibleArg `elem` argopts a then RErased else RNotErased
1082 arg' = case a of
1083 PImp {} -> RFunArg n ty RImplicit erased
1084 PExp {} -> RFunArg n ty RExplicit erased
1085 PConstraint {} -> RFunArg n ty RConstraint erased
1086 PTacImplicit {} -> RFunArg n ty RImplicit erased
1087 in (arg':args, res)
1088getArgs _ r = ([], r)
1090unApplyRaw :: Raw -> (Raw, [Raw])
1091unApplyRaw tm = ua [] tm
1092 where
1093 ua args (RApp f a) = ua (a:args) f
1094 ua args t = (t, args)
1096-- | Build the reflected function definition(s) that correspond(s) to
1097-- a provided unqualifed name
1098buildFunDefns :: IState -> Name -> [RFunDefn Term]
1099buildFunDefns ist n =
1100 [ mkFunDefn name clauses
1101 | (name, (clauses, _)) <- lookupCtxtName n $ idris_patdefs ist
1104 where mkFunDefn name clauses = RDefineFun name (map mkFunClause clauses)
1106 mkFunClause ([], lhs, Impossible) = RMkImpossibleClause lhs
1107 mkFunClause ([], lhs, rhs) = RMkFunClause lhs rhs
1108 mkFunClause (((n, ty) : ns), lhs, rhs) = mkFunClause (ns, bind lhs, bind rhs) where
1109 bind Impossible = Impossible
1110 bind tm = Bind n (PVar ty) tm
1112-- | Build the reflected datatype definition(s) that correspond(s) to
1113-- a provided unqualified name
1114buildDatatypes :: IState -> Name -> [RDatatype]
1115buildDatatypes ist n =
1116 catMaybes [ mkDataType dn ti
1117 | (dn, ti) <- lookupCtxtName n datatypes
1119 where datatypes = idris_datatypes ist
1120 ctxt = tt_ctxt ist
1121 impls = idris_implicits ist
1123 ctorSig params cn = do cty <- fmap forget (lookupTyExact cn ctxt)
1124 argInfo <- lookupCtxtExact cn impls
1125 let (args, res) = getArgs argInfo cty
1126 return (cn, ctorArgsStatus args res params, res)
1128 argPos n [] res = findPos n res
1129 where findPos n app = case unApplyRaw app of
1130 (_, argL) -> findIndex (== Var n) argL
1131 argPos n (arg:args) res = if n == argName arg
1132 then Nothing
1133 else argPos n args res
1135 ctorArgsStatus :: [RFunArg] -> Raw -> [Int] -> [RCtorArg]
1136 ctorArgsStatus [] _ _ = []
1137 ctorArgsStatus (arg:args) res params =
1138 case argPos (argName arg) args res of
1139 Nothing -> RCtorField arg : ctorArgsStatus args res params
1140 Just i -> if i `elem` params
1141 then RCtorParameter arg : ctorArgsStatus args res params
1142 else RCtorField arg : ctorArgsStatus args res params
1144 mkDataType name (TI {param_pos = params, con_names = constrs}) =
1145 do (TyDecl (TCon _ _) ty) <- lookupDefExact name ctxt
1146 implInfo <- lookupCtxtExact name impls
1147 let (tcargs, tcres) = getTCArgs params implInfo (forget ty)
1148 ctors <- mapM (ctorSig params) constrs
1149 return $ RDatatype name tcargs tcres ctors
1151 getTCArgs :: [Int] -> [PArg] -> Raw -> ([RTyConArg], Raw)
1152 getTCArgs params implInfo tcTy =
1153 let (args, res) = getArgs implInfo tcTy
1154 in (tcArg args 0, res)
1155 where tcArg [] _ = []
1156 tcArg (arg:args) i | i `elem` params = RParameter arg : tcArg args (i+1)
1157 | otherwise = RIndex arg : tcArg args (i+1)
1160reflectErasure :: RErasure -> Raw
1161reflectErasure RErased = Var (tacN "Erased")
1162reflectErasure RNotErased = Var (tacN "NotErased")
1164reflectPlicity :: RPlicity -> Raw
1165reflectPlicity RExplicit = Var (tacN "Explicit")
1166reflectPlicity RImplicit = Var (tacN "Implicit")
1167reflectPlicity RConstraint = Var (tacN "Constraint")
1169reflectArg :: RFunArg -> Raw
1170reflectArg (RFunArg n ty plic erasure) =
1171 RApp (RApp (RApp (RApp (Var $ tacN "MkFunArg") (reflectName n))
1172 (reflectRaw ty))
1173 (reflectPlicity plic))
1174 (reflectErasure erasure)
1176reflectCtorArg :: RCtorArg -> Raw
1177reflectCtorArg (RCtorParameter arg) = RApp (Var $ tacN "CtorParameter") (reflectArg arg)
1178reflectCtorArg (RCtorField arg) = RApp (Var $ tacN "CtorField") (reflectArg arg)
1180reflectDatatype :: RDatatype -> Raw
1181reflectDatatype (RDatatype tyn tyConArgs tyConRes constrs) =
1182 raw_apply (Var $ tacN "MkDatatype") [ reflectName tyn
1183 , rawList (Var $ tacN "TyConArg") (map reflectConArg tyConArgs)
1184 , reflectRaw tyConRes
1185 , rawList (rawTripleTy (Var $ reflm "TTName")
1186 (RApp (Var (sNS (sUN "List") ["List", "Prelude"])) (Var $ tacN "CtorArg"))
1187 (Var $ reflm "Raw"))
1188 [ rawTriple ((Var $ reflm "TTName"),
1189 (RApp (Var (sNS (sUN "List") ["List", "Prelude"])) (Var $ tacN "CtorArg")),
1190 (Var $ reflm "Raw"))
1191 (reflectName cn,
1192 rawList (Var $ tacN "CtorArg") (map reflectCtorArg cargs),
1193 reflectRaw cty)
1194 | (cn, cargs, cty) <- constrs
1197 where reflectConArg (RParameter a) =
1198 RApp (Var $ tacN "TyConParameter") (reflectArg a)
1199 reflectConArg (RIndex a) =
1200 RApp (Var $ tacN "TyConIndex") (reflectArg a)
1202reflectFunClause :: RFunClause Term -> Raw
1203reflectFunClause (RMkFunClause lhs rhs) = raw_apply (Var $ tacN "MkFunClause") $ (Var $ reflm "TT") : map reflect [ lhs, rhs ]
1204reflectFunClause (RMkImpossibleClause lhs) = raw_apply (Var $ tacN "MkImpossibleClause") $ [ Var $ reflm "TT", reflect lhs ]
1206reflectFunDefn :: RFunDefn Term -> Raw
1207reflectFunDefn (RDefineFun name clauses) = raw_apply (Var $ tacN "DefineFun") [ Var $ reflm "TT"
1208 , reflectName name
1209 , rawList (RApp (Var $ tacN "FunClause") (Var $ reflm "TT")) (map reflectFunClause clauses)