@@ -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
@@ -396,7 +400,7 @@ elab ist info pattern opts fn tm
397 elab' (_, _, inty) (PApp fc (PRef _ f) args')
401 elab' (_, _, inty) (PApp fc (PRef _ f) args')
398 | isTConName f (tt_ctxt ist) && pattern && not reflect && not inty
402 | isTConName f (tt_ctxt ist) && pattern && not reflect && not inty
399− = lift $ tfail (Msg "Typecase is not allowed")
403+ = lift $ tfail (Msg "Typecase is not allowed")
400 -- if f is local, just do a simple_app
404 -- if f is local, just do a simple_app
401 elab' (ina, g, inty) tm@(PApp fc (PRef _ f) args)
405 elab' (ina, g, inty) tm@(PApp fc (PRef _ f) args)
402 = do env <- get_env
406 = do env <- get_env
@@ -419,12 +423,14 @@ elab ist info pattern opts fn tm
419 _ -> mapM_ setInjective (map getTm args)
423 _ -> mapM_ setInjective (map getTm args)
420 ctxt <- get_context
424 ctxt <- get_context
421 let guarded = isConName f ctxt
425 let guarded = isConName f ctxt
426+-- trace ("args is " ++ show args) $ return ()
422 ns <- apply (Var f) (map isph args)
427 ns <- apply (Var f) (map isph args)
428+-- trace ("ns is " ++ show ns) $ return ()
423 -- Sort so that the implicit tactics and alternatives go last
429 -- Sort so that the implicit tactics and alternatives go last
424 let (ns', eargs) = unzip $
430 let (ns', eargs) = unzip $
425 sortBy cmpArg (zip ns args)
431 sortBy cmpArg (zip ns args)
426− elabArgs (ina || not isinf, guarded, inty)
432+ elabArgs ist (ina || not isinf, guarded, inty)
427− [] fc False ns' (map (\x -> (lazyarg x, getTm x)) eargs)
433+ [] fc False f ns' (map (\x -> (lazyarg x, getTm x)) eargs)
429 ivs' <- get_instances
435 ivs' <- get_instances
430 -- Attempt to resolve any type classes which have 'complete' types,
436 -- Attempt to resolve any type classes which have 'complete' types,
@@ -613,45 +619,73 @@ elab ist info pattern opts fn tm
613 addImpl ist (PApp fc (PRef fc n) [pexp (PCoerced t)])
619 addImpl ist (PApp fc (PRef fc n) [pexp (PCoerced t)])
615 -- | Elaborate the arguments to a function
621 -- | Elaborate the arguments to a function
622+ elabArgs :: IState -- ^ The current Idris state
616− elabArgs :: (Bool, Bool, Bool) -- ^ (in an argument, guarded, in a type)
623+ -> (Bool, Bool, Bool) -- ^ (in an argument, guarded, in a type)
617 -> [Bool]
624 -> [Bool]
618 -> FC -- ^ Source location
625 -> FC -- ^ Source location
620− -> [Name] -- ^ Names of arguments - these identify the holes to be filled
627+ -> Name -- ^ Name of the function being applied
628+ -> [(Name, Name)] -- ^ (Argument Name, Hole Name)
621 -> [(Bool, PTerm)] -- ^ (Laziness, argument)
629 -> [(Bool, PTerm)] -- ^ (Laziness, argument)
622 -> ElabD ()
630 -> ElabD ()
623− elabArgs ina failed fc retry [] _
631+ elabArgs ist ina failed fc retry f [] _
624-- | retry = let (ns, ts) = unzip (reverse failed) in
632-- | retry = let (ns, ts) = unzip (reverse failed) in
625-- elabArgs ina [] False ns ts
633-- elabArgs ina [] False ns ts
626 | otherwise = return ()
634 | otherwise = return ()
627− elabArgs ina failed fc r (n:ns) ((_, Placeholder) : args)
635+ elabArgs ist ina failed fc r f (n:ns) ((_, Placeholder) : args)
628− = elabArgs ina failed fc r ns args
636+ = elabArgs ist ina failed fc r f ns args
629− elabArgs ina failed fc r (n:ns) ((lazy, t) : args)
637+ elabArgs ist ina failed fc r f ((argName, holeName):ns) ((lazy, t) : args)
630 | lazy && not pattern
638 | lazy && not pattern
631− = do elabArg n (PApp bi (PRef bi (sUN "lazy"))
639+ = elabArg argName holeName (PApp bi (PRef bi (sUN "lazy"))
632− [pimp (sUN "a") Placeholder True,
640+ [pimp (sUN "a") Placeholder True,
633− pexp t]);
641+ pexp t])
634− | otherwise = elabArg n t
642+ | otherwise = elabArg argName holeName t
635− where elabArg n t
643+ where elabArg argName holeName t =
644+ reflectFunctionErrors ist f argName $
636− = do hs <- get_holes
645+ do hs <- get_holes
637− tm <- get_term
646+ tm <- get_term
638− failed' <- -- trace (show (n, t, hs, tm)) $
647+ failed' <- -- trace (show (n, t, hs, tm)) $
639− -- traceWhen (not (null cs)) (show ty ++ "\n" ++ showImp True t) $
648+ -- traceWhen (not (null cs)) (show ty ++ "\n" ++ showImp True t) $
640− case n `elem` hs of
649+ case holeName `elem` hs of
641− True -> do focus n; elabE ina t; return failed
650+ True -> do focus holeName; elabE ina t; return failed
642− False -> return failed
651+ False -> return failed
643− elabArgs ina failed fc r ns args
652+ elabArgs ist ina failed fc r f ns args
645−-- | Perform error reflection for functions with specific error handlers
654+-- | Perform error reflection for function applicaitons with specific error handlers
646−reflectFunctionErrors :: IState -> Name -> ElabD a -> ElabD a
655+reflectFunctionErrors :: IState -> Name -> Name -> ElabD a -> ElabD a
647−reflectFunctionErrors ist f action =
656+reflectFunctionErrors ist f arg action =
648 do elabState <- get
657 do elabState <- get
649 (result, newState) <- case runStateT action elabState of
658 (result, newState) <- case runStateT action elabState of
650 OK (res, newState) -> return (res, newState)
659 OK (res, newState) -> return (res, newState)
651− Error e -> lift (tfail e) -- TODO: actual error reflection!
660+ Error e@(ReflectionError _ _) -> (lift . tfail) e
661+ Error e@(ReflectionFailed _ _) -> (lift . tfail) e
662+ Error e -> handle e >>= lift . tfail
652 put newState
663 put newState
653 return result
664 return result
665+ where handle :: Err -> ElabD Err
666+ handle e = do let funhandlers = (maybe M.empty id . lookupCtxtExact f . idris_function_errorhandlers) ist
667+ handlers = (maybe [] S.toList . M.lookup arg) funhandlers
668+ reports = map (\n -> RApp (Var n) (reflectErr e)) handlers
671+ -- Typecheck error handlers - if this fails, then something else was wrong earlier!
672+ handlers <- case mapM (check (tt_ctxt ist) []) reports of
673+ Error e -> lift . tfail $
674+ ReflectionFailed "Type error while constructing reflected error" e
677+ -- Normalize error handler terms to produce the new messages
678+ let ctxt = tt_ctxt ist
679+ results = map (normalise ctxt []) (map fst handlers)
681+ -- For each handler term output, either discard it if it is Nothing or reify it the Haskell equivalent
682+ let errorpartsTT = mapMaybe unList (mapMaybe fromTTMaybe results)
683+ errorparts <- case mapM (mapM reifyReportPart) errorpartsTT of
684+ Left err -> lift (tfail err)
685+ Right ok -> return ok
686+ return $ case errorparts of
688+ parts -> ReflectionError errorparts e
656-- For every alternative, look at the function at the head. Automatically resolve
690-- For every alternative, look at the function at the head. Automatically resolve
657-- any nested alternatives where that function is also at the head
691-- any nested alternatives where that function is also at the head
@@ -788,8 +822,8 @@ resolveTC depth topg fn ist
788 [args] -> map isImp (snd args) -- won't be overloaded!
822 [args] -> map isImp (snd args) -- won't be overloaded!
789 ps <- get_probs
823 ps <- get_probs
790 tm <- get_term
824 tm <- get_term
791− args <- try' (apply (Var n) imps)
825+ args <- map snd <$> try' (apply (Var n) imps)
792− (match_apply (Var n) imps) True
826+ (match_apply (Var n) imps) True
793 ps' <- get_probs
827 ps' <- get_probs
794 when (length ps < length ps') $ fail "Can't apply type class"
828 when (length ps < length ps') $ fail "Can't apply type class"
795-- traceWhen (all boundVar ttypes) ("Progress: " ++ show t ++ " with " ++ show n) $
829-- traceWhen (all boundVar ttypes) ("Progress: " ++ show t ++ " with " ++ show n) $
@@ -802,7 +836,7 @@ resolveTC depth topg fn ist
802 -- if there's any arguments left, we've failed to resolve
836 -- if there's any arguments left, we've failed to resolve
803 hs <- get_holes
837 hs <- get_holes
804 ulog <- getUnifyLog
838 ulog <- getUnifyLog
806 traceWhen ulog ("Got " ++ show n) $ return ()
840 traceWhen ulog ("Got " ++ show n) $ return ()
807 where isImp (PImp p _ _ _ _ _) = (True, p)
841 where isImp (PImp p _ _ _ _ _) = (True, p)
808 isImp arg = (False, priority arg)
842 isImp arg = (False, priority arg)
@@ -1487,6 +1521,7 @@ reflectErr (LoadingFailed str err) =
1487 raw_apply (Var $ reflErrName "LoadingFailed") [RConstant (Str str)]
1521 raw_apply (Var $ reflErrName "LoadingFailed") [RConstant (Str str)]
1488reflectErr x = raw_apply (Var (sNS (sUN "Msg") ["Errors", "Reflection", "Language"])) [RConstant . Str $ "Default reflection: " ++ show x]
1522reflectErr x = raw_apply (Var (sNS (sUN "Msg") ["Errors", "Reflection", "Language"])) [RConstant . Str $ "Default reflection: " ++ show x]
1490withErrorReflection :: Idris a -> Idris a
1525withErrorReflection :: Idris a -> Idris a
1491withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
1526withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
1492 where handle :: Err -> Idris Err
1527 where handle :: Err -> Idris Err
@@ -1512,47 +1547,50 @@ withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
1513 -- For each handler term output, either discard it if it is Nothing or reify it the Haskell equivalent
1548 -- For each handler term output, either discard it if it is Nothing or reify it the Haskell equivalent
1514 let errorpartsTT = mapMaybe unList (mapMaybe fromTTMaybe results)
1549 let errorpartsTT = mapMaybe unList (mapMaybe fromTTMaybe results)
1515− errorparts <- mapM (mapM reifyReportPart) errorpartsTT
1550+ errorparts <- case mapM (mapM reifyReportPart) errorpartsTT of
1516−
1551+ Left err -> ierror err
1552+ Right ok -> return ok
1517 return $ case errorparts of
1553 return $ case errorparts of
1519 parts -> ReflectionError errorparts e
1555 parts -> ReflectionError errorparts e
1521− fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
1557+fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
1522− fromTTMaybe (App (App (P (DCon _ _) (NS (UN just) _) _) ty) tm)
1558+fromTTMaybe (App (App (P (DCon _ _) (NS (UN just) _) _) ty) tm)
1523− | just == txt "Just" = Just tm
1559+ | just == txt "Just" = Just tm
1524− fromTTMaybe x = Nothing
1560+fromTTMaybe x = Nothing
1526reflErrName :: String -> Name
1562reflErrName :: String -> Name
1527reflErrName n = sNS (sUN n) ["Errors", "Reflection", "Language"]
1563reflErrName n = sNS (sUN n) ["Errors", "Reflection", "Language"]
1565+-- | Attempt to reify a report part from TT to the internal
1566+-- representation. Not in Idris or ElabD monads because it should be usable
1529−reifyReportPart :: Term -> Idris ErrorReportPart
1568+reifyReportPart :: Term -> Either Err ErrorReportPart
1530reifyReportPart (App (P (DCon _ _) n _) (Constant (Str msg))) | n == reflErrName "TextPart" =
1569reifyReportPart (App (P (DCon _ _) n _) (Constant (Str msg))) | n == reflErrName "TextPart" =
1531− return (TextPart msg)
1570+ Right (TextPart msg)
1532reifyReportPart (App (P (DCon _ _) n _) ttn)
1571reifyReportPart (App (P (DCon _ _) n _) ttn)
1533 | n == reflErrName "NamePart" =
1572 | n == reflErrName "NamePart" =
1534 case runElab [] (reifyTTName ttn) (initElaborator NErased initContext Erased) of
1573 case runElab [] (reifyTTName ttn) (initElaborator NErased initContext Erased) of
1535− Error e -> ierror . InternalMsg $
1574+ Error e -> Left . InternalMsg $
1536 "could not reify name term " ++
1575 "could not reify name term " ++
1537 show ttn ++
1576 show ttn ++
1538 " when reflecting an error"
1577 " when reflecting an error"
1539− OK (n', _)-> return $ NamePart n'
1578+ OK (n', _)-> Right $ NamePart n'
1540reifyReportPart (App (P (DCon _ _) n _) tm)
1579reifyReportPart (App (P (DCon _ _) n _) tm)
1541 | n == reflErrName "TermPart" =
1580 | n == reflErrName "TermPart" =
1542− do ist <- getIState
1543− case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
1581+ case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
1544− Error e -> ierror . InternalMsg $
1582+ Error e -> Left . InternalMsg $
1545− "could not reify reflected term " ++
1583+ "could not reify reflected term " ++
1546− show tm ++
1584+ show tm ++
1547− " when reflecting an error"
1585+ " when reflecting an error"
1548− OK (tm', _) -> return $ TermPart tm'
1586+ OK (tm', _) -> Right $ TermPart tm'
1549reifyReportPart (App (P (DCon _ _) n _) tm)
1587reifyReportPart (App (P (DCon _ _) n _) tm)
1550 | n == reflErrName "SubReport" =
1588 | n == reflErrName "SubReport" =
1551− case unList tm of
1589+ case unList tm of
1552− Just xs -> do subParts <- mapM reifyReportPart xs
1590+ Just xs -> do subParts <- mapM reifyReportPart xs
1553− return (SubReport subParts)
1591+ Right (SubReport subParts)
1554− Nothing -> ierror . InternalMsg $ "could not reify subreport " ++ show tm
1592+ Nothing -> Left . InternalMsg $ "could not reify subreport " ++ show tm
1555−reifyReportPart x = ierror . InternalMsg $ "could not reify " ++ show x
1593+reifyReportPart x = Left . InternalMsg $ "could not reify " ++ show x
1557envTupleType :: Raw
1595envTupleType :: Raw
1558envTupleType
1596envTupleType