@@ -13,10 +13,14 @@ import Idris.Core.TT
13import Idris.Core.Evaluate
13import Idris.Core.Evaluate
14import Idris.Core.Typecheck (check)
14import Idris.Core.Typecheck (check)
16+import Control.Applicative ((<$>))
16import Control.Monad
17import Control.Monad
17import Control.Monad.State.Strict
18import Control.Monad.State.Strict
18import Data.List
19import Data.List
20+import qualified Data.Map as M
19import Data.Maybe (mapMaybe)
21import Data.Maybe (mapMaybe)
22+import qualified Data.Set as S
23+import qualified Data.Text as T
21import Debug.Trace
25import Debug.Trace
@@ -153,13 +157,18 @@ elab ist info pattern opts fn tm
154 local f = do e <- get_env
158 local f = do e <- get_env
155 return (f `elem` map fst e)
159 return (f `elem` map fst e)
161+ -- | Is a constant a type?
162+ constType :: Const -> Bool
157 constType (AType _) = True
163 constType (AType _) = True
158 constType StrType = True
164 constType StrType = True
159 constType PtrType = True
165 constType PtrType = True
160 constType VoidType = True
166 constType VoidType = True
161 constType _ = False
167 constType _ = False
169+ elab' :: (Bool, Bool, Bool) -- ^ (in an argument, guarded, in a type)
170+ -> PTerm -- ^ The term to elaborate
163 elab' ina (PNoImplicits t) = elab' ina t -- skip elabE step
172 elab' ina (PNoImplicits t) = elab' ina t -- skip elabE step
164 elab' ina PType = do apply RType []; solve
173 elab' ina PType = do apply RType []; solve
165 elab' (_,_,inty) (PConstant c)
174 elab' (_,_,inty) (PConstant c)
@@ -387,7 +396,7 @@ elab ist info pattern opts fn tm
388 elab' (_, _, inty) (PApp fc (PRef _ f) args')
397 elab' (_, _, inty) (PApp fc (PRef _ f) args')
389 | isTConName f (tt_ctxt ist) && pattern && not reflect && not inty
398 | isTConName f (tt_ctxt ist) && pattern && not reflect && not inty
390− = lift $ tfail (Msg "Typecase is not allowed")
399+ = lift $ tfail (Msg "Typecase is not allowed")
391 -- if f is local, just do a simple_app
400 -- if f is local, just do a simple_app
392 elab' (ina, g, inty) tm@(PApp fc (PRef _ f) args)
401 elab' (ina, g, inty) tm@(PApp fc (PRef _ f) args)
393 = do env <- get_env
402 = do env <- get_env
@@ -410,16 +419,18 @@ elab ist info pattern opts fn tm
410 _ -> mapM_ setInjective (map getTm args)
419 _ -> mapM_ setInjective (map getTm args)
411 ctxt <- get_context
420 ctxt <- get_context
412 let guarded = isConName f ctxt
421 let guarded = isConName f ctxt
422+-- trace ("args is " ++ show args) $ return ()
413 ns <- apply (Var f) (map isph args)
423 ns <- apply (Var f) (map isph args)
424+-- trace ("ns is " ++ show ns) $ return ()
414 -- Sort so that the implicit tactics and alternatives go last
425 -- Sort so that the implicit tactics and alternatives go last
415 let (ns', eargs) = unzip $
426 let (ns', eargs) = unzip $
416 sortBy cmpArg (zip ns args)
427 sortBy cmpArg (zip ns args)
417− elabArgs (ina || not isinf, guarded, inty)
428+ elabArgs ist (ina || not isinf, guarded, inty)
418− [] fc False ns' (map (\x -> (lazyarg x, getTm x)) eargs)
429+ [] fc False f ns' (map (\x -> (lazyarg x, getTm x)) eargs)
420 ivs' <- get_instances
431 ivs' <- get_instances
421− -- Attempt to resolve any type classes which have 'complete' types,
432+ -- Attempt to resolve any type classes which have 'complete' types,
422− -- i.e. no holes in them
433+ -- i.e. no holes in them
423 when (not pattern || (ina && not tcgen && not guarded)) $
434 when (not pattern || (ina && not tcgen && not guarded)) $
424 mapM_ (\n -> do focus n
435 mapM_ (\n -> do focus n
425 g <- goal
436 g <- goal
@@ -603,31 +614,74 @@ elab ist info pattern opts fn tm
603 mkCoerce t n = let fc = fileFC "Coercion" in -- line never appears!
614 mkCoerce t n = let fc = fileFC "Coercion" in -- line never appears!
604 addImpl ist (PApp fc (PRef fc n) [pexp (PCoerced t)])
615 addImpl ist (PApp fc (PRef fc n) [pexp (PCoerced t)])
617+ -- | Elaborate the arguments to a function
618+ elabArgs :: IState -- ^ The current Idris state
619+ -> (Bool, Bool, Bool) -- ^ (in an argument, guarded, in a type)
621+ -> FC -- ^ Source location
623+ -> Name -- ^ Name of the function being applied
624+ -> [(Name, Name)] -- ^ (Argument Name, Hole Name)
625+ -> [(Bool, PTerm)] -- ^ (Laziness, argument)
606− elabArgs ina failed fc retry [] _
627+ elabArgs ist ina failed fc retry f [] _
607-- | retry = let (ns, ts) = unzip (reverse failed) in
628-- | retry = let (ns, ts) = unzip (reverse failed) in
608-- elabArgs ina [] False ns ts
629-- elabArgs ina [] False ns ts
609 | otherwise = return ()
630 | otherwise = return ()
610− elabArgs ina failed fc r (n:ns) ((_, Placeholder) : args)
631+ elabArgs ist ina failed fc r f (n:ns) ((_, Placeholder) : args)
611− = elabArgs ina failed fc r ns args
632+ = elabArgs ist ina failed fc r f ns args
612− elabArgs ina failed fc r (n:ns) ((lazy, t) : args)
633+ elabArgs ist ina failed fc r f ((argName, holeName):ns) ((lazy, t) : args)
613 | lazy && not pattern
634 | lazy && not pattern
614− = do elabArg n (PApp bi (PRef bi (sUN "lazy"))
635+ = elabArg argName holeName (PApp bi (PRef bi (sUN "lazy"))
615− [pimp (sUN "a") Placeholder True,
636+ [pimp (sUN "a") Placeholder True,
616− pexp t]);
637+ pexp t])
617− | otherwise = elabArg n t
638+ | otherwise = elabArg argName holeName t
618− where elabArg n t
639+ where elabArg argName holeName t =
640+ reflectFunctionErrors ist f argName $
619− = do hs <- get_holes
641+ do hs <- get_holes
620− tm <- get_term
642+ tm <- get_term
621− failed' <- -- trace (show (n, t, hs, tm)) $
643+ failed' <- -- trace (show (n, t, hs, tm)) $
622− -- traceWhen (not (null cs)) (show ty ++ "\n" ++ showImp True t) $
644+ -- traceWhen (not (null cs)) (show ty ++ "\n" ++ showImp True t) $
623− case n `elem` hs of
645+ case holeName `elem` hs of
626−-- then try (do focus n; elabE ina t; return failed)
646+ True -> do focus holeName; elabE ina t; return failed
627−-- (return ((n,(lazy, t)):failed))
628− do focus n; elabE ina t; return failed
629− False -> return failed
647+ False -> return failed
630− elabArgs ina failed fc r ns args
648+ elabArgs ist ina failed fc r f ns args
650+-- | Perform error reflection for function applicaitons with specific error handlers
651+reflectFunctionErrors :: IState -> Name -> Name -> ElabD a -> ElabD a
652+reflectFunctionErrors ist f arg action =
654+ (result, newState) <- case runStateT action elabState of
655+ OK (res, newState) -> return (res, newState)
656+ Error e@(ReflectionError _ _) -> (lift . tfail) e
657+ Error e@(ReflectionFailed _ _) -> (lift . tfail) e
658+ Error e -> handle e >>= lift . tfail
661+ where handle :: Err -> ElabD Err
662+ handle e = do let funhandlers = (maybe M.empty id . lookupCtxtExact f . idris_function_errorhandlers) ist
663+ handlers = (maybe [] S.toList . M.lookup arg) funhandlers
664+ reports = map (\n -> RApp (Var n) (reflectErr e)) handlers
667+ -- Typecheck error handlers - if this fails, then something else was wrong earlier!
668+ handlers <- case mapM (check (tt_ctxt ist) []) reports of
669+ Error e -> lift . tfail $
670+ ReflectionFailed "Type error while constructing reflected error" e
673+ -- Normalize error handler terms to produce the new messages
674+ let ctxt = tt_ctxt ist
675+ results = map (normalise ctxt []) (map fst handlers)
677+ -- For each handler term output, either discard it if it is Nothing or reify it the Haskell equivalent
678+ let errorpartsTT = mapMaybe unList (mapMaybe fromTTMaybe results)
679+ errorparts <- case mapM (mapM reifyReportPart) errorpartsTT of
680+ Left err -> lift (tfail err)
681+ Right ok -> return ok
682+ return $ case errorparts of
684+ parts -> ReflectionError errorparts e
632-- For every alternative, look at the function at the head. Automatically resolve
686-- For every alternative, look at the function at the head. Automatically resolve
633-- any nested alternatives where that function is also at the head
687-- any nested alternatives where that function is also at the head
@@ -764,8 +818,8 @@ resolveTC depth topg fn ist
764 [args] -> map isImp (snd args) -- won't be overloaded!
818 [args] -> map isImp (snd args) -- won't be overloaded!
765 ps <- get_probs
819 ps <- get_probs
766 tm <- get_term
820 tm <- get_term
767− args <- try' (apply (Var n) imps)
821+ args <- map snd <$> try' (apply (Var n) imps)
768− (match_apply (Var n) imps) True
822+ (match_apply (Var n) imps) True
769 ps' <- get_probs
823 ps' <- get_probs
770 when (length ps < length ps') $ fail "Can't apply type class"
824 when (length ps < length ps') $ fail "Can't apply type class"
771-- traceWhen (all boundVar ttypes) ("Progress: " ++ show t ++ " with " ++ show n) $
825-- traceWhen (all boundVar ttypes) ("Progress: " ++ show t ++ " with " ++ show n) $
@@ -778,7 +832,7 @@ resolveTC depth topg fn ist
778 -- if there's any arguments left, we've failed to resolve
832 -- if there's any arguments left, we've failed to resolve
779 hs <- get_holes
833 hs <- get_holes
780 ulog <- getUnifyLog
834 ulog <- getUnifyLog
782 traceWhen ulog ("Got " ++ show n) $ return ()
836 traceWhen ulog ("Got " ++ show n) $ return ()
783 where isImp (PImp p _ _ _ _ _) = (True, p)
837 where isImp (PImp p _ _ _ _ _) = (True, p)
784 isImp arg = (False, priority arg)
838 isImp arg = (False, priority arg)
@@ -1134,7 +1188,7 @@ reifyRawApp t [c]
1134reifyRawApp t args = fail ("Unknown reflection raw term: " ++ show (t, args))
1188reifyRawApp t args = fail ("Unknown reflection raw term: " ++ show (t, args))
1136reifyTTName :: Term -> ElabD Name
1190reifyTTName :: Term -> ElabD Name
1137−reifyTTName t@(App _ _)
1191+reifyTTName t
1138 | (P _ f _, args) <- unApply t = reifyTTNameApp f args
1192 | (P _ f _, args) <- unApply t = reifyTTNameApp f args
1139reifyTTName t = fail ("Unknown reflection term name: " ++ show t)
1193reifyTTName t = fail ("Unknown reflection term name: " ++ show t)
@@ -1470,6 +1524,7 @@ reflectErr (LoadingFailed str err) =
1470 raw_apply (Var $ reflErrName "LoadingFailed") [RConstant (Str str)]
1524 raw_apply (Var $ reflErrName "LoadingFailed") [RConstant (Str str)]
1471reflectErr x = raw_apply (Var (sNS (sUN "Msg") ["Errors", "Reflection", "Language"])) [RConstant . Str $ "Default reflection: " ++ show x]
1525reflectErr x = raw_apply (Var (sNS (sUN "Msg") ["Errors", "Reflection", "Language"])) [RConstant . Str $ "Default reflection: " ++ show x]
1473withErrorReflection :: Idris a -> Idris a
1528withErrorReflection :: Idris a -> Idris a
1474withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
1529withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
1475 where handle :: Err -> Idris Err
1530 where handle :: Err -> Idris Err
@@ -1495,47 +1550,50 @@ withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
1496 -- For each handler term output, either discard it if it is Nothing or reify it the Haskell equivalent
1551 -- For each handler term output, either discard it if it is Nothing or reify it the Haskell equivalent
1497 let errorpartsTT = mapMaybe unList (mapMaybe fromTTMaybe results)
1552 let errorpartsTT = mapMaybe unList (mapMaybe fromTTMaybe results)
1498− errorparts <- mapM (mapM reifyReportPart) errorpartsTT
1553+ errorparts <- case mapM (mapM reifyReportPart) errorpartsTT of
1499−
1554+ Left err -> ierror err
1555+ Right ok -> return ok
1500 return $ case errorparts of
1556 return $ case errorparts of
1502 parts -> ReflectionError errorparts e
1558 parts -> ReflectionError errorparts e
1504− fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
1560+fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
1505− fromTTMaybe (App (App (P (DCon _ _) (NS (UN just) _) _) ty) tm)
1561+fromTTMaybe (App (App (P (DCon _ _) (NS (UN just) _) _) ty) tm)
1506− | just == txt "Just" = Just tm
1562+ | just == txt "Just" = Just tm
1507− fromTTMaybe x = Nothing
1563+fromTTMaybe x = Nothing
1509reflErrName :: String -> Name
1565reflErrName :: String -> Name
1510reflErrName n = sNS (sUN n) ["Errors", "Reflection", "Language"]
1566reflErrName n = sNS (sUN n) ["Errors", "Reflection", "Language"]
1568+-- | Attempt to reify a report part from TT to the internal
1569+-- representation. Not in Idris or ElabD monads because it should be usable
1512−reifyReportPart :: Term -> Idris ErrorReportPart
1571+reifyReportPart :: Term -> Either Err ErrorReportPart
1513reifyReportPart (App (P (DCon _ _) n _) (Constant (Str msg))) | n == reflErrName "TextPart" =
1572reifyReportPart (App (P (DCon _ _) n _) (Constant (Str msg))) | n == reflErrName "TextPart" =
1514− return (TextPart msg)
1573+ Right (TextPart msg)
1515reifyReportPart (App (P (DCon _ _) n _) ttn)
1574reifyReportPart (App (P (DCon _ _) n _) ttn)
1516 | n == reflErrName "NamePart" =
1575 | n == reflErrName "NamePart" =
1517 case runElab [] (reifyTTName ttn) (initElaborator NErased initContext Erased) of
1576 case runElab [] (reifyTTName ttn) (initElaborator NErased initContext Erased) of
1518− Error e -> ierror . InternalMsg $
1577+ Error e -> Left . InternalMsg $
1519 "could not reify name term " ++
1578 "could not reify name term " ++
1520 show ttn ++
1579 show ttn ++
1521− " when reflecting an error"
1580+ " when reflecting an error:" ++ show e
1522− OK (n', _)-> return $ NamePart n'
1581+ OK (n', _)-> Right $ NamePart n'
1523reifyReportPart (App (P (DCon _ _) n _) tm)
1582reifyReportPart (App (P (DCon _ _) n _) tm)
1524 | n == reflErrName "TermPart" =
1583 | n == reflErrName "TermPart" =
1525− do ist <- getIState
1526− case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
1584+ case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
1527− Error e -> ierror . InternalMsg $
1585+ Error e -> Left . InternalMsg $
1528− "could not reify reflected term " ++
1586+ "could not reify reflected term " ++
1529− show tm ++
1587+ show tm ++
1530− " when reflecting an error"
1588+ " when reflecting an error:" ++ show e
1531− OK (tm', _) -> return $ TermPart tm'
1589+ OK (tm', _) -> Right $ TermPart tm'
1532reifyReportPart (App (P (DCon _ _) n _) tm)
1590reifyReportPart (App (P (DCon _ _) n _) tm)
1533 | n == reflErrName "SubReport" =
1591 | n == reflErrName "SubReport" =
1534− case unList tm of
1592+ case unList tm of
1535− Just xs -> do subParts <- mapM reifyReportPart xs
1593+ Just xs -> do subParts <- mapM reifyReportPart xs
1536− return (SubReport subParts)
1594+ Right (SubReport subParts)
1537− Nothing -> ierror . InternalMsg $ "could not reify subreport " ++ show tm
1595+ Nothing -> Left . InternalMsg $ "could not reify subreport " ++ show tm
1538−reifyReportPart x = ierror . InternalMsg $ "could not reify " ++ show x
1596+reifyReportPart x = Left . InternalMsg $ "could not reify " ++ show x
1540envTupleType :: Raw
1598envTupleType :: Raw
1541envTupleType
1599envTupleType