@@ -13,10 +13,14 @@ import Idris.Core.TT
1313import Idris.Core.Evaluate
1414import Idris.Core.Typecheck (check)
1515
16+import Control.Applicative ((<$>))
1617import Control.Monad
1718import Control.Monad.State.Strict
1819import Data.List
20+import qualified Data.Map as M
1921import Data.Maybe (mapMaybe)
22+import qualified Data.Set as S
23+import qualified Data.Text as T
2024
2125import Debug.Trace
2226
@@ -396,7 +400,7 @@ elab ist info pattern opts fn tm
396400 solve
397401 elab' (_, _, inty) (PApp fc (PRef _ f) args')
398402 | 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")
400404 -- if f is local, just do a simple_app
401405 elab' (ina, g, inty) tm@(PApp fc (PRef _ f) args)
402406 = do env <- get_env
@@ -419,12 +423,14 @@ elab ist info pattern opts fn tm
419423 _ -> mapM_ setInjective (map getTm args)
420424 ctxt <- get_context
421425 let guarded = isConName f ctxt
426+-- trace ("args is " ++ show args) $ return ()
422427 ns <- apply (Var f) (map isph args)
428+-- trace ("ns is " ++ show ns) $ return ()
423429 -- Sort so that the implicit tactics and alternatives go last
424430 let (ns', eargs) = unzip $
425431 sortBy cmpArg (zip ns args)
426− elabArgs (ina || not isinf, guarded, inty)
427− [] fc False ns' (map (\x -> (lazyarg x, getTm x)) eargs)
432+ elabArgs ist (ina || not isinf, guarded, inty)
433+ [] fc False f ns' (map (\x -> (lazyarg x, getTm x)) eargs)
428434 solve
429435 ivs' <- get_instances
430436 -- Attempt to resolve any type classes which have 'complete' types,
@@ -613,45 +619,73 @@ elab ist info pattern opts fn tm
613619 addImpl ist (PApp fc (PRef fc n) [pexp (PCoerced t)])
614620
615621 -- | Elaborate the arguments to a function
616− elabArgs :: (Bool, Bool, Bool) -- ^ (in an argument, guarded, in a type)
622+ elabArgs :: IState -- ^ The current Idris state
623+ -> (Bool, Bool, Bool) -- ^ (in an argument, guarded, in a type)
617624 -> [Bool]
618625 -> FC -- ^ Source location
619626 -> Bool
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)
621629 -> [(Bool, PTerm)] -- ^ (Laziness, argument)
622630 -> ElabD ()
623− elabArgs ina failed fc retry [] _
631+ elabArgs ist ina failed fc retry f [] _
624632-- | retry = let (ns, ts) = unzip (reverse failed) in
625633-- elabArgs ina [] False ns ts
626634 | otherwise = return ()
627− elabArgs ina failed fc r (n:ns) ((_, Placeholder) : args)
628− = elabArgs ina failed fc r ns args
629− elabArgs ina failed fc r (n:ns) ((lazy, t) : args)
635+ elabArgs ist ina failed fc r f (n:ns) ((_, Placeholder) : args)
636+ = elabArgs ist ina failed fc r f ns args
637+ elabArgs ist ina failed fc r f ((argName, holeName):ns) ((lazy, t) : args)
630638 | lazy && not pattern
631− = do elabArg n (PApp bi (PRef bi (sUN "lazy"))
632− [pimp (sUN "a") Placeholder True,
633− pexp t]);
634− | otherwise = elabArg n t
635− where elabArg n t
636− = do hs <- get_holes
637− tm <- get_term
638− failed' <- -- trace (show (n, t, hs, tm)) $
639− -- traceWhen (not (null cs)) (show ty ++ "\n" ++ showImp True t) $
640− case n `elem` hs of
641− True -> do focus n; elabE ina t; return failed
642− False -> return failed
643− elabArgs ina failed fc r ns args
644−
645−-- | Perform error reflection for functions with specific error handlers
646−reflectFunctionErrors :: IState -> Name -> ElabD a -> ElabD a
647−reflectFunctionErrors ist f action =
639+ = elabArg argName holeName (PApp bi (PRef bi (sUN "lazy"))
640+ [pimp (sUN "a") Placeholder True,
641+ pexp t])
642+ | otherwise = elabArg argName holeName t
643+ where elabArg argName holeName t =
644+ reflectFunctionErrors ist f argName $
645+ do hs <- get_holes
646+ tm <- get_term
647+ failed' <- -- trace (show (n, t, hs, tm)) $
648+ -- traceWhen (not (null cs)) (show ty ++ "\n" ++ showImp True t) $
649+ case holeName `elem` hs of
650+ True -> do focus holeName; elabE ina t; return failed
651+ False -> return failed
652+ elabArgs ist ina failed fc r f ns args
653+
654+-- | Perform error reflection for function applicaitons with specific error handlers
655+reflectFunctionErrors :: IState -> Name -> Name -> ElabD a -> ElabD a
656+reflectFunctionErrors ist f arg action =
648657 do elabState <- get
649658 (result, newState) <- case runStateT action elabState of
650659 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
652663 put newState
653664 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
669+
670+
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
675+ OK hs -> return hs
654676
677+ -- Normalize error handler terms to produce the new messages
678+ let ctxt = tt_ctxt ist
679+ results = map (normalise ctxt []) (map fst handlers)
680+
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
687+ [] -> e
688+ parts -> ReflectionError errorparts e
655689
656690-- For every alternative, look at the function at the head. Automatically resolve
657691-- any nested alternatives where that function is also at the head
@@ -788,8 +822,8 @@ resolveTC depth topg fn ist
788822 [args] -> map isImp (snd args) -- won't be overloaded!
789823 ps <- get_probs
790824 tm <- get_term
791− args <- try' (apply (Var n) imps)
792− (match_apply (Var n) imps) True
825+ args <- map snd <$> try' (apply (Var n) imps)
826+ (match_apply (Var n) imps) True
793827 ps' <- get_probs
794828 when (length ps < length ps') $ fail "Can't apply type class"
795829-- traceWhen (all boundVar ttypes) ("Progress: " ++ show t ++ " with " ++ show n) $
@@ -802,7 +836,7 @@ resolveTC depth topg fn ist
802836 -- if there's any arguments left, we've failed to resolve
803837 hs <- get_holes
804838 ulog <- getUnifyLog
805− solve
839+ solve
806840 traceWhen ulog ("Got " ++ show n) $ return ()
807841 where isImp (PImp p _ _ _ _ _) = (True, p)
808842 isImp arg = (False, priority arg)
@@ -1487,6 +1521,7 @@ reflectErr (LoadingFailed str err) =
14871521 raw_apply (Var $ reflErrName "LoadingFailed") [RConstant (Str str)]
14881522reflectErr x = raw_apply (Var (sNS (sUN "Msg") ["Errors", "Reflection", "Language"])) [RConstant . Str $ "Default reflection: " ++ show x]
14891523
1524+
14901525withErrorReflection :: Idris a -> Idris a
14911526withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
14921527 where handle :: Err -> Idris Err
@@ -1512,47 +1547,50 @@ withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
15121547
15131548 -- For each handler term output, either discard it if it is Nothing or reify it the Haskell equivalent
15141549 let errorpartsTT = mapMaybe unList (mapMaybe fromTTMaybe results)
1515− errorparts <- mapM (mapM reifyReportPart) errorpartsTT
1516−
1550+ errorparts <- case mapM (mapM reifyReportPart) errorpartsTT of
1551+ Left err -> ierror err
1552+ Right ok -> return ok
15171553 return $ case errorparts of
15181554 [] -> e
15191555 parts -> ReflectionError errorparts e
15201556
1521− fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
1522− fromTTMaybe (App (App (P (DCon _ _) (NS (UN just) _) _) ty) tm)
1523− | just == txt "Just" = Just tm
1524− fromTTMaybe x = Nothing
1557+fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
1558+fromTTMaybe (App (App (P (DCon _ _) (NS (UN just) _) _) ty) tm)
1559+ | just == txt "Just" = Just tm
1560+fromTTMaybe x = Nothing
15251561
15261562reflErrName :: String -> Name
15271563reflErrName n = sNS (sUN n) ["Errors", "Reflection", "Language"]
15281564
1529−reifyReportPart :: Term -> Idris ErrorReportPart
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
1567+-- from either.
1568+reifyReportPart :: Term -> Either Err ErrorReportPart
15301569reifyReportPart (App (P (DCon _ _) n _) (Constant (Str msg))) | n == reflErrName "TextPart" =
1531− return (TextPart msg)
1570+ Right (TextPart msg)
15321571reifyReportPart (App (P (DCon _ _) n _) ttn)
15331572 | n == reflErrName "NamePart" =
15341573 case runElab [] (reifyTTName ttn) (initElaborator NErased initContext Erased) of
1535− Error e -> ierror . InternalMsg $
1574+ Error e -> Left . InternalMsg $
15361575 "could not reify name term " ++
15371576 show ttn ++
15381577 " when reflecting an error"
1539− OK (n', _)-> return $ NamePart n'
1578+ OK (n', _)-> Right $ NamePart n'
15401579reifyReportPart (App (P (DCon _ _) n _) tm)
15411580 | n == reflErrName "TermPart" =
1542− do ist <- getIState
1543− case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
1544− Error e -> ierror . InternalMsg $
1545− "could not reify reflected term " ++
1546− show tm ++
1547− " when reflecting an error"
1548− OK (tm', _) -> return $ TermPart tm'
1581+ case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
1582+ Error e -> Left . InternalMsg $
1583+ "could not reify reflected term " ++
1584+ show tm ++
1585+ " when reflecting an error"
1586+ OK (tm', _) -> Right $ TermPart tm'
15491587reifyReportPart (App (P (DCon _ _) n _) tm)
15501588 | n == reflErrName "SubReport" =
1551− case unList tm of
1552− Just xs -> do subParts <- mapM reifyReportPart xs
1553− return (SubReport subParts)
1554− Nothing -> ierror . InternalMsg $ "could not reify subreport " ++ show tm
1555−reifyReportPart x = ierror . InternalMsg $ "could not reify " ++ show x
1589+ case unList tm of
1590+ Just xs -> do subParts <- mapM reifyReportPart xs
1591+ Right (SubReport subParts)
1592+ Nothing -> Left . InternalMsg $ "could not reify subreport " ++ show tm
1593+reifyReportPart x = Left . InternalMsg $ "could not reify " ++ show x
15561594
15571595envTupleType :: Raw
15581596envTupleType