module Agda.Syntax.Translation.InternalToAbstract
( Reify(..)
, NamedClause(..)
, reifyPatterns
) where
import Prelude hiding (mapM_, mapM, null)
import Control.Applicative hiding (empty)
import Control.Monad.State hiding (mapM_, mapM)
import Control.Monad.Reader hiding (mapM_, mapM)
import Data.Foldable (foldMap)
import Data.List hiding (null, sort)
import qualified Data.Map as Map
import Data.Maybe
import Data.Semigroup (Semigroup, Monoid, (<>), mempty, mappend)
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Traversable (traverse, mapM)
import qualified Data.Traversable as Trav
import Agda.Syntax.Literal
import Agda.Syntax.Position
import Agda.Syntax.Common
import Agda.Syntax.Fixity
import Agda.Syntax.Concrete (FieldAssignment'(..), exprFieldA)
import Agda.Syntax.Info as Info
import Agda.Syntax.Abstract as A
import Agda.Syntax.Abstract.Pretty
import Agda.Syntax.Internal as I
import Agda.Syntax.Internal.Pattern as I
import Agda.Syntax.Scope.Base (isNameInScope, inverseScopeLookupName)
import Agda.TypeChecking.Monad
import Agda.TypeChecking.Monad.Builtin
import Agda.TypeChecking.Reduce
import Agda.TypeChecking.Records
import Agda.TypeChecking.CompiledClause (CompiledClauses(Fail))
import Agda.TypeChecking.DisplayForm
import Agda.TypeChecking.Level
import Agda.TypeChecking.Datatypes
import Agda.TypeChecking.Free
import Agda.TypeChecking.Substitute
import Agda.TypeChecking.Telescope
import Agda.TypeChecking.DropArgs
import Agda.Interaction.Options ( optPostfixProjections )
import Agda.Utils.Except ( MonadError(catchError) )
import Agda.Utils.Function
import Agda.Utils.Functor
import Agda.Utils.Lens
import Agda.Utils.List
import Agda.Utils.Maybe
import Agda.Utils.Monad
import Agda.Utils.Null
import Agda.Utils.Permutation
import Agda.Utils.Pretty hiding ((<>))
import Agda.Utils.Singleton
import Agda.Utils.Size
import Agda.Utils.Tuple
#include "undefined.h"
import Agda.Utils.Impossible
napps :: Expr -> [NamedArg Expr] -> TCM Expr
napps e = nelims e . map I.Apply
apps :: Expr -> [Arg Expr] -> TCM Expr
apps e = elims e . map I.Apply
nelims :: Expr -> [I.Elim' (Named_ Expr)] -> TCM Expr
nelims e [] = return e
nelims e (I.Apply arg : es) = do
arg <- reify arg
dontShowImp <- not <$> showImplicitArguments
let hd | notVisible arg && dontShowImp = e
| otherwise = A.App noExprInfo e arg
nelims hd es
nelims e (I.Proj o@ProjPrefix d : es) =
nelims (A.App noExprInfo (A.Proj o $ AmbQ [d]) $ defaultNamedArg e) es
nelims e (I.Proj o d : es) =
nelims (A.App noExprInfo e (defaultNamedArg $ A.Proj o $ AmbQ [d])) es
elims :: Expr -> [I.Elim' Expr] -> TCM Expr
elims e = nelims e . map (fmap unnamed)
noExprInfo :: ExprInfo
noExprInfo = ExprRange noRange
reifyWhenE :: Reify i Expr => Bool -> i -> TCM Expr
reifyWhenE True i = reify i
reifyWhenE False t = return underscore
class Reify i a | i -> a where
reify :: i -> TCM a
reifyWhen :: Bool -> i -> TCM a
reifyWhen _ = reify
instance Reify Name Name where
reify = return
instance Reify Expr Expr where
reifyWhen = reifyWhenE
reify = return
instance Reify MetaId Expr where
reifyWhen = reifyWhenE
reify x@(MetaId n) = liftTCM $ do
b <- asks envPrintMetasBare
mi <- mvInfo <$> lookupMeta x
let mi' = Info.MetaInfo
{ metaRange = getRange $ miClosRange mi
, metaScope = clScope $ miClosRange mi
, metaNumber = if b then Nothing else Just x
, metaNameSuggestion = if b then "" else miNameSuggestion mi
}
underscore = return $ A.Underscore mi'
caseMaybeM (isInteractionMeta x) underscore $ \ ii@InteractionId{} ->
return $ A.QuestionMark mi' ii
instance Reify DisplayTerm Expr where
reifyWhen = reifyWhenE
reify d = case d of
DTerm v -> reifyTerm False v
DDot v -> reify v
DCon c ci vs -> apps (A.Con (AmbQ [conName c])) =<< reify vs
DDef f es -> elims (A.Def f) =<< reify es
DWithApp u us es0 -> do
(e, es) <- reify (u, us)
elims (if null es then e else A.WithApp noExprInfo e es) =<< reify es0
reifyDisplayForm :: QName -> I.Elims -> TCM A.Expr -> TCM A.Expr
reifyDisplayForm f es fallback = do
ifNotM displayFormsEnabled fallback $ do
caseMaybeM (liftTCM $ displayForm f es) fallback reify
reifyDisplayFormP :: A.SpineLHS -> TCM A.SpineLHS
reifyDisplayFormP lhs@(A.SpineLHS i f ps wps) =
ifNotM displayFormsEnabled (return lhs) $ do
md <- liftTCM $
displayForm f $ zipWith (\ p i -> I.Apply $ p $> I.var i) ps [0..]
reportSLn "reify.display" 60 $
"display form of " ++ show f ++ " " ++ show ps ++ " " ++ show wps ++ ":\n " ++ show md
case md of
Just d | okDisplayForm d -> do
lhs' <- displayLHS (map namedArg ps) wps d
reportSDoc "reify.display" 70 $ do
doc <- prettyA lhs'
return $ vcat
[ text "rewritten lhs to"
, text " lhs' = " <+> doc
]
reifyDisplayFormP lhs'
_ -> do
reportSLn "reify.display" 70 $ "display form absent or not valid as lhs"
return lhs
where
okDisplayForm (DWithApp d ds es) =
okDisplayForm d && all okDisplayTerm ds && all okToDropE es
okDisplayForm (DTerm (I.Def f vs)) = all okElim vs
okDisplayForm (DDef f es) = all okDElim es
okDisplayForm DDot{} = False
okDisplayForm DCon{} = False
okDisplayForm DTerm{} = False
okDisplayTerm (DTerm v) = okTerm v
okDisplayTerm DDot{} = True
okDisplayTerm DCon{} = True
okDisplayTerm DDef{} = False
okDisplayTerm _ = False
okDElim (I.Apply v) = okDisplayTerm $ unArg v
okDElim I.Proj{} = True
okToDropE (I.Apply v) = okToDrop v
okToDropE I.Proj{} = False
okToDrop arg = notVisible arg && case ignoreSharing $ unArg arg of
I.Var _ [] -> True
I.DontCare{} -> True
I.Level{} -> True
_ -> False
okArg = okTerm . unArg
okElim (I.Apply a) = okArg a
okElim (I.Proj{}) = True
okTerm (I.Var _ []) = True
okTerm (I.Con c ci vs) = all okArg vs
okTerm (I.Def x []) = isNoName $ qnameToConcrete x
okTerm _ = False
flattenWith :: DisplayTerm -> (QName, [I.Elim' DisplayTerm], [I.Elim' DisplayTerm])
flattenWith (DWithApp d ds1 es2) =
let (f, es, ds0) = flattenWith d
in (f, es, ds0 ++ map (I.Apply . defaultArg) ds1 ++ map (fmap DTerm) es2)
flattenWith (DDef f es) = (f, es, [])
flattenWith (DTerm (I.Def f es)) = (f, map (fmap DTerm) es, [])
flattenWith _ = __IMPOSSIBLE__
displayLHS :: [A.Pattern] -> [A.Pattern] -> DisplayTerm -> TCM A.SpineLHS
displayLHS ps wps d = do
let (f, vs, es) = flattenWith d
ds <- mapM (namedArg <.> elimToPat) es
vs <- mapM elimToPat vs
return $ SpineLHS i f vs (ds ++ wps)
where
argToPat arg = fmap unnamed <$> traverse termToPat arg
elimToPat (I.Apply arg) = argToPat arg
elimToPat (I.Proj o d) = return $ defaultNamedArg $ A.ProjP patNoRange o $ AmbQ [d]
termToPat :: DisplayTerm -> TCM A.Pattern
termToPat (DTerm (I.Var n [])) = return $ case ps !!! n of
Nothing -> __IMPOSSIBLE__
Just p -> p
termToPat (DCon c ci vs) = tryRecPFromConP =<< do
A.ConP (ConPatInfo ci patNoRange) (AmbQ [conName c]) <$> mapM argToPat vs
termToPat (DTerm (I.Con c ci vs)) = tryRecPFromConP =<< do
A.ConP (ConPatInfo ci patNoRange) (AmbQ [conName c]) <$> mapM (argToPat . fmap DTerm) vs
termToPat (DTerm (I.Def _ [])) = return $ A.WildP patNoRange
termToPat (DDef _ []) = return $ A.WildP patNoRange
termToPat (DDot v) = A.DotP patNoRange Inserted <$> termToExpr v
termToPat v = A.DotP patNoRange Inserted <$> reify v
len = genericLength ps
argsToExpr = mapM (traverse termToExpr)
termToExpr :: Term -> TCM A.Expr
termToExpr v = do
reportSLn "reify.display" 60 $ "termToExpr " ++ show v
case unSpine v of
I.Con c ci vs ->
apps (A.Con (AmbQ [conName c])) =<< argsToExpr vs
I.Def f es -> do
let vs = fromMaybe __IMPOSSIBLE__ $ mapM isApplyElim es
apps (A.Def f) =<< argsToExpr vs
I.Var n es -> do
let vs = fromMaybe __IMPOSSIBLE__ $ mapM isApplyElim es
e <- if n < len
then return $ A.patternToExpr $ ps !! n
else reify (I.var (n len))
apps e =<< argsToExpr vs
_ -> return underscore
instance Reify Literal Expr where
reifyWhen = reifyWhenE
reify l = return (A.Lit l)
instance Reify Term Expr where
reifyWhen = reifyWhenE
reify v = reifyTerm True v
reifyTerm :: Bool -> Term -> TCM Expr
reifyTerm expandAnonDefs0 v = do
metasBare <- asks envPrintMetasBare
expandAnonDefs <- return expandAnonDefs0 `and2M` displayFormsEnabled
havePfp <- optPostfixProjections <$> pragmaOptions
let pred = if havePfp then (== ProjPrefix) else (/= ProjPostfix)
v <- ignoreSharing <$> instantiate v
case applyUnless metasBare (unSpine' pred) v of
I.Var n es -> do
x <- liftTCM $ nameOfBV n `catchError` \_ -> freshName_ ("@" ++ show n)
elims (A.Var x) =<< reify es
I.Def x es -> do
reifyDisplayForm x es $ reifyDef expandAnonDefs x es
I.Con c ci vs -> do
let x = conName c
isR <- isGeneratedRecordConstructor x
case isR || ci == ConORec of
True -> do
showImp <- showImplicitArguments
let keep (a, v) = showImp || notHidden a
r <- getConstructorData x
xs <- getRecordFieldNames r
vs <- map unArg <$> reify vs
return $ A.Rec noExprInfo $ map (Left . uncurry FieldAssignment . mapFst unArg) $ filter keep $ zip xs vs
False -> reifyDisplayForm x (map I.Apply vs) $ do
def <- getConstInfo x
let Constructor{conPars = np} = theDef def
n <- getDefFreeVars x
when (n > np) __IMPOSSIBLE__
let h = A.Con (AmbQ [x])
if null vs then return h else do
es <- reify vs
if np == 0 then apps h es else do
TelV tel _ <- telView (defType def)
let (pars, rest) = splitAt np $ telToList tel
case rest of
(Dom info _ : _) | notVisible info -> do
let us = for (drop n pars) $ \ (Dom ai _) ->
hideOrKeepInstance $ Arg ai underscore
apps h $ us ++ es
_ -> apps h es
I.Lam info b -> do
(x,e) <- reify b
return $ A.Lam noExprInfo (DomainFree info x) e
I.Lit l -> reify l
I.Level l -> reify l
I.Pi a b -> case b of
NoAbs _ b'
| notHidden a -> uncurry (A.Fun $ noExprInfo) <$> reify (a, b')
| otherwise -> mkPi b =<< reify a
b -> mkPi b =<< do
ifM (domainFree a (absBody b))
(pure $ Arg (domInfo a) underscore)
(reify a)
where
mkPi b (Arg info a) = do
(x, b) <- reify b
return $ A.Pi noExprInfo [TypedBindings noRange $ Arg info (TBind noRange [pure x] a)] b
domainFree a b = do
df <- asks envPrintDomainFreePi
return $ and [df, freeIn 0 b, closed a]
I.Sort s -> reify s
I.MetaV x es -> do
x' <- reify x
ifM (asks envPrintMetasBare) (return x') $
elims x' =<< reify es
I.DontCare v -> A.DontCare <$> reifyTerm expandAnonDefs v
I.Shared p -> reifyTerm expandAnonDefs $ derefPtr p
where
reifyDef :: Bool -> QName -> I.Elims -> TCM Expr
reifyDef True x es =
ifM (not . null . inverseScopeLookupName x <$> getScope) (reifyDef' x es) $ do
r <- reduceDefCopy x es
case r of
YesReduction _ v -> do
reportSLn "reify.anon" 60 $ unlines
[ "reduction on defined ident. in anonymous module"
, "x = " ++ show x
, "v = " ++ show v
]
reify v
NoReduction () -> do
reportSLn "reify.anon" 60 $ unlines
[ "no reduction on defined ident. in anonymous module"
, "x = " ++ show x
, "es = " ++ show es
]
reifyDef' x es
reifyDef _ x es = reifyDef' x es
reifyDef' :: QName -> I.Elims -> TCM Expr
reifyDef' x es = do
reportSLn "reify.def" 60 $ "reifying call to " ++ show x
n <- getDefFreeVars x
let fallback = elims (A.Def x) =<< reify (drop n es)
caseMaybeM (tryMaybe $ getConstInfo x) fallback $ \ defn -> do
let def = theDef defn
case def of
Function{ funCompiled = Just Fail, funClauses = [cl] }
| isAbsurdLambdaName x -> do
let h = getHiding $ last $ namedClausePats cl
elims (A.AbsurdLam noExprInfo h) =<< reify (drop n es)
_ -> do
df <- displayFormsEnabled
toppars <- size <$> do lookupSection $ qnameModule x
let extLam = case def of
Function{ funExtLam = Just{}, funProjection = Just{} } -> __IMPOSSIBLE__
Function{ funExtLam = Just (ExtLamInfo h nh) } -> Just (toppars + h + nh)
_ -> Nothing
case extLam of
Just pars | df -> reifyExtLam x pars (defClauses defn) es
_ -> do
(pad, nes :: [Elim' (Named_ Term)]) <- case def of
Function{ funProjection = Just Projection{ projIndex = np } } | np > 0 -> do
TelV tel _ <- telViewUpTo np (defType defn)
let (as, rest) = splitAt (np 1) $ telToList tel
dom = fromMaybe __IMPOSSIBLE__ $ headMaybe rest
scope <- getScope
let underscore = A.Underscore $ Info.emptyMetaInfo { metaScope = scope }
let pad = for as $ \ (Dom ai (x, _)) ->
Arg ai $ Named (Just $ unranged x) underscore
let pad' = drop n pad
es' = drop (max 0 (n size pad)) es
showImp <- showImplicitArguments
let (padVisNamed, padRest) = filterAndRest visible pad'
let padVis = map (fmap (unnamed . namedThing)) padVisNamed
let padTail = filter ((getHiding dom ==) . getHiding) padRest
let padSame = filter ((Just (fst (unDom dom)) ==) . fmap rangedThing . nameOf . unArg) padTail
return $ if null padTail || not showImp
then (padVis , map (fmap unnamed) es')
else (padVis ++ padSame, nameFirstIfHidden dom es')
_ -> return ([], map (fmap unnamed) $ drop n es)
let hd = foldl' (A.App noExprInfo) (A.Def x) pad
nelims hd =<< reify nes
reifyExtLam :: QName -> Int -> [I.Clause] -> I.Elims -> TCM Expr
reifyExtLam x npars cls es = do
reportSLn "reify.def" 10 $ "reifying extended lambda " ++ show x
reportSLn "reify.def" 50 $ show $ nest 2 $ vcat
[ text "npars =" <+> pretty npars
, text "es =" <+> fsep (map (prettyPrec 10) es)
, text "def =" <+> vcat (map pretty cls) ]
let (pars, rest) = splitAt npars es
cls <- mapM (reify . NamedClause x False . (`applyE` pars)) cls
let cx = nameConcrete $ qnameName x
dInfo = mkDefInfo cx noFixity' PublicAccess ConcreteDef (getRange x)
elims (A.ExtendedLam noExprInfo dInfo x cls) =<< reify rest
nameFirstIfHidden :: Dom (ArgName, t) -> [Elim' a] -> [Elim' (Named_ a)]
nameFirstIfHidden dom (I.Apply (Arg info e) : es) | notVisible info =
I.Apply (Arg info (Named (Just $ unranged $ fst $ unDom dom) e)) :
map (fmap unnamed) es
nameFirstIfHidden _ es =
map (fmap unnamed) es
instance Reify i a => Reify (Named n i) (Named n a) where
reify = traverse reify
reifyWhen b = traverse (reifyWhen b)
instance (Reify i a) => Reify (Arg i) (Arg a) where
reify (Arg info i) = Arg info <$> (flip reifyWhen i =<< condition)
where condition = (return (argInfoHiding info /= Hidden) `or2M` showImplicitArguments)
`and2M` (return (argInfoRelevance info /= Irrelevant) `or2M` showIrrelevantArguments)
reifyWhen b i = traverse (reifyWhen b) i
data NamedClause = NamedClause QName Bool I.Clause
newtype MonoidMap k v = MonoidMap { unMonoidMap :: Map.Map k v }
instance (Ord k, Monoid v) => Semigroup (MonoidMap k v) where
MonoidMap m1 <> MonoidMap m2 = MonoidMap (Map.unionWith mappend m1 m2)
instance (Ord k, Monoid v) => Monoid (MonoidMap k v) where
mempty = MonoidMap Map.empty
mappend = (<>)
stripImplicits :: ([NamedArg A.Pattern], [A.Pattern]) ->
TCM ([NamedArg A.Pattern], [A.Pattern])
stripImplicits (ps, wps) = do
ifM showImplicitArguments (return (map (unnamed . namedThing <$>) ps, wps)) $ do
reportSLn "reify.implicit" 30 $ unlines
[ "stripping implicits"
, " ps = " ++ show ps
, " wps = " ++ show wps
]
let allps = ps ++ map defaultNamedArg wps
sps = blankDots $ strip allps
(ps', wps') = splitAt (length sps length wps) sps
reportSLn "reify.implicit" 30 $ unlines
[ " ps' = " ++ show ps'
, " wps' = " ++ show (map namedArg wps')
]
return (ps', map namedArg wps')
where
blankDots ps = blank (varsBoundIn ps) ps
strip ps = stripArgs True ps
where
stripArgs _ [] = []
stripArgs fixedPos (a : as) =
if canStrip a
then if all canStrip $ takeWhile isUnnamedHidden as
then stripArgs False as
else let a' = fmap ($> A.WildP (Info.PatRange $ getRange a)) a
in stripName fixedPos a' : stripArgs True as
else stripName fixedPos (stripArg a) : stripArgs True as
stripName True = fmap (unnamed . namedThing)
stripName False = id
canStrip a = and
[ notVisible a
, getOrigin a /= UserWritten
, varOrDot (namedArg a)
]
isUnnamedHidden x = notVisible x && nameOf (unArg x) == Nothing && isNothing (isProjP x)
stripArg a = fmap (fmap stripPat) a
stripPat p = case p of
A.VarP _ -> p
A.ConP i c ps -> A.ConP i c $ stripArgs True ps
A.ProjP{} -> p
A.DefP _ _ _ -> p
A.DotP _ _ e -> p
A.WildP _ -> p
A.AbsurdP _ -> p
A.LitP _ -> p
A.AsP i x p -> A.AsP i x $ stripPat p
A.PatternSynP _ _ _ -> __IMPOSSIBLE__
A.RecP i fs -> A.RecP i $ map (fmap stripPat) fs
varOrDot A.VarP{} = True
varOrDot A.WildP{} = True
varOrDot A.DotP{} = True
varOrDot (A.ConP cpi _ ps) | patOrigin cpi == ConOSystem
= all varOrDot $ map namedArg ps
varOrDot _ = False
class BlankVars a where
blank :: Set Name -> a -> a
instance BlankVars a => BlankVars (Arg a) where
blank bound = fmap $ blank bound
instance BlankVars a => BlankVars (Named s a) where
blank bound = fmap $ blank bound
instance BlankVars a => BlankVars [a] where
blank bound = fmap $ blank bound
instance (BlankVars a, BlankVars b) => BlankVars (a, b) where
blank bound (x, y) = (blank bound x, blank bound y)
instance (BlankVars a, BlankVars b) => BlankVars (Either a b) where
blank bound (Left x) = Left $ blank bound x
blank bound (Right y) = Right $ blank bound y
instance BlankVars A.NamedDotPattern where
blank bound = id
instance BlankVars A.Clause where
blank bound (A.Clause lhs namedDots rhs [] ca) =
let bound' = varsBoundIn lhs `Set.union` bound
in A.Clause (blank bound' lhs)
(blank bound' namedDots)
(blank bound' rhs) [] ca
blank bound (A.Clause lhs namedDots rhs (_:_) ca) = __IMPOSSIBLE__
instance BlankVars A.LHS where
blank bound (A.LHS i core wps) = uncurry (A.LHS i) $ blank bound (core, wps)
instance BlankVars A.LHSCore where
blank bound (A.LHSHead f ps) = A.LHSHead f $ blank bound ps
blank bound (A.LHSProj p b ps) = uncurry (A.LHSProj p) $ blank bound (b, ps)
instance BlankVars A.Pattern where
blank bound p = case p of
A.VarP _ -> p
A.ConP c i ps -> A.ConP c i $ blank bound ps
A.ProjP{} -> p
A.DefP i f ps -> A.DefP i f $ blank bound ps
A.DotP i o e -> A.DotP i o $ blank bound e
A.WildP _ -> p
A.AbsurdP _ -> p
A.LitP _ -> p
A.AsP i n p -> A.AsP i n $ blank bound p
A.PatternSynP _ _ _ -> __IMPOSSIBLE__
A.RecP i fs -> A.RecP i $ blank bound fs
instance BlankVars A.Expr where
blank bound e = case e of
A.ScopedExpr i e -> A.ScopedExpr i $ blank bound e
A.Var x -> if x `Set.member` bound then e
else A.Underscore emptyMetaInfo
A.Def _ -> e
A.Proj{} -> e
A.Con _ -> e
A.Lit _ -> e
A.QuestionMark{} -> e
A.Underscore _ -> e
A.Dot i e -> A.Dot i $ blank bound e
A.App i e1 e2 -> uncurry (A.App i) $ blank bound (e1, e2)
A.WithApp i e es -> uncurry (A.WithApp i) $ blank bound (e, es)
A.Lam i b e -> let bound' = varsBoundIn b `Set.union` bound
in A.Lam i (blank bound b) (blank bound' e)
A.AbsurdLam _ _ -> e
A.ExtendedLam i d f cs -> A.ExtendedLam i d f $ blank bound cs
A.Pi i tel e -> let bound' = varsBoundIn tel `Set.union` bound
in uncurry (A.Pi i) $ blank bound' (tel, e)
A.Fun i a b -> uncurry (A.Fun i) $ blank bound (a, b)
A.Set _ _ -> e
A.Prop _ -> e
A.Let _ _ _ -> __IMPOSSIBLE__
A.Rec i es -> A.Rec i $ blank bound es
A.RecUpdate i e es -> uncurry (A.RecUpdate i) $ blank bound (e, es)
A.ETel _ -> __IMPOSSIBLE__
A.QuoteGoal {} -> __IMPOSSIBLE__
A.QuoteContext {} -> __IMPOSSIBLE__
A.Quote {} -> __IMPOSSIBLE__
A.QuoteTerm {} -> __IMPOSSIBLE__
A.Unquote {} -> __IMPOSSIBLE__
A.Tactic {} -> __IMPOSSIBLE__
A.DontCare v -> A.DontCare $ blank bound v
A.PatternSyn {} -> e
A.Macro {} -> e
instance BlankVars a => BlankVars (FieldAssignment' a) where
blank bound = over exprFieldA (blank bound)
instance BlankVars A.ModuleName where
blank bound = id
instance BlankVars RHS where
blank bound (RHS e mc) = RHS (blank bound e) mc
blank bound AbsurdRHS = AbsurdRHS
blank bound (WithRHS _ es clauses) = __IMPOSSIBLE__
blank bound (RewriteRHS xes rhs _) = __IMPOSSIBLE__
instance BlankVars A.LamBinding where
blank bound b@A.DomainFree{} = b
blank bound (A.DomainFull bs) = A.DomainFull $ blank bound bs
instance BlankVars TypedBindings where
blank bound (TypedBindings r bs) = TypedBindings r $ blank bound bs
instance BlankVars TypedBinding where
blank bound (TBind r n e) = TBind r n $ blank bound e
blank bound (TLet _ _) = __IMPOSSIBLE__
class Binder a where
varsBoundIn :: a -> Set Name
instance Binder A.LHS where
varsBoundIn (A.LHS _ core ps) = varsBoundIn (core, ps)
instance Binder A.LHSCore where
varsBoundIn (A.LHSHead _ ps) = varsBoundIn ps
varsBoundIn (A.LHSProj _ b ps) = varsBoundIn (b, ps)
instance Binder A.Pattern where
varsBoundIn p = case p of
A.VarP x -> if show x == "()" then empty else singleton x
A.ConP _ _ ps -> varsBoundIn ps
A.ProjP{} -> empty
A.DefP _ _ ps -> varsBoundIn ps
A.WildP{} -> empty
A.AsP _ _ p -> varsBoundIn p
A.DotP{} -> empty
A.AbsurdP{} -> empty
A.LitP{} -> empty
A.PatternSynP _ _ ps -> varsBoundIn ps
A.RecP _ fs -> varsBoundIn fs
instance Binder A.LamBinding where
varsBoundIn (A.DomainFree _ x) = singleton x
varsBoundIn (A.DomainFull b) = varsBoundIn b
instance Binder TypedBindings where
varsBoundIn (TypedBindings _ b) = varsBoundIn b
instance Binder TypedBinding where
varsBoundIn (TBind _ xs _) = varsBoundIn xs
varsBoundIn (TLet _ bs) = varsBoundIn bs
instance Binder LetBinding where
varsBoundIn (LetBind _ _ x _ _) = singleton x
varsBoundIn (LetPatBind _ p _) = varsBoundIn p
varsBoundIn LetApply{} = empty
varsBoundIn LetOpen{} = empty
varsBoundIn LetDeclaredVariable{} = empty
instance Binder a => Binder (FieldAssignment' a) where
varsBoundIn = varsBoundIn . (^. exprFieldA)
instance Binder a => Binder (Arg a) where
varsBoundIn = varsBoundIn . unArg
instance Binder a => Binder (Named x a) where
varsBoundIn = varsBoundIn . namedThing
instance Binder (WithHiding Name) where
varsBoundIn (WithHiding _ x) = singleton x
instance Binder a => Binder [a] where
varsBoundIn xs = Set.unions $ map varsBoundIn xs
instance (Binder a, Binder b) => Binder (a, b) where
varsBoundIn (x, y) = varsBoundIn x `Set.union` varsBoundIn y
reifyPatterns :: MonadTCM tcm => [NamedArg I.DeBruijnPattern] -> tcm [NamedArg A.Pattern]
reifyPatterns = mapM $ stripNameFromExplicit <.> traverse (traverse reifyPat)
where
stripNameFromExplicit :: NamedArg p -> NamedArg p
stripNameFromExplicit a
| getHiding a == NotHidden = fmap (unnamed . namedThing) a
| otherwise = a
reifyPat :: MonadTCM tcm => I.DeBruijnPattern -> tcm A.Pattern
reifyPat p = do
liftTCM $ reportSLn "reify.pat" 80 $ "reifying pattern " ++ show p
case p of
I.VarP x | isAbsurdPatternName (dbPatVarName x)
-> return $ A.AbsurdP patNoRange
I.VarP x -> liftTCM $ A.VarP <$> nameOfBV (dbPatVarIndex x)
I.DotP v -> do
t <- liftTCM $ reify v
return $ A.DotP patNoRange Inserted t
I.LitP l -> return $ A.LitP l
I.ProjP o d -> return $ A.ProjP patNoRange o $ AmbQ [d]
I.ConP c cpi ps -> do
liftTCM $ reportSLn "reify.pat" 60 $ "reifying pattern " ++ show p
tryRecPFromConP =<< do A.ConP ci (AmbQ [conName c]) <$> reifyPatterns ps
where
ci = ConPatInfo origin patNoRange
origin = fromMaybe ConOCon $ I.conPRecord cpi
tryRecPFromConP :: MonadTCM tcm => A.Pattern -> tcm A.Pattern
tryRecPFromConP p = do
let fallback = return p
case p of
A.ConP ci (AmbQ [c]) ps -> do
caseMaybeM (liftTCM $ isRecordConstructor c) fallback $ \ (r, def) -> do
if recNamedCon def && patOrigin ci /= ConORec then fallback else do
fs <- liftTCM $ getRecordFieldNames r
unless (length fs == length ps) __IMPOSSIBLE__
return $ A.RecP patNoRange $ zipWith mkFA fs ps
where
mkFA ax nap = FieldAssignment (unArg ax) (namedArg nap)
_ -> __IMPOSSIBLE__
instance Reify (QNamed I.Clause) A.Clause where
reify (QNamed f cl) = reify (NamedClause f True cl)
instance Reify NamedClause A.Clause where
reify (NamedClause f toDrop cl) = addContext (clauseTel cl) $ do
reportSLn "reify.clause" 60 $ "reifying NamedClause"
++ "\n f = " ++ show f
++ "\n toDrop = " ++ show toDrop
++ "\n cl = " ++ show cl
ps <- reifyPatterns $ namedClausePats cl
lhs <- liftTCM $ reifyDisplayFormP $ SpineLHS info f ps []
lhs <- if not toDrop then return lhs else do
nfv <- getDefFreeVars f `catchError` \_ -> return 0
return $ dropParams nfv lhs
lhs <- stripImps lhs
reportSLn "reify.clause" 60 $ "reifying NamedClause, lhs = " ++ show lhs
rhs <- caseMaybe (clauseBody cl) (return AbsurdRHS) $ \ e -> do
RHS <$> reify e <*> pure Nothing
reportSLn "reify.clause" 60 $ "reifying NamedClause, rhs = " ++ show rhs
let result = A.Clause (spineToLhs lhs) [] rhs [] (I.clauseCatchall cl)
reportSLn "reify.clause" 60 $ "reified NamedClause, result = " ++ show result
return result
where
perm = fromMaybe __IMPOSSIBLE__ $ clausePerm cl
info = LHSRange noRange
dropParams n (SpineLHS i f ps wps) = SpineLHS i f (genericDrop n ps) wps
stripImps (SpineLHS i f ps wps) = do
(ps, wps) <- stripImplicits (ps, wps)
return $ SpineLHS i f ps wps
instance Reify Type Expr where
reifyWhen = reifyWhenE
reify (I.El _ t) = reify t
instance Reify Sort Expr where
reifyWhen = reifyWhenE
reify s = do
s <- instantiateFull s
case s of
I.Type (I.Max []) -> return $ A.Set noExprInfo 0
I.Type (I.Max [I.ClosedLevel n]) -> return $ A.Set noExprInfo n
I.Type a -> do
a <- reify a
return $ A.App noExprInfo (A.Set noExprInfo 0) (defaultNamedArg a)
I.Prop -> return $ A.Prop noExprInfo
I.Inf -> A.Var <$> freshName_ ("SetĪ" :: String)
I.SizeUniv -> do
I.Def sizeU [] <- primSizeUniv
return $ A.Def sizeU
I.DLub s1 s2 -> do
lub <- freshName_ ("dLub" :: String)
(e1,e2) <- reify (s1, I.Lam defaultArgInfo $ fmap Sort s2)
let app x y = A.App noExprInfo x (defaultNamedArg y)
return $ A.Var lub `app` e1 `app` e2
instance Reify Level Expr where
reifyWhen = reifyWhenE
reify l = reify =<< reallyUnLevelView l
instance (Free i, Reify i a) => Reify (Abs i) (Name, a) where
reify (NoAbs x v) = (,) <$> freshName_ x <*> reify v
reify (Abs s v) = do
s <- return $ if isUnderscore s && 0 `freeIn` v then "z" else s
x <- freshName_ s
e <- addContext' x
$ reify v
return (x,e)
instance Reify I.Telescope A.Telescope where
reify EmptyTel = return []
reify (ExtendTel arg tel) = do
Arg info e <- reify arg
(x,bs) <- reify tel
let r = getRange e
return $ TypedBindings r (Arg info (TBind r [pure x] e)) : bs
instance Reify i a => Reify (Dom i) (Arg a) where
reify (Dom info i) = Arg info <$> reify i
instance Reify i a => Reify (I.Elim' i) (I.Elim' a) where
reify = traverse reify
reifyWhen b = traverse (reifyWhen b)
instance Reify i a => Reify [i] [a] where
reify = traverse reify
reifyWhen b = traverse (reifyWhen b)
instance (Reify i1 a1, Reify i2 a2) => Reify (i1,i2) (a1,a2) where
reify (x,y) = (,) <$> reify x <*> reify y
instance (Reify i1 a1, Reify i2 a2, Reify i3 a3) => Reify (i1,i2,i3) (a1,a2,a3) where
reify (x,y,z) = (,,) <$> reify x <*> reify y <*> reify z
instance (Reify i1 a1, Reify i2 a2, Reify i3 a3, Reify i4 a4) => Reify (i1,i2,i3,i4) (a1,a2,a3,a4) where
reify (x,y,z,w) = (,,,) <$> reify x <*> reify y <*> reify z <*> reify w