@@ -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
@@ -153,13 +157,18 @@ elab ist info pattern opts fn tm
153157
154158 local f = do e <- get_env
155159 return (f `elem` map fst e)
156−
160+
161+ -- | Is a constant a type?
162+ constType :: Const -> Bool
157163 constType (AType _) = True
158164 constType StrType = True
159165 constType PtrType = True
160166 constType VoidType = True
161167 constType _ = False
162168
169+ elab' :: (Bool, Bool, Bool) -- ^ (in an argument, guarded, in a type)
170+ -> PTerm -- ^ The term to elaborate
171+ -> ElabD ()
163172 elab' ina (PNoImplicits t) = elab' ina t -- skip elabE step
164173 elab' ina PType = do apply RType []; solve
165174 elab' (_,_,inty) (PConstant c)
@@ -387,7 +396,7 @@ elab ist info pattern opts fn tm
387396 solve
388397 elab' (_, _, inty) (PApp fc (PRef _ f) args')
389398 | 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")
391400 -- if f is local, just do a simple_app
392401 elab' (ina, g, inty) tm@(PApp fc (PRef _ f) args)
393402 = do env <- get_env
@@ -410,16 +419,18 @@ elab ist info pattern opts fn tm
410419 _ -> mapM_ setInjective (map getTm args)
411420 ctxt <- get_context
412421 let guarded = isConName f ctxt
422+-- trace ("args is " ++ show args) $ return ()
413423 ns <- apply (Var f) (map isph args)
424+-- trace ("ns is " ++ show ns) $ return ()
414425 -- Sort so that the implicit tactics and alternatives go last
415426 let (ns', eargs) = unzip $
416427 sortBy cmpArg (zip ns args)
417− elabArgs (ina || not isinf, guarded, inty)
418− [] fc False ns' (map (\x -> (lazyarg x, getTm x)) eargs)
428+ elabArgs ist (ina || not isinf, guarded, inty)
429+ [] fc False f ns' (map (\x -> (lazyarg x, getTm x)) eargs)
419430 solve
420431 ivs' <- get_instances
421− -- Attempt to resolve any type classes which have 'complete' types,
422− -- i.e. no holes in them
432+ -- Attempt to resolve any type classes which have 'complete' types,
433+ -- i.e. no holes in them
423434 when (not pattern || (ina && not tcgen && not guarded)) $
424435 mapM_ (\n -> do focus n
425436 g <- goal
@@ -603,31 +614,74 @@ elab ist info pattern opts fn tm
603614 mkCoerce t n = let fc = fileFC "Coercion" in -- line never appears!
604615 addImpl ist (PApp fc (PRef fc n) [pexp (PCoerced t)])
605616
606− elabArgs ina failed fc retry [] _
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)
620+ -> [Bool]
621+ -> FC -- ^ Source location
622+ -> Bool
623+ -> Name -- ^ Name of the function being applied
624+ -> [(Name, Name)] -- ^ (Argument Name, Hole Name)
625+ -> [(Bool, PTerm)] -- ^ (Laziness, argument)
626+ -> ElabD ()
627+ elabArgs ist ina failed fc retry f [] _
607628-- | retry = let (ns, ts) = unzip (reverse failed) in
608629-- elabArgs ina [] False ns ts
609630 | otherwise = return ()
610− elabArgs ina failed fc r (n:ns) ((_, Placeholder) : args)
611− = elabArgs ina failed fc r ns args
612− elabArgs ina failed fc r (n:ns) ((lazy, t) : args)
631+ elabArgs ist ina failed fc r f (n:ns) ((_, Placeholder) : args)
632+ = elabArgs ist ina failed fc r f ns args
633+ elabArgs ist ina failed fc r f ((argName, holeName):ns) ((lazy, t) : args)
613634 | lazy && not pattern
614− = do elabArg n (PApp bi (PRef bi (sUN "lazy"))
615− [pimp (sUN "a") Placeholder True,
616− pexp t]);
617− | otherwise = elabArg n t
618− where elabArg n t
619− = do hs <- get_holes
620− tm <- get_term
621− failed' <- -- trace (show (n, t, hs, tm)) $
622− -- traceWhen (not (null cs)) (show ty ++ "\n" ++ showImp True t) $
623− case n `elem` hs of
624− True ->
625−-- if r
626−-- then try (do focus n; elabE ina t; return failed)
627−-- (return ((n,(lazy, t)):failed))
628− do focus n; elabE ina t; return failed
629− False -> return failed
630− elabArgs ina failed fc r ns args
635+ = elabArg argName holeName (PApp bi (PRef bi (sUN "lazy"))
636+ [pimp (sUN "a") Placeholder True,
637+ pexp t])
638+ | otherwise = elabArg argName holeName t
639+ where elabArg argName holeName t =
640+ reflectFunctionErrors ist f argName $
641+ do hs <- get_holes
642+ tm <- get_term
643+ failed' <- -- trace (show (n, t, hs, tm)) $
644+ -- traceWhen (not (null cs)) (show ty ++ "\n" ++ showImp True t) $
645+ case holeName `elem` hs of
646+ True -> do focus holeName; elabE ina t; return failed
647+ False -> return failed
648+ elabArgs ist ina failed fc r f ns args
649+
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 =
653+ do elabState <- get
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
659+ put newState
660+ return result
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
665+
666+
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
671+ OK hs -> return hs
672+
673+ -- Normalize error handler terms to produce the new messages
674+ let ctxt = tt_ctxt ist
675+ results = map (normalise ctxt []) (map fst handlers)
676+
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
683+ [] -> e
684+ parts -> ReflectionError errorparts e
631685
632686-- For every alternative, look at the function at the head. Automatically resolve
633687-- any nested alternatives where that function is also at the head
@@ -764,8 +818,8 @@ resolveTC depth topg fn ist
764818 [args] -> map isImp (snd args) -- won't be overloaded!
765819 ps <- get_probs
766820 tm <- get_term
767− args <- try' (apply (Var n) imps)
768− (match_apply (Var n) imps) True
821+ args <- map snd <$> try' (apply (Var n) imps)
822+ (match_apply (Var n) imps) True
769823 ps' <- get_probs
770824 when (length ps < length ps') $ fail "Can't apply type class"
771825-- traceWhen (all boundVar ttypes) ("Progress: " ++ show t ++ " with " ++ show n) $
@@ -778,7 +832,7 @@ resolveTC depth topg fn ist
778832 -- if there's any arguments left, we've failed to resolve
779833 hs <- get_holes
780834 ulog <- getUnifyLog
781− solve
835+ solve
782836 traceWhen ulog ("Got " ++ show n) $ return ()
783837 where isImp (PImp p _ _ _ _ _) = (True, p)
784838 isImp arg = (False, priority arg)
@@ -1134,7 +1188,7 @@ reifyRawApp t [c]
11341188reifyRawApp t args = fail ("Unknown reflection raw term: " ++ show (t, args))
11351189
11361190reifyTTName :: Term -> ElabD Name
1137−reifyTTName t@(App _ _)
1191+reifyTTName t
11381192 | (P _ f _, args) <- unApply t = reifyTTNameApp f args
11391193reifyTTName t = fail ("Unknown reflection term name: " ++ show t)
11401194
@@ -1470,6 +1524,7 @@ reflectErr (LoadingFailed str err) =
14701524 raw_apply (Var $ reflErrName "LoadingFailed") [RConstant (Str str)]
14711525reflectErr x = raw_apply (Var (sNS (sUN "Msg") ["Errors", "Reflection", "Language"])) [RConstant . Str $ "Default reflection: " ++ show x]
14721526
1527+
14731528withErrorReflection :: Idris a -> Idris a
14741529withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
14751530 where handle :: Err -> Idris Err
@@ -1495,47 +1550,50 @@ withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
14951550
14961551 -- For each handler term output, either discard it if it is Nothing or reify it the Haskell equivalent
14971552 let errorpartsTT = mapMaybe unList (mapMaybe fromTTMaybe results)
1498− errorparts <- mapM (mapM reifyReportPart) errorpartsTT
1499−
1553+ errorparts <- case mapM (mapM reifyReportPart) errorpartsTT of
1554+ Left err -> ierror err
1555+ Right ok -> return ok
15001556 return $ case errorparts of
15011557 [] -> e
15021558 parts -> ReflectionError errorparts e
15031559
1504− fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
1505− fromTTMaybe (App (App (P (DCon _ _) (NS (UN just) _) _) ty) tm)
1506− | just == txt "Just" = Just tm
1507− fromTTMaybe x = Nothing
1560+fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
1561+fromTTMaybe (App (App (P (DCon _ _) (NS (UN just) _) _) ty) tm)
1562+ | just == txt "Just" = Just tm
1563+fromTTMaybe x = Nothing
15081564
15091565reflErrName :: String -> Name
15101566reflErrName n = sNS (sUN n) ["Errors", "Reflection", "Language"]
15111567
1512−reifyReportPart :: Term -> Idris ErrorReportPart
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
1570+-- from either.
1571+reifyReportPart :: Term -> Either Err ErrorReportPart
15131572reifyReportPart (App (P (DCon _ _) n _) (Constant (Str msg))) | n == reflErrName "TextPart" =
1514− return (TextPart msg)
1573+ Right (TextPart msg)
15151574reifyReportPart (App (P (DCon _ _) n _) ttn)
15161575 | n == reflErrName "NamePart" =
15171576 case runElab [] (reifyTTName ttn) (initElaborator NErased initContext Erased) of
1518− Error e -> ierror . InternalMsg $
1577+ Error e -> Left . InternalMsg $
15191578 "could not reify name term " ++
15201579 show ttn ++
1521− " when reflecting an error"
1522− OK (n', _)-> return $ NamePart n'
1580+ " when reflecting an error:" ++ show e
1581+ OK (n', _)-> Right $ NamePart n'
15231582reifyReportPart (App (P (DCon _ _) n _) tm)
15241583 | n == reflErrName "TermPart" =
1525− do ist <- getIState
1526− case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
1527− Error e -> ierror . InternalMsg $
1528− "could not reify reflected term " ++
1529− show tm ++
1530− " when reflecting an error"
1531− OK (tm', _) -> return $ TermPart tm'
1584+ case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
1585+ Error e -> Left . InternalMsg $
1586+ "could not reify reflected term " ++
1587+ show tm ++
1588+ " when reflecting an error:" ++ show e
1589+ OK (tm', _) -> Right $ TermPart tm'
15321590reifyReportPart (App (P (DCon _ _) n _) tm)
15331591 | n == reflErrName "SubReport" =
1534− case unList tm of
1535− Just xs -> do subParts <- mapM reifyReportPart xs
1536− return (SubReport subParts)
1537− Nothing -> ierror . InternalMsg $ "could not reify subreport " ++ show tm
1538−reifyReportPart x = ierror . InternalMsg $ "could not reify " ++ show x
1592+ case unList tm of
1593+ Just xs -> do subParts <- mapM reifyReportPart xs
1594+ Right (SubReport subParts)
1595+ Nothing -> Left . InternalMsg $ "could not reify subreport " ++ show tm
1596+reifyReportPart x = Left . InternalMsg $ "could not reify " ++ show x
15391597
15401598envTupleType :: Raw
15411599envTupleType