@@ -18,6 +18,7 @@ import Idris.Core.Typecheck (check, recheck)
18import Idris.ErrReverse (errReverse)
18import Idris.ErrReverse (errReverse)
19import Idris.ElabQuasiquote (extractUnquotes)
19import Idris.ElabQuasiquote (extractUnquotes)
20import Idris.Elab.Utils
20import Idris.Elab.Utils
21+import Idris.Reflection
21import qualified Util.Pretty as U
22import qualified Util.Pretty as U
23import Control.Applicative ((<$>))
24import Control.Applicative ((<$>))
@@ -36,6 +37,32 @@ import Debug.Trace
36data ElabMode = ETyDecl | ELHS | ERHS
37data ElabMode = ETyDecl | ELHS | ERHS
37 deriving Eq
38 deriving Eq
41+ ElabResult { resultTerm :: Term -- ^ The term resulting from elaboration
42+ , resultMetavars :: [(Name, (Int, Maybe Name, Type))]
43+ -- ^ Information about new metavariables
44+ , resultCaseDecls :: [PDecl]
45+ -- ^ Deferred declarations as the meaning of case blocks
46+ , resultContext :: Context
47+ -- ^ The potentially extended context from new definitions
48+ , resultTyDecls :: [(Name, FC, [PArg], Type)]
49+ -- ^ Meta-info about the new type declarations
52+processTacticDecls :: [(Name, FC, [PArg], Type)] -> Idris ()
53+processTacticDecls info =
54+ forM_ info $ \(n, fc, impls, ty) ->
55+ do logLvl 3 $ "Declaration from tactics: " ++ show n ++ " : " ++ show ty
56+ logLvl 3 $ " It has impls " ++ show impls
57+ updateIState $ \i -> i { idris_implicits =
58+ addDef n impls (idris_implicits i) }
60+ ds <- checkDef fc [(n, (-1, Nothing, ty))]
62+ let ds' = map (\(n, (i, top, t)) -> (n, (i, top, t, True))) ds
39-- Using the elaborator, convert a term in raw syntax to a fully
66-- Using the elaborator, convert a term in raw syntax to a fully
40-- elaborated, typechecked term.
67-- elaborated, typechecked term.
@@ -45,7 +72,7 @@ data ElabMode = ETyDecl | ELHS | ERHS
45-- Also find deferred names in the term and their types
72-- Also find deferred names in the term and their types
47build :: IState -> ElabInfo -> ElabMode -> FnOpts -> Name -> PTerm ->
74build :: IState -> ElabInfo -> ElabMode -> FnOpts -> Name -> PTerm ->
48− ElabD (Term, [(Name, (Int, Maybe Name, Type))], [PDecl])
75+ ElabD ElabResult
49build ist info emode opts fn tm
76build ist info emode opts fn tm
50 = do elab ist info emode opts fn tm
77 = do elab ist info emode opts fn tm
51 let tmIn = tm
78 let tmIn = tm
@@ -95,12 +122,13 @@ build ist info emode opts fn tm
95 when tydecl (do update_term orderPats
122 when tydecl (do update_term orderPats
97-- update_term liftPats)
124-- update_term liftPats)
98− EState is _ <- getAux
125+ EState is _ impls <- getAux
99 tt <- get_term
126 tt <- get_term
100 let (tm, ds) = runState (collectDeferred (Just fn) tt) []
127 let (tm, ds) = runState (collectDeferred (Just fn) tt) []
101 log <- getLog
128 log <- getLog
102− if (log /= "") then trace log $ return (tm, ds, is)
130+ if (log /= "") then trace log $ return (ElabResult tm ds is ctxt impls)
103− else return (tm, ds, is)
131+ else return (ElabResult tm ds is ctxt impls)
104 where pattern = emode == ELHS
132 where pattern = emode == ELHS
105 tydecl = emode == ETyDecl
133 tydecl = emode == ETyDecl
@@ -115,7 +143,7 @@ build ist info emode opts fn tm
115-- know about yet on the LHS of a pattern def)
143-- know about yet on the LHS of a pattern def)
117buildTC :: IState -> ElabInfo -> ElabMode -> FnOpts -> Name -> PTerm ->
145buildTC :: IState -> ElabInfo -> ElabMode -> FnOpts -> Name -> PTerm ->
118− ElabD (Term, [(Name, (Int, Maybe Name, Type))], [PDecl])
146+ ElabD ElabResult
119buildTC ist info emode opts fn tm
147buildTC ist info emode opts fn tm
120 = do -- set name supply to begin after highest index in tm
148 = do -- set name supply to begin after highest index in tm
121 let ns = allNamesIn tm
149 let ns = allNamesIn tm
@@ -136,12 +164,13 @@ buildTC ist info emode opts fn tm
136 -- unification
164 -- unification
137 when (not (null dots)) $
165 when (not (null dots)) $
138 lift (Error (CantMatch (getInferTerm tm)))
166 lift (Error (CantMatch (getInferTerm tm)))
139− EState is _ <- getAux
167+ EState is _ impls <- getAux
140 tt <- get_term
168 tt <- get_term
141 let (tm, ds) = runState (collectDeferred (Just fn) tt) []
169 let (tm, ds) = runState (collectDeferred (Just fn) tt) []
142 log <- getLog
170 log <- getLog
143− if (log /= "") then trace log $ return (tm, ds, is)
172+ if (log /= "") then trace log $ return (ElabResult tm ds is ctxt impls)
144− else return (tm, ds, is)
173+ else return (ElabResult tm ds is ctxt impls)
145 where pattern = emode == ELHS
174 where pattern = emode == ELHS
147-- return whether arguments of the given constructor name can be
176-- return whether arguments of the given constructor name can be
@@ -184,9 +213,9 @@ goal_polymorphic =
184 _ -> return True
213 _ -> return True
185 _ -> return False
214 _ -> return False
187−-- Returns the set of declarations we need to add to complete the definition
216+-- | Returns the set of declarations we need to add to complete the
188−-- (most likely case blocks to elaborate)
217+-- definition (most likely case blocks to elaborate) as well as
189−
218+-- declarations resulting from user tactic scripts (%runTactics)
190elab :: IState -> ElabInfo -> ElabMode -> FnOpts -> Name -> PTerm ->
219elab :: IState -> ElabInfo -> ElabMode -> FnOpts -> Name -> PTerm ->
192elab ist info emode opts fn tm
221elab ist info emode opts fn tm
@@ -970,10 +999,10 @@ elab ist info emode opts fn tm
970 = do -- First extract the unquoted subterms, replacing them with fresh
999 = do -- First extract the unquoted subterms, replacing them with fresh
971 -- names in the quasiquoted term. Claim their reflections to be
1000 -- names in the quasiquoted term. Claim their reflections to be
972 -- an inferred type (to support polytypic quasiquotes).
1001 -- an inferred type (to support polytypic quasiquotes).
973− qty <- goal
1002+ finalTy <- goal
974 (t, unq) <- extractUnquotes 0 t
1003 (t, unq) <- extractUnquotes 0 t
975 let unquoteNames = map fst unq
1004 let unquoteNames = map fst unq
976− mapM_ (\uqn -> claim uqn (forget qty)) unquoteNames
1005+ mapM_ (\uqn -> claim uqn (forget finalTy)) unquoteNames
978 -- Save the old state - we need a fresh proof state to avoid
1007 -- Save the old state - we need a fresh proof state to avoid
979 -- capturing lexically available variables in the quoted term.
1008 -- capturing lexically available variables in the quoted term.
@@ -1023,18 +1052,20 @@ elab ist info emode opts fn tm
1023 env <- get_env
1052 env <- get_env
1024 loadState
1053 loadState
1025 let quoted = fmap (explicitNames . binderVal) $ lookup nTm env
1054 let quoted = fmap (explicitNames . binderVal) $ lookup nTm env
1026−
1055+ isRaw = case unApply (normaliseAll ctxt env finalTy) of
1056+ (P _ n _, []) | n == reflm "Raw" -> True
1027 case quoted of
1058 case quoted of
1028 Just q -> do ctxt <- get_context
1059 Just q -> do ctxt <- get_context
1029 (q', _, _) <- lift $ recheck ctxt [(uq, Lam Erased) | uq <- unquoteNames] (forget q) q
1060 (q', _, _) <- lift $ recheck ctxt [(uq, Lam Erased) | uq <- unquoteNames] (forget q) q
1030 if pattern
1061 if pattern
1063+ then reflectRawQuotePattern unquoteNames (forget q')
1031− then do try' (reflectTTQuotePattern unquoteNames q')
1064+ else reflectTTQuotePattern unquoteNames q'
1032− (reflectRawQuotePattern unquoteNames (forget q'))
1065+ else do if isRaw
1034− else do try' (fill $ reflectTTQuote unquoteNames q')
1035− -- we forget q' instead of using q to ensure rechecking
1066+ then -- we forget q' instead of using q to ensure rechecking
1036− (fill $ reflectRawQuote unquoteNames (forget q'))
1067+ fill $ reflectRawQuote unquoteNames (forget q')
1037− True -- ignore errors like proof search does
1068+ else fill $ reflectTTQuote unquoteNames q'
1040 Nothing -> lift . tfail . Msg $ "Broken elaboration of quasiquote"
1071 Nothing -> lift . tfail . Msg $ "Broken elaboration of quasiquote"
@@ -1075,8 +1106,8 @@ elab ist info emode opts fn tm
1076 elab' ina (Just fc') tm
1107 elab' ina (Just fc') tm
1077 env <- get_env
1108 env <- get_env
1078− ctxt <- get_context
1079− runTactical (maybe fc' id fc) ctxt env (P Bound n' Erased)
1109+ runTactical (maybe fc' id fc) env (P Bound n' Erased)
1110+ EState _ _ todo <- getAux
1081 elab' ina fc x = fail $ "Unelaboratable syntactic form " ++ showTmImpls x
1112 elab' ina fc x = fail $ "Unelaboratable syntactic form " ++ showTmImpls x
@@ -1543,11 +1574,17 @@ case_ ind autoSolve ist fn tm = do
1543 else casetac (forget val)
1574 else casetac (forget val)
1544 when autoSolve solveAll
1575 when autoSolve solveAll
1577+tacN :: String -> Name
1578+tacN str = sNS (sUN str) ["Tactical", "Reflection", "Language"]
1546−runTactical :: FC -> Context -> Env -> Term -> ElabD ()
1580+runTactical :: FC -> Env -> Term -> ElabD ()
1547−runTactical fc ctxt env tm = runTacTm (eval tm) >> return ()
1581+runTactical fc env tm = do tm' <- eval tm
1585+ eval tm = do ctxt <- get_context
1549− eval = normaliseAll ctxt env . finalise
1586+ return $ normaliseAll ctxt env (finalise tm)
1550− tacN str = sNS (sUN str) ["Tactical", "Reflection", "Language"]
1587+
1551 returnUnit = fmap fst $ get_type_val (Var unitCon)
1588 returnUnit = fmap fst $ get_type_val (Var unitCon)
1553 -- | Do a step in the reflected elaborator monad. The input is the
1590 -- | Do a step in the reflected elaborator monad. The input is the
@@ -1585,26 +1622,31 @@ runTactical fc ctxt env tm = runTacTm (eval tm) >> return ()
1585 = do env <- get_env
1622 = do env <- get_env
1586 fmap fst . get_type_val $ reflectEnv env
1623 fmap fst . get_type_val $ reflectEnv env
1587 | n == tacN "prim__Fail", [_a, errs] <- args
1624 | n == tacN "prim__Fail", [_a, errs] <- args
1625+ = do errs' <- eval errs
1588− = do parts <- reifyReportParts (eval errs)
1626+ parts <- reifyReportParts errs'
1589 lift . tfail $ ReflectionError [parts] (Msg "")
1627 lift . tfail $ ReflectionError [parts] (Msg "")
1590 | n == tacN "prim__PureTactical", [_a, tm] <- args
1628 | n == tacN "prim__PureTactical", [_a, tm] <- args
1591 = return tm
1629 = return tm
1592 | n == tacN "prim__BindTactical", [_a, _b, first, andThen] <- args
1630 | n == tacN "prim__BindTactical", [_a, _b, first, andThen] <- args
1593− = do let first' = eval first
1631+ = do first' <- eval first
1594 res <- runTacTm first'
1632 res <- runTacTm first'
1595− let next = eval (App andThen res)
1633+ next <- eval (App andThen res)
1596 runTacTm next
1634 runTacTm next
1597 | n == tacN "prim__Try", [_a, first, alt] <- args
1635 | n == tacN "prim__Try", [_a, first, alt] <- args
1598− = do let first' = eval first
1636+ = do first' <- eval first
1599− let alt' = eval alt
1637+ alt' <- eval alt
1600 try' (runTacTm first') (runTacTm alt') True
1638 try' (runTacTm first') (runTacTm alt') True
1601 | n == tacN "prim__Fill", [raw] <- args
1639 | n == tacN "prim__Fill", [raw] <- args
1602 = do raw' <- reifyRaw raw
1640 = do raw' <- reifyRaw raw
1603 apply raw' []
1641 apply raw' []
1604 returnUnit
1642 returnUnit
1605− | n == tacN "prim__Gensym", [eval -> Constant (Str hint)] <- args
1643+ | n == tacN "prim__Gensym", [hint] <- args
1644+ = do hintStr <- eval hint
1646+ Constant (Str h) -> do
1606− = do n <- getNameFrom (sMN 0 hint)
1647+ n <- getNameFrom (sMN 0 h)
1607− fmap fst $ get_type_val (reflectName n)
1648+ fmap fst $ get_type_val (reflectName n)
1649+ _ -> fail "no hint"
1608 | n == tacN "prim__Claim", [n, ty] <- args
1650 | n == tacN "prim__Claim", [n, ty] <- args
1609 = do n' <- reifyTTName n
1651 = do n' <- reifyTTName n
1610 ty' <- reifyRaw ty
1652 ty' <- reifyRaw ty
@@ -1634,6 +1676,29 @@ runTactical fc ctxt env tm = runTacTm (eval tm) >> return ()
1634 Just name -> fmap Just $ reifyTTName name
1676 Just name -> fmap Just $ reifyTTName name
1636 returnUnit
1678 returnUnit
1679+ | n == tacN "prim__DeclareType", [decl] <- args
1680+ = do (RDeclare n args res) <- reifyTyDecl decl
1681+ ctxt <- get_context
1682+ let mkPi arg res = RBind (argName arg)
1683+ (Pi Nothing (argTy arg) (RUType AllTypes))
1685+ rty = foldr mkPi res args
1686+ (checked, ty') <- lift $ check ctxt [] rty
1687+ case normaliseAll ctxt [] (finalise ty') of
1688+ TType _ -> lift . tfail . InternalMsg $
1689+ show checked ++ " is not a type: it's " ++ show ty'
1691+ case lookupDefExact n ctxt of
1692+ Just _ -> lift . tfail . InternalMsg $
1693+ show n ++ " is already defined."
1694+ Nothing -> return ()
1695+ let decl = TyDecl Ref checked
1696+ ctxt' = addCtxtDef n decl ctxt
1698+ updateAux $ \e -> e { new_tyDecls = (n, fc, map rArgToPArg args, checked) :
1637 | n == tacN "prim__Debug", [ty, msg] <- args
1702 | n == tacN "prim__Debug", [ty, msg] <- args
1638 = do let msg' = fromTTMaybe msg
1703 = do let msg' = fromTTMaybe msg
1639 case msg' of
1704 case msg' of
@@ -2400,7 +2465,7 @@ reflectTTQuote unq (P nt n t)
2400reflectTTQuote unq (V n)
2465reflectTTQuote unq (V n)
2401 = reflCall "V" [RConstant (I n)]
2466 = reflCall "V" [RConstant (I n)]
2402reflectTTQuote unq (Bind n b x)
2467reflectTTQuote unq (Bind n b x)
2403− = reflCall "Bind" [reflectName n, reflectBinderQuote reflectTTQuote unq b, reflectTTQuote unq x]
2468+ = reflCall "Bind" [reflectName n, reflectBinderQuote reflectTTQuote (reflm "TT") unq b, reflectTTQuote unq x]
2404reflectTTQuote unq (App f x)
2469reflectTTQuote unq (App f x)
2405 = reflCall "App" [reflectTTQuote unq f, reflectTTQuote unq x]
2470 = reflCall "App" [reflectTTQuote unq f, reflectTTQuote unq x]
2406reflectTTQuote unq (Constant c)
2471reflectTTQuote unq (Constant c)
@@ -2417,7 +2482,7 @@ reflectRawQuote unq (Var n)
2417 | n `elem` unq = Var n
2482 | n `elem` unq = Var n
2418 | otherwise = reflCall "Var" [reflectName n]
2483 | otherwise = reflCall "Var" [reflectName n]
2419reflectRawQuote unq (RBind n b r) =
2484reflectRawQuote unq (RBind n b r) =
2420− reflCall "RBind" [reflectName n, reflectBinderQuote reflectRawQuote unq b, reflectRawQuote unq r]
2485+ reflCall "RBind" [reflectName n, reflectBinderQuote reflectRawQuote (reflm "Raw") unq b, reflectRawQuote unq r]
2421reflectRawQuote unq (RApp f x) =
2486reflectRawQuote unq (RApp f x) =
2422 reflCall "RApp" [reflectRawQuote unq f, reflectRawQuote unq x]
2487 reflCall "RApp" [reflectRawQuote unq f, reflectRawQuote unq x]
2423reflectRawQuote unq RType = Var (reflm "RType")
2488reflectRawQuote unq RType = Var (reflm "RType")
@@ -2475,27 +2540,27 @@ reflectNameQuotePattern _ -- for all other names, match any
2477reflectBinder :: Binder Term -> Raw
2542reflectBinder :: Binder Term -> Raw
2478−reflectBinder = reflectBinderQuote reflectTTQuote []
2543+reflectBinder = reflectBinderQuote reflectTTQuote (reflm "TT") []
2480−reflectBinderQuote :: ([Name] -> a -> Raw) -> [Name] -> Binder a -> Raw
2545+reflectBinderQuote :: ([Name] -> a -> Raw) -> Name -> [Name] -> Binder a -> Raw
2481−reflectBinderQuote q unq (Lam t)
2546+reflectBinderQuote q ty unq (Lam t)
2482− = reflCall "Lam" [Var (reflm "TT"), q unq t]
2547+ = reflCall "Lam" [Var ty, q unq t]
2483−reflectBinderQuote q unq (Pi _ t k)
2548+reflectBinderQuote q ty unq (Pi _ t k)
2484− = reflCall "Pi" [Var (reflm "TT"), q unq t, q unq k]
2549+ = reflCall "Pi" [Var ty, q unq t, q unq k]
2485−reflectBinderQuote q unq (Let x y)
2550+reflectBinderQuote q ty unq (Let x y)
2486− = reflCall "Let" [Var (reflm "TT"), q unq x, q unq y]
2551+ = reflCall "Let" [Var ty, q unq x, q unq y]
2487−reflectBinderQuote q unq (NLet x y)
2552+reflectBinderQuote q ty unq (NLet x y)
2488− = reflCall "NLet" [Var (reflm "TT"), q unq x, q unq y]
2553+ = reflCall "NLet" [Var ty, q unq x, q unq y]
2489−reflectBinderQuote q unq (Hole t)
2554+reflectBinderQuote q ty unq (Hole t)
2490− = reflCall "Hole" [Var (reflm "TT"), q unq t]
2555+ = reflCall "Hole" [Var ty, q unq t]
2491−reflectBinderQuote q unq (GHole _ t)
2556+reflectBinderQuote q ty unq (GHole _ t)
2492− = reflCall "GHole" [Var (reflm "TT"), q unq t]
2557+ = reflCall "GHole" [Var ty, q unq t]
2493−reflectBinderQuote q unq (Guess x y)
2558+reflectBinderQuote q ty unq (Guess x y)
2494− = reflCall "Guess" [Var (reflm "TT"), q unq x, q unq y]
2559+ = reflCall "Guess" [Var ty, q unq x, q unq y]
2495−reflectBinderQuote q unq (PVar t)
2560+reflectBinderQuote q ty unq (PVar t)
2496− = reflCall "PVar" [Var (reflm "TT"), q unq t]
2561+ = reflCall "PVar" [Var ty, q unq t]
2497−reflectBinderQuote q unq (PVTy t)
2562+reflectBinderQuote q ty unq (PVTy t)
2498− = reflCall "PVTy" [Var (reflm "TT"), q unq t]
2563+ = reflCall "PVTy" [Var ty, q unq t]
2500mkList :: Raw -> [Raw] -> Raw
2565mkList :: Raw -> [Raw] -> Raw
2501mkList ty [] = RApp (Var (sNS (sUN "Nil") ["List", "Prelude"])) ty
2566mkList ty [] = RApp (Var (sNS (sUN "Nil") ["List", "Prelude"])) ty
@@ -2790,6 +2855,28 @@ reifyReportPart (App (P (DCon _ _ _) n _) tm)
2790 Nothing -> Left . InternalMsg $ "could not reify subreport " ++ show tm
2855 Nothing -> Left . InternalMsg $ "could not reify subreport " ++ show tm
2791reifyReportPart x = Left . InternalMsg $ "could not reify " ++ show x
2856reifyReportPart x = Left . InternalMsg $ "could not reify " ++ show x
2858+reifyTyDecl :: Term -> ElabD RTyDecl
2859+reifyTyDecl (App (App (App (P (DCon _ _ _) n _) tyN) args) ret)
2860+ | n == tacN "Declare" =
2861+ do tyN' <- reifyTTName tyN
2862+ args' <- case unList args of
2863+ Nothing -> fail $ "Couldn't reify " ++ show args ++ " as an arglist."
2864+ Just xs -> mapM reifyRArg xs
2865+ ret' <- reifyRaw ret
2866+ return $ RDeclare tyN' args' ret'
2867+ where reifyRArg :: Term -> ElabD RArg
2868+ reifyRArg (App (App (P (DCon _ _ _) n _) argN) argTy)
2869+ | n == tacN "Explicit" = liftM2 RExplicit
2872+ | n == tacN "Implicit" = liftM2 RImplicit
2874+ (reifyRaw argTy) | n == tacN "Constraint" = liftM2 RConstraint
2877+ reifyRArg aTm = fail $ "Couldn't reify " ++ show aTm ++ " as an RArg."
2878+reifyTyDecl tm = fail $ "Couldn't reify " ++ show tm ++ " as a type declaration."
2793envTupleType :: Raw
2880envTupleType :: Raw
2794envTupleType
2881envTupleType
2795 = raw_apply (Var pairTy) [ (Var $ reflm "TTName")
2882 = raw_apply (Var pairTy) [ (Var $ reflm "TTName")