@@ -6,37 +6,44 @@ quoters and unquoters along with some supporting datatypes.
66module Idris.Reflection where
77
88import Control.Applicative ((<$>), (<*>), pure)
9−import Control.Monad (liftM, liftM2)
9+import Control.Monad (liftM, liftM2, liftM3)
1010import Data.Maybe (catMaybes)
1111import Data.List ((\\))
1212import qualified Data.Text as T
1313
1414import Idris.Core.Elaborate (claim, fill, focus, getNameFrom, initElaborator,
1515 movelast, runElab, solve)
16−import Idris.Core.Evaluate (Context, Def(TyDecl), initContext, lookupDefExact, lookupTyExact)
16+import Idris.Core.Evaluate (Def(TyDecl), initContext, lookupDefExact, lookupTyExact)
1717import Idris.Core.TT
1818
19−import Idris.AbsSyntaxTree (ElabD, IState, PArg'(..), PArg, PTactic, PTactic'(..),
20− PTerm(..), initEState, pairCon, pairTy)
19+import Idris.AbsSyntaxTree (ArgOpt(..),ElabD, IState(tt_ctxt, idris_implicits,idris_datatypes),
20+ PArg'(..), PArg, PTactic, PTactic'(..), PTerm(..),
21+ initEState, pairCon, pairTy)
2122import Idris.Delaborate (delab)
2223
23−data RArg = RExplicit { argName :: Name, argTy :: Raw }
24− | RImplicit { argName :: Name, argTy :: Raw }
25− | RConstraint { argName :: Name, argTy :: Raw }
24+data RErasure = RErased | RNotErased deriving Show
25+
26+data RArg = RExplicit { argName :: Name, argErased :: RErasure, argTy :: Raw }
27+ | RImplicit { argName :: Name, argErased :: RErasure, argTy :: Raw }
28+ | RConstraint { argName :: Name, argErased :: RErasure, argTy :: Raw }
2629 deriving Show
2730
2831data RTyDecl = RDeclare Name [RArg] Raw deriving Show
2932
30−data RTyConArg = RParameter { tcArgName :: Name, tcArgTy :: Raw }
31− | RIndex { tcArgName :: Name, tcArgTy :: Raw }
33+data RTyConArg = RParameter { tcArgName :: Name, tcArgErased :: RErasure, tcArgTy :: Raw }
34+ | RIndex { tcArgName :: Name, tcArgErased :: RErasure, tcArgTy :: Raw }
3235 deriving Show
3336
34−data RDatatype = RDatatype Name [RTyConArg] Raw [(Name, Raw)] deriving Show
37+data RDatatype = RDatatype Name [RTyConArg] Raw [(Name, [RArg], Raw)] deriving Show
38+
39+rArgOpts :: RErasure -> [ArgOpt]
40+rArgOpts RErased = [InaccessibleArg]
41+rArgOpts _ = []
3542
3643rArgToPArg :: RArg -> PArg
37−rArgToPArg (RExplicit n _) = PExp 0 [] n Placeholder
38−rArgToPArg (RImplicit n _) = PImp 0 False [] n Placeholder
39−rArgToPArg (RConstraint n _) = PConstraint 0 [] n Placeholder
44+rArgToPArg (RExplicit n e _) = PExp 0 (rArgOpts e) n Placeholder
45+rArgToPArg (RImplicit n e _) = PImp 0 False (rArgOpts e) n Placeholder
46+rArgToPArg (RConstraint n e _) = PConstraint 0 (rArgOpts e) n Placeholder
4047
4148data RFunClause = RMkFunClause Raw Raw
4249 | RMkImpossibleClause Raw
@@ -154,8 +161,16 @@ reifyTTApp t [t', Constant (I i)]
154161 return $ Proj t'' i
155162reifyTTApp t [tt]
156163 | t == reflm "TType" = liftM TType (reifyTTUExp tt)
164+reifyTTApp t [tt]
165+ | t == reflm "UType" = liftM UType (reifyUniverse tt)
157166reifyTTApp t args = fail ("Unknown reflection term: " ++ show (t, args))
158167
168+reifyUniverse :: Term -> ElabD Universe
169+reifyUniverse (P _ n _) | n == reflm "AllTypes" = return AllTypes
170+ | n == reflm "UniqueType" = return UniqueType
171+ | n == reflm "NullType" = return NullType
172+reifyUniverse tm = fail ("Unknown reflection universe: " ++ show tm)
173+
159174-- | Reify raw terms from their reflected representation
160175reifyRaw :: Term -> ElabD Raw
161176reifyRaw t@(App _ _ _)
@@ -780,6 +795,13 @@ rawPairTy t1 t2 = raw_apply (Var pairTy) [t1, t2]
780795rawPair :: (Raw, Raw) -> (Raw, Raw) -> Raw
781796rawPair (a, b) (x, y) = raw_apply (Var pairCon) [a, b, x, y]
782797
798+-- | Idris tuples nest to the right
799+rawTripleTy :: Raw -> Raw -> Raw -> Raw
800+rawTripleTy a b c = rawPairTy a (rawPairTy b c)
801+
802+rawTriple :: (Raw, Raw, Raw) -> (Raw, Raw, Raw) -> Raw
803+rawTriple (a, b, c) (x, y, z) = rawPair (a, rawPairTy b c) (x, rawPair (b, c) (y, z))
804+
783805reflectCtxt :: [(Name, Type)] -> Raw
784806reflectCtxt ctxt = rawList (rawPairTy (Var $ reflm "TTName") (Var $ reflm "TT"))
785807 (map (\ (n, t) -> (rawPair (Var $ reflm "TTName", Var $ reflm "TT")
@@ -929,6 +951,12 @@ reifyReportPart (App _ (P (DCon _ _ _) n _) tm)
929951 Nothing -> Left . InternalMsg $ "could not reify subreport " ++ show tm
930952reifyReportPart x = Left . InternalMsg $ "could not reify " ++ show x
931953
954+reifyErasure :: Term -> ElabD RErasure
955+reifyErasure (P (DCon _ _ _) n _)
956+ | n == tacN "Erased" = return RErased
957+ | n == tacN "NotErased" = return RNotErased
958+reifyErasure tm = fail $ "Can't reify " ++ show tm ++ " as erasure info."
959+
932960reifyTyDecl :: Term -> ElabD RTyDecl
933961reifyTyDecl (App _ (App _ (App _ (P (DCon _ _ _) n _) tyN) args) ret)
934962 | n == tacN "Declare" =
@@ -939,14 +967,17 @@ reifyTyDecl (App _ (App _ (App _ (P (DCon _ _ _) n _) tyN) args) ret)
939967 ret' <- reifyRaw ret
940968 return $ RDeclare tyN' args' ret'
941969 where reifyRArg :: Term -> ElabD RArg
942− reifyRArg (App _ (App _ (P (DCon _ _ _) n _) argN) argTy)
943− | n == tacN "Explicit" = liftM2 RExplicit
970+ reifyRArg (App _ (App _ (App _ (P (DCon _ _ _) n _) argN) argE) argTy)
971+ | n == tacN "Explicit" = liftM3 RExplicit
944972 (reifyTTName argN)
973+ (reifyErasure argE)
945974 (reifyRaw argTy)
946− | n == tacN "Implicit" = liftM2 RImplicit
975+ | n == tacN "Implicit" = liftM3 RImplicit
947976 (reifyTTName argN)
948− (reifyRaw argTy) | n == tacN "Constraint" = liftM2 RConstraint
977+ (reifyErasure argE)
978+ (reifyRaw argTy) | n == tacN "Constraint" = liftM3 RConstraint
949979 (reifyTTName argN)
980+ (reifyErasure argE)
950981 (reifyRaw argTy)
951982 reifyRArg aTm = fail $ "Couldn't reify " ++ show aTm ++ " as an RArg."
952983reifyTyDecl tm = fail $ "Couldn't reify " ++ show tm ++ " as a type declaration."
@@ -975,38 +1006,89 @@ envTupleType
9751006 , (RApp (Var $ reflm "Binder") (Var $ reflm "TT"))
9761007 ]
9771008
1009+-- | Apply Idris's implicit info to get a signature. The [PArg] should
1010+-- come from a lookup in idris_implicits on IState.
1011+getArgs :: [PArg] -> Raw -> ([RArg], Raw)
1012+getArgs [] r = ([], r)
1013+getArgs (a:as) (RBind n (Pi _ ty _) sc) =
1014+ let (args, res) = getArgs as sc
1015+ erased = if InaccessibleArg `elem` argopts a then RErased else RNotErased
1016+ arg' = case a of
1017+ PImp {} -> RImplicit n erased ty
1018+ PExp {} -> RExplicit n erased ty
1019+ PConstraint {} -> RConstraint n erased ty
1020+ PTacImplicit {} -> RImplicit n erased ty -- TODO?
1021+ in (arg':args, res)
1022+getArgs _ r = ([], r)
1023+
9781024-- | Build the reflected datatype definition(s) that correspond(s) to
9791025-- a provided unqualified name
980−buildDatatypes :: Context -> Ctxt TypeInfo -> Name -> [RDatatype]
981−buildDatatypes ctxt datatypes n =
1026+buildDatatypes :: IState -> Name -> [RDatatype]
1027+buildDatatypes ist n =
9821028 catMaybes [ mkDataType dn ti
9831029 | (dn, ti) <- lookupCtxtName n datatypes
9841030 ]
985− where mkDataType name (TI {param_pos = params, con_names = constrs}) =
986− do (TyDecl (TCon _ _) ty) <- lookupDefExact name ctxt
987− let (tcargs, tcres) = getArgs params (forget ty) 0
988− conTys <- mapM (fmap forget . flip lookupTyExact ctxt) constrs
989− return $ RDatatype name tcargs tcres $ zip constrs conTys
1031+ where datatypes = idris_datatypes ist
1032+ ctxt = tt_ctxt ist
1033+ impls = idris_implicits ist
9901034
991− getArgs params (RBind an (Pi _ ty _) body) i =
992− let (args, res) = getArgs params body (i+1)
1035+ ctorSig cn = do cty <- fmap forget (lookupTyExact cn ctxt)
1036+ argInfo <- lookupCtxtExact cn impls
1037+ let (args, res) = getArgs argInfo cty
1038+ return (cn, args, res)
1039+
1040+ mkDataType name (TI {param_pos = params, con_names = constrs}) =
1041+ do (TyDecl (TCon _ _) ty) <- lookupDefExact name ctxt
1042+ implInfo <- lookupCtxtExact name impls
1043+ let (tcargs, tcres) = getTCArgs params implInfo (forget ty) 0
1044+ ctors <- mapM ctorSig constrs
1045+ return $ RDatatype name tcargs tcres ctors
1046+
1047+ getTCArgs params implInfo (RBind an (Pi _ ty _) body) i =
1048+ let (erased, implInfo') = case implInfo of
1049+ [] -> (RNotErased, [])
1050+ (a:as) -> (if InaccessibleArg `elem` argopts a
1051+ then RErased
1052+ else RNotErased,
1053+ as)
1054+ (args, res) = getTCArgs params implInfo' body (i+1)
9931055 in if i `elem` params
994− then (RParameter an ty : args, res )
995− else (RIndex an ty : args, res)
996− getArgs _ tm _ = ([], tm)
1056+ then (RParameter an erased ty : args, res )
1057+ else (RIndex an erased ty : args, res)
1058+ getTCArgs _ implInfo tm _ = ([], tm)
1059+
1060+reflectErasure :: RErasure -> Raw
1061+reflectErasure RErased = Var (tacN "Erased")
1062+reflectErasure RNotErased = Var (tacN "NotErased")
1063+
1064+reflectArg :: RArg -> Raw
1065+reflectArg arg =
1066+ RApp (RApp (RApp (Var con) (reflectName $ argName arg))
1067+ (reflectErasure $ argErased arg))
1068+ (reflectRaw $ argTy arg)
1069+ where con = case arg of
1070+ RExplicit{} -> tacN "Explicit"
1071+ RImplicit{} -> tacN "Implicit"
1072+ RConstraint{} -> tacN "Constraint"
9971073
9981074reflectDatatype :: RDatatype -> Raw
9991075reflectDatatype (RDatatype tyn tyConArgs tyConRes constrs) =
10001076 raw_apply (Var $ tacN "MkDatatype") [ reflectName tyn
10011077 , rawList (Var $ tacN "TyConArg") (map reflectConArg tyConArgs)
10021078 , reflectRaw tyConRes
1003− , rawList (rawPairTy (Var $ reflm "TTName") (Var $ reflm "Raw"))
1004− [ rawPair ((Var $ reflm "TTName"), (Var $ reflm "Raw"))
1005− (reflectName cn, reflectRaw cty)
1006− | (cn, cty) <- constrs
1079+ , rawList (rawTripleTy (Var $ reflm "TTName")
1080+ (RApp (Var (sNS (sUN "List") ["List", "Prelude"])) (Var $ tacN "Arg"))
1081+ (Var $ reflm "Raw"))
1082+ [ rawTriple ((Var $ reflm "TTName"),
1083+ (RApp (Var (sNS (sUN "List") ["List", "Prelude"])) (Var $ tacN "Arg")),
1084+ (Var $ reflm "Raw"))
1085+ (reflectName cn,
1086+ rawList (Var $ tacN "Arg") (map reflectArg cargs),
1087+ reflectRaw cty)
1088+ | (cn, cargs, cty) <- constrs
10071089 ]
10081090 ]
1009− where reflectConArg (RParameter n t) =
1010− raw_apply (Var $ tacN "Parameter") [reflectName n, reflectRaw t]
1011− reflectConArg (RIndex n t) =
1012− raw_apply (Var $ tacN "Index") [reflectName n, reflectRaw t]
1091+ where reflectConArg (RParameter n e t) =
1092+ raw_apply (Var $ tacN "Parameter") [reflectName n, reflectErasure e, reflectRaw t]
1093+ reflectConArg (RIndex n e t) =
1094+ raw_apply (Var $ tacN "Index") [reflectName n, reflectErasure e, reflectRaw t]