@@ -5,15 +5,18 @@ module Idris.ElabTerm where
55import Idris.AbsSyntax
66import Idris.DSL
77import Idris.Delaborate
8+import Idris.Error
89import Idris.ProofSearch
910
1011import Idris.Core.Elaborate hiding (Tactic(..))
1112import Idris.Core.TT
1213import Idris.Core.Evaluate
14+import Idris.Core.Typecheck (check)
1315
1416import Control.Monad
1517import Control.Monad.State
1618import Data.List
19+import Data.Maybe (mapMaybe)
1720
1821import Debug.Trace
1922
@@ -1031,7 +1034,7 @@ runTac autoSolve ist tac
10311034 runReflected t = do t' <- reify ist t
10321035 runTac autoSolve ist t'
10331036
1034−-- | Prefix a name with the "Reflection.Language" namespace
1037+-- | Prefix a name with the "Language.Reflection" namespace
10351038reflm :: String -> Name
10361039reflm n = NS (UN n) ["Reflection", "Language"]
10371040
@@ -1370,10 +1373,172 @@ reflectEnv = foldr consToEnvList emptyEnvList
13701373 [envTupleType]
13711374
13721375-- | Reflect an error into the internal datatype of Idris -- TODO
1376+rawBool :: Bool -> Raw
1377+rawBool True = Var (NS (UN "True") ["Bool", "Prelude"])
1378+rawBool False = Var (NS (UN "False") ["Bool", "Prelude"])
1379+
1380+rawNil :: Raw -> Raw
1381+rawNil ty = raw_apply (Var (NS (UN "Nil") ["List", "Prelude"])) [ty]
1382+
1383+rawCons :: Raw -> Raw -> Raw -> Raw
1384+rawCons ty hd tl = raw_apply (Var (NS (UN "::") ["List", "Prelude"])) [ty, hd, tl]
1385+
1386+rawList :: Raw -> [Raw] -> Raw
1387+rawList ty = foldr (rawCons ty) (rawNil ty)
1388+
1389+rawPairTy :: Raw -> Raw -> Raw
1390+rawPairTy t1 t2 = raw_apply (Var pairTy) [t1, t2]
1391+
1392+rawPair :: (Raw, Raw) -> (Raw, Raw) -> Raw
1393+rawPair (a, b) (x, y) = raw_apply (Var pairCon) [a, b, x, y]
1394+
1395+reflectCtxt :: [(Name, Type)] -> Raw
1396+reflectCtxt ctxt = rawList (rawPairTy (Var $ reflm "TTName") (Var $ reflm "TT"))
1397+ (map (\ (n, t) -> (rawPair (Var $ reflm "TTName", Var $ reflm "TT")
1398+ (reflectName n, reflect t)))
1399+ ctxt)
1400+
13731401reflectErr :: Err -> Raw
1374−reflectErr (Msg msg) = raw_apply (Var (NS (UN "Msg") ["Reflection", "Language"])) [reflectConstant (Str msg)]
1375−reflectErr (InternalMsg msg) = raw_apply (Var (NS (UN "InternalMsg") ["Reflection", "Language"])) [reflectConstant (Str msg)]
1376−reflectErr x = trace ("Couldn't reflect error " ++ show x) raw_apply (Var (NS (UN "Msg") ["Reflection", "Language"])) [reflectConstant (Str $ show x)]
1402+reflectErr (Msg msg) = raw_apply (Var $ reflErrName "Msg") [RConstant (Str msg)]
1403+reflectErr (InternalMsg msg) = raw_apply (Var $ reflErrName "InternalMsg") [RConstant (Str msg)]
1404+reflectErr (CantUnify b t1 t2 e ctxt i) =
1405+ raw_apply (Var $ reflErrName "CantUnify")
1406+ [ rawBool b
1407+ , reflect t1
1408+ , reflect t2
1409+ , reflectErr e
1410+ , reflectCtxt ctxt
1411+ , RConstant (I i)]
1412+reflectErr (InfiniteUnify n tm ctxt) =
1413+ raw_apply (Var $ reflErrName "InfiniteUnify")
1414+ [ reflectName n
1415+ , reflect tm
1416+ , reflectCtxt ctxt
1417+ ]
1418+reflectErr (CantConvert t t' ctxt) =
1419+ raw_apply (Var $ reflErrName "CantConvert")
1420+ [ reflect t
1421+ , reflect t'
1422+ , reflectCtxt ctxt
1423+ ]
1424+reflectErr (UnifyScope n n' t ctxt) =
1425+ raw_apply (Var $ reflErrName "UnifyScope")
1426+ [ reflectName n
1427+ , reflectName n'
1428+ , reflect t
1429+ , reflectCtxt ctxt
1430+ ]
1431+reflectErr (CantInferType str) =
1432+ raw_apply (Var $ reflErrName "CantInferType") [RConstant (Str str)]
1433+reflectErr (NonFunctionType t t') =
1434+ raw_apply (Var $ reflErrName "NonFunctionType") [reflect t, reflect t']
1435+reflectErr (NotEquality t t') =
1436+ raw_apply (Var $ reflErrName "NotEquality") [reflect t, reflect t']
1437+reflectErr (TooManyArguments n) = raw_apply (Var $ reflErrName "TooManyArguments") [reflectName n]
1438+reflectErr (CantIntroduce t) = raw_apply (Var $ reflErrName "CantIntroduce") [reflect t]
1439+reflectErr (NoSuchVariable n) = raw_apply (Var $ reflErrName "NoSuchVariable") [reflectName n]
1440+reflectErr (NoTypeDecl n) = raw_apply (Var $ reflErrName "NoTypeDecl") [reflectName n]
1441+reflectErr (NotInjective t1 t2 t3) =
1442+ raw_apply (Var $ reflErrName "NotInjective")
1443+ [ reflect t1
1444+ , reflect t2
1445+ , reflect t3
1446+ ]
1447+reflectErr (CantResolve t) = raw_apply (Var $ reflErrName "CantResolve") [reflect t]
1448+reflectErr (CantResolveAlts ss) =
1449+ raw_apply (Var $ reflErrName "CantResolve")
1450+ [rawList (Var $ (UN "String")) (map (RConstant . Str) ss)]
1451+reflectErr (IncompleteTerm t) = raw_apply (Var $ reflErrName "IncompleteTerm") [reflect t]
1452+reflectErr UniverseError = Var $ reflErrName "UniverseError"
1453+reflectErr ProgramLineComment = Var $ reflErrName "ProgramLineComment"
1454+reflectErr (Inaccessible n) = raw_apply (Var $ reflErrName "Inaccessible") [reflectName n]
1455+reflectErr (NonCollapsiblePostulate n) = raw_apply (Var $ reflErrName "NonCollabsiblePostulate") [reflectName n]
1456+reflectErr (AlreadyDefined n) = raw_apply (Var $ reflErrName "AlreadyDefined") [reflectName n]
1457+reflectErr (ProofSearchFail e) = raw_apply (Var $ reflErrName "ProofSearchFail") [reflectErr e]
1458+reflectErr (NoRewriting tm) = raw_apply (Var $ reflErrName "NoRewriting") [reflect tm]
1459+reflectErr (At fc err) = raw_apply (Var $ reflErrName "At") [reflectFC fc, reflectErr err]
1460+ where reflectFC (FC source line col) = raw_apply (Var $ reflErrName "FileLoc")
1461+ [ RConstant (Str source)
1462+ , RConstant (I line)
1463+ , RConstant (I col)
1464+ ]
1465+reflectErr (Elaborating str n e) =
1466+ raw_apply (Var $ reflErrName "Elaborating")
1467+ [ RConstant (Str str)
1468+ , reflectName n
1469+ , reflectErr e
1470+ ]
1471+reflectErr (ProviderError str) =
1472+ raw_apply (Var $ reflErrName "ProviderError") [RConstant (Str str)]
1473+reflectErr (LoadingFailed str err) =
1474+ raw_apply (Var $ reflErrName "LoadingFailed") [RConstant (Str str)]
1475+reflectErr x = raw_apply (Var (NS (UN "Msg") ["Errors", "Reflection", "Language"])) [RConstant . Str $ "Default reflection: " ++ show x]
1476+
1477+withErrorReflection :: Idris a -> Idris a
1478+withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
1479+ where handle :: Err -> Idris Err
1480+ handle e@(ReflectionError _ _) = do logLvl 3 "Skipping reflection of error reflection result"
1481+ return e -- Don't do meta-reflection of errors
1482+ handle e@(ReflectionFailed _ _) = do logLvl 3 "Skipping reflection of reflection failure"
1483+ return e
1484+ handle e = do ist <- getIState
1485+ logLvl 2 "Starting error reflection"
1486+ let handlers = idris_errorhandlers ist
1487+ logLvl 3 $ "Using reflection handlers " ++ concat (intersperse ", " (map show handlers))
1488+ let reports = map (\n -> RApp (Var n) (reflectErr e)) handlers
1489+
1490+ -- Typecheck error handlers - if this fails, then something else was wrong earlier!
1491+ handlers <- case mapM (check (tt_ctxt ist) []) reports of
1492+ Error e -> ierror $ ReflectionFailed "Type error while constructing reflected error" e
1493+ OK hs -> return hs
1494+
1495+ -- Normalize error handler terms to produce the new messages
1496+ ctxt <- getContext
1497+ let results = map (normalise ctxt []) (map fst handlers)
1498+ logLvl 3 $ "New error message info: " ++ concat (intersperse " and " (map show results))
1499+
1500+ -- For each handler term output, either discard it if it is Nothing or reify it the Haskell equivalent
1501+ let errorpartsTT = mapMaybe unList (mapMaybe fromTTMaybe results)
1502+ errorparts <- mapM (mapM reifyReportPart) errorpartsTT
1503+
1504+ return $ case errorparts of
1505+ [] -> e
1506+ parts -> ReflectionError errorparts e
1507+
1508+ fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
1509+ fromTTMaybe (App (App (P (DCon _ _) (NS (UN "Just") _) _) ty) tm) = Just tm
1510+ fromTTMaybe x = Nothing
1511+
1512+reflErrName :: String -> Name
1513+reflErrName n = NS (UN n) ["Errors", "Reflection", "Language"]
1514+
1515+reifyReportPart :: Term -> Idris ErrorReportPart
1516+reifyReportPart (App (P (DCon _ _) n _) (Constant (Str msg))) | n == reflErrName "TextPart" =
1517+ return (TextPart msg)
1518+reifyReportPart (App (P (DCon _ _) n _) ttn)
1519+ | n == reflErrName "NamePart" =
1520+ case runElab [] (reifyTTName ttn) (initElaborator NErased initContext Erased) of
1521+ Error e -> ierror . InternalMsg $
1522+ "could not reify name term " ++
1523+ show ttn ++
1524+ " when reflecting an error"
1525+ OK (n', _)-> return $ NamePart n'
1526+reifyReportPart (App (P (DCon _ _) n _) tm)
1527+ | n == reflErrName "TermPart" =
1528+ do ist <- getIState
1529+ case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
1530+ Error e -> ierror . InternalMsg $
1531+ "could not reify reflected term " ++
1532+ show tm ++
1533+ " when reflecting an error"
1534+ OK (tm', _) -> return $ TermPart tm'
1535+reifyReportPart (App (P (DCon _ _) n _) tm)
1536+ | n == reflErrName "SubReport" =
1537+ case unList tm of
1538+ Just xs -> do subParts <- mapM reifyReportPart xs
1539+ return (SubReport subParts)
1540+ Nothing -> ierror . InternalMsg $ "could not reify subreport " ++ show tm
1541+reifyReportPart x = ierror . InternalMsg $ "could not reify " ++ show x
13771542
13781543envTupleType :: Raw
13791544envTupleType