1- {-# LANGUAGE FlexibleContexts, OverloadedStrings #-}
1+ {-# LANGUAGE FlexibleContexts, OverloadedStrings, BangPatterns #-}
22
33-- | Agda utilities.
44module Agda.Utils where
@@ -11,9 +11,12 @@ import Control.Arrow ( first )
1111import Data.List ( partition )
1212import qualified Data.List.NonEmpty as NE ( fromList )
1313import Data.Maybe ( isJust , isNothing )
14+ import Data.Bifunctor ( second )
1415
1516import Utils
1617import Agda.Lib
18+ import Agda.TypeChecking.Free.Lazy (underBinder )
19+ import Agda.TypeChecking.Datatypes (getConstructorInfo , ConstructorInfo (.. ))
1720
1821-- ** useful monad constraint kinds
1922
@@ -59,6 +62,58 @@ unqual = pp . last . qnameToList0
5962hasPragma :: QName -> TCM Bool
6063hasPragma qn = isJust <$> getUniqueCompilerPragma " AGDA2LAMBOX" qn
6164
65+
66+ -- ** eta-expansion of constructors
67+
68+ -- NOTE(flupe):
69+ -- We do this because CertiCoq requires fully-applied constructors.
70+ -- In the future, this transformation should be made on the Coq side.
71+ -- (as it would be proven correct).
72+ -- NB: MetaCoq provides eta-expansion of constructors, but only for eprograms.
73+ -- (see : erasure/theories/EConstructorsAsBlocks.v)
74+
75+ -- | Check whether a treeless term is a constructor applied to (many) terms.
76+ unSpineCon :: TTerm -> Maybe (QName , [TTerm ])
77+ unSpineCon (TCon q) = Just (q, [] )
78+ unSpineCon (TApp u v) = second (++ v) <$> unSpineCon u
79+ unSpineCon _ = Nothing
80+
81+ -- | Return the arity of a constructor. Ignores parameters.
82+ conArity :: ConstructorInfo -> Int
83+ conArity (DataCon a) = a
84+ conArity (RecordCon _ _ a _) = a
85+
86+ -- | Eta-expand treeless constructors.
87+ etaExpandCtor :: TTerm -> TCM TTerm
88+ etaExpandCtor t | Just (q, args) <- unSpineCon t = do
89+ arity <- conArity <$> getConstructorInfo q
90+ let nargs = length args
91+
92+ if nargs >= arity then -- should really be (==), but just in case
93+ TApp (TCon q) <$> mapM etaExpandCtor args
94+ else do
95+ let nlam = arity - nargs
96+ exargs <- mapM (etaExpandCtor . raise nlam) args
97+ let vars = TVar <$> [(nlam - 1 ) .. 0 ]
98+ pure $ iterate TLam (TApp (TCon q) $ exargs ++ vars) !! nlam
99+
100+ etaExpandCtor t | otherwise = case t of
101+ TApp u v -> TApp <$> etaExpandCtor u <*> mapM etaExpandCtor v
102+ TLam u -> TLam <$> etaExpandCtor u
103+ TLet u v -> TLet <$> etaExpandCtor u <*> etaExpandCtor v
104+ TCase k ci tdef alts -> TCase k ci <$> etaExpandCtor tdef
105+ <*> mapM etaExpandAlt alts
106+ TCoerce u -> TCoerce <$> etaExpandCtor u
107+ _ -> pure t
108+
109+ etaExpandAlt :: TAlt -> TCM TAlt
110+ etaExpandAlt = \ case
111+ TACon q a b -> TACon q a <$> etaExpandCtor b
112+ TAGuard a b -> TAGuard a <$> etaExpandCtor b
113+ TALit l b -> TALit l <$> etaExpandCtor b
114+
115+
116+
62117{-
63118lookupCtx :: MonadTCEnv m => Int -> m (String, Type)
64119lookupCtx i = first transcribe . (!! i) {- . reverse-} <$> currentCtx
0 commit comments