1
{-# LANGUAGE CPP, PatternGuards #-}
2
{-# LANGUAGE FlexibleContexts #-}
3
{-# LANGUAGE FlexibleInstances #-}
4
{-# LANGUAGE PatternGuards #-}
2
6
module Agda.TypeChecking.Monad.Signature where
4
import Control.Arrow ((***))
8
import Control.Applicative
5
9
import Control.Monad.State
6
10
import Control.Monad.Reader
8
import qualified Data.Set as Set
9
13
import Data.Map (Map)
10
14
import qualified Data.Map as Map
14
17
import Agda.Syntax.Abstract.Name
15
18
import Agda.Syntax.Common
16
import Agda.Syntax.Internal
19
import Agda.Syntax.Internal as I
17
20
import Agda.Syntax.Position
19
22
import qualified Agda.Compiler.JS.Parser as JS
24
27
import Agda.TypeChecking.Monad.Env
25
28
import Agda.TypeChecking.Monad.Mutual
26
29
import Agda.TypeChecking.Monad.Open
27
import Agda.TypeChecking.Free (isBinderUsed)
30
import Agda.TypeChecking.Monad.State
28
31
import Agda.TypeChecking.Substitute
29
32
import {-# SOURCE #-} Agda.TypeChecking.CompiledClause.Compile
30
33
import {-# SOURCE #-} Agda.TypeChecking.Polarity
31
34
import {-# SOURCE #-} Agda.TypeChecking.ProjectionLike
36
import Agda.Utils.Map as Map
37
import Agda.Utils.Maybe
33
38
import Agda.Utils.Monad
34
import Agda.Utils.Map as Map
35
39
import Agda.Utils.Size
36
40
import Agda.Utils.Permutation
37
41
import Agda.Utils.Pretty
87
93
updateDefCompiledRep :: (CompiledRepresentation -> CompiledRepresentation) -> (Definition -> Definition)
88
94
updateDefCompiledRep f def = def { defCompiledRep = f (defCompiledRep def) }
96
updateFunClauses :: ([Clause] -> [Clause]) -> (Defn -> Defn)
97
updateFunClauses f def@Function{ funClauses = cs} = def { funClauses = f cs }
98
updateFunClauses f _ = __IMPOSSIBLE__
90
100
-- | Add a constant to the signature. Lifts the definition to top level.
91
101
addConstant :: QName -> Definition -> TCM ()
92
102
addConstant q d = do
93
103
reportSLn "tc.signature" 20 $ "adding constant " ++ show q ++ " to signature"
94
104
tel <- getContextTelescope
95
let tel' = killRange $ case theDef d of
96
Constructor{} -> fmap (mapDomHiding (const Hidden)) tel
105
let tel' = replaceEmptyName "r" $ killRange $ case theDef d of
106
Constructor{} -> fmap (setHiding Hidden) tel
98
108
let d' = abstract tel' $ d { defName = q }
99
109
reportSLn "tc.signature" 30 $ "lambda-lifted definition = " ++ show d'
111
121
setT def@Function{} = def { funTerminates = Just b }
124
-- | Modify the clauses of a function.
125
modifyFunClauses :: QName -> ([Clause] -> [Clause]) -> TCM ()
126
modifyFunClauses q f =
127
modifySignature $ updateDefinition q $ updateTheDef $ updateFunClauses f
129
-- | Lifts clauses to the top-level and adds them to definition.
130
addClauses :: QName -> [Clause] -> TCM ()
131
addClauses q cls = do
132
tel <- getContextTelescope
133
modifyFunClauses q (++ abstract tel cls)
114
135
addHaskellCode :: QName -> HaskellType -> HaskellCode -> TCM ()
115
136
addHaskellCode q hsTy hsDef = modifySignature $ updateDefinition q $ updateDefCompiledRep $ addHs
116
137
-- TODO: sanity checking
118
139
addHs crep = crep { compiledHaskell = Just $ HsDefn hsTy hsDef }
141
addHaskellExport :: QName -> HaskellType -> String -> TCM ()
142
addHaskellExport q hsTy hsName = modifySignature $ updateDefinition q $ updateDefCompiledRep $ addHs
143
-- TODO: sanity checking
145
addHs crep = crep { exportHaskell = Just (HsExport hsTy hsName)}
120
147
addHaskellType :: QName -> HaskellType -> TCM ()
121
148
addHaskellType q hsTy = modifySignature $ updateDefinition q $ updateDefCompiledRep $ addHs
122
149
-- TODO: sanity checking
169
196
-- Add display forms to all names @xn@ such that @x = x1 es1@, ... @xn-1 = xn esn@.
170
197
addDisplayForms :: QName -> TCM ()
171
198
addDisplayForms x = do
199
def <- getConstInfo x
172
200
args <- getContextArgs
174
203
proj <- isProjection x
175
204
return $ case proj of
178
add (drop (n - 1) args) x x []
208
add (drop (projectionArgs $ theDef def) args) x x []
180
210
add args top x vs0 = do
181
211
def <- getConstInfo x
182
212
let cs = defClauses def
184
[ Clause{ clausePats = pats, clauseBody = b } ]
185
| all (isVar . unArg) pats
186
, Just (m, Def y vs) <- strip (b `apply` vs0) -> do
187
let ps = raise 1 (map unArg vs)
188
df = Display 0 ps $ DTerm $ Def top args
214
[ Clause{ namedClausePats = pats, clauseBody = b } ]
215
| all (isVar . namedArg) pats
216
, Just (m, Def y es) <- strip (b `apply` vs0)
217
, Just vs <- mapM isApplyElim es -> do
218
let ps = raise 1 $ map unArg vs
219
df = Display 0 ps $ DTerm $ Def top $ map Apply args
189
220
reportSLn "tc.display.section" 20 $ "adding display form " ++ show y ++ " --> " ++ show top
190
221
++ "\n " ++ show df
191
222
addDisplayForm y df
196
227
_:_:_ -> "many clauses"
197
228
[ Clause{ clauseBody = b } ] -> case strip b of
198
229
Nothing -> "bad body"
200
231
| m < length args -> "too few args"
201
232
| m > length args -> "too many args"
202
| otherwise -> "args=" ++ show args ++ " vs=" ++ show vs
233
| otherwise -> "args=" ++ show args ++ " es=" ++ show es
203
234
Just (m, v) -> "not a def body"
204
235
reportSLn "tc.display.section" 30 $ "no display form from " ++ show x ++ " because " ++ reason
206
strip (Body v) = return (0, v)
237
strip (Body v) = return (0, unSpine v)
207
238
strip NoBody = Nothing
208
239
strip (Bind b) = do
209
240
(n, v) <- strip $ absBody b
212
243
isVar VarP{} = True
216
ModuleName -> Telescope -> ModuleName -> Args ->
217
Map QName QName -> Map ModuleName ModuleName -> TCM ()
246
-- | Module application (followed by module parameter abstraction).
248
:: ModuleName -- ^ Name of new module defined by the module macro.
249
-> Telescope -- ^ Parameters of new module.
250
-> ModuleName -- ^ Name of old module applied to arguments.
251
-> Args -- ^ Arguments of module application.
252
-> Map QName QName -- ^ Imported names (given as renaming).
253
-> Map ModuleName ModuleName -- ^ Imported modules (given as renaming).
218
255
applySection new ptel old ts rd rm = do
219
256
sig <- getSignature
220
257
isig <- getImportedSignature
244
281
partOfOldM x = x `isSubModuleOf` old
245
282
partOfOldD x = x `isInModule` old
247
copyName x = maybe x id $ Map.lookup x rd
284
-- Andreas, 2013-10-29
285
-- Here, if the name x is not imported, it persists as
286
-- old, possibly out-of-scope name.
287
-- This old name may used by the case split tactic, leading to
288
-- names that cannot be printed properly.
289
-- I guess it would make sense to mark non-imported names
290
-- as such (out-of-scope) and let splitting fail if it would
291
-- produce out-of-scope constructors.
292
copyName x = Map.findWithDefault x x rd
249
294
copyDef :: Args -> (QName, Definition) -> TCM ()
250
copyDef ts (x, d) = case Map.lookup x rd of
296
case Map.lookup x rd of
251
297
Nothing -> return () -- if it's not in the renaming it was private and
252
298
-- we won't need it
265
311
pol = defPolarity d `apply` ts
266
312
occ = defArgOccurrences d `apply` ts
267
313
-- the name is set by the addConstant function
268
nd y = Defn (defRelevance d) y t pol occ [] (-1) noCompiledRep <$> def -- TODO: mutual block?
314
nd y = Defn (defArgInfo d) y t pol occ [] (-1) noCompiledRep <$> def -- TODO: mutual block?
269
315
oldDef = theDef d
270
isCon = case oldDef of
271
Constructor{} -> True
275
Function { funArgOccurrences = os } -> os
276
Datatype { dataArgOccurrences = os } -> os
277
Record { recArgOccurrences = os } -> os
279
oldOcc = getOcc oldDef
316
isCon = case oldDef of { Constructor{} -> True ; _ -> False }
317
mutual = case oldDef of { Function{funMutual = m} -> m ; _ -> [] }
318
extlam = case oldDef of { Function{funExtLam = e} -> e ; _ -> Nothing }
319
with = case oldDef of { Function{funWith = w} -> copyName <$> w ; _ -> Nothing }
320
{- THIS BREAKS A LOT OF THINGS:
321
-- Andreas, 2013-10-21:
322
-- Even if we apply the record argument, we stay a projection.
323
-- This is because we may abstract the record argument later again.
324
-- See succeed/ProjectionNotNormalized.agda
325
proj = case oldDef of
326
Function{funProjection = Just p@Projection{projIndex = n}}
327
-> Just $ p { projIndex = n - size ts
328
, projDropPars = projDropPars p `apply` ts
332
-- NB (Andreas, 2013-10-19):
333
-- If we apply the record argument, we are no longer a projection!
334
proj = case oldDef of
335
Function{funProjection = Just p@Projection{projIndex = n}} | size ts < n
336
-> Just $ p { projIndex = n - size ts
337
, projDropPars = projDropPars p `apply` ts
281
341
def = case oldDef of
282
342
Constructor{ conPars = np, conData = d } -> return $
283
oldDef { conPars = np - size ts, conData = copyName d }
343
oldDef { conPars = np - size ts
344
, conData = copyName d
284
346
Datatype{ dataPars = np, dataCons = cs } -> return $
285
oldDef { dataPars = np - size ts, dataClause = Just cl, dataCons = map copyName cs
286
{- , dataArgOccurrences = drop (length ts) oldOcc -} }
347
oldDef { dataPars = np - size ts
348
, dataClause = Just cl
349
, dataCons = map copyName cs
287
351
Record{ recPars = np, recConType = t, recTel = tel } -> return $
288
oldDef { recPars = np - size ts, recClause = Just cl
289
, recConType = apply t ts, recTel = apply tel ts
290
{- , recArgOccurrences = drop (length ts) oldOcc -}
352
oldDef { recPars = np - size ts
353
, recClause = Just cl
354
, recConType = apply t ts
355
, recTel = apply tel ts
293
358
cc <- compileClauses Nothing [cl] -- Andreas, 2012-10-07 non need for record pattern translation
294
359
let newDef = Function
295
360
{ funClauses = [cl]
361
, funCompiled = Just $ cc
297
362
, funDelayed = NotDelayed
298
363
, funInv = NotInjective
301
, funArgOccurrences = drop (length ts') oldOcc
303
364
, funMutual = mutual
304
365
, funAbstr = ConcreteDef
305
366
, funProjection = proj
306
367
, funStatic = False
308
369
, funTerminates = Just True
310
373
reportSLn "tc.mod.apply" 80 $ "new def for " ++ show x ++ "\n " ++ show newDef
313
mutual = case oldDef of
314
Function{funMutual = m} -> m
316
proj = case oldDef of
317
Function{funProjection = Just (r, n)}
318
| size ts < n -> Just (r, n - size ts)
320
376
ts' | null ts = []
321
377
| otherwise = case oldDef of
322
Function{funProjection = Just (_, n)}
378
Function{funProjection = Just Projection{ projIndex = n}}
323
379
| n == 0 -> __IMPOSSIBLE__
324
380
| otherwise -> drop (n - 1) ts
326
cl = Clause { clauseRange = getRange $ defClauses d
327
, clauseTel = EmptyTel
330
, clauseBody = Body $ Def x ts'
383
head = case oldDef of
384
Function{funProjection = Just Projection{ projDropPars = f}}
387
cl = Clause { clauseRange = getRange $ defClauses d
388
, clauseTel = EmptyTel
390
, namedClausePats = []
391
, clauseBody = Body $ head `apply` ts
392
, clauseType = Just $ defaultArg t
333
395
copySec :: Args -> (ModuleName, Section) -> TCM ()
393
461
_ -> __IMPOSSIBLE__
394
462
_ -> __IMPOSSIBLE__
396
{-# SPECIALIZE getConstInfo :: QName -> TCM Definition #-}
397
getConstInfo :: MonadTCM tcm => QName -> tcm Definition
398
getConstInfo q = liftTCM $ join $ pureTCM $ \st env ->
399
let defs = sigDefinitions $ stSignature st
400
idefs = sigDefinitions $ stImports st
401
smash = (++) `on` maybe [] (:[])
402
in case smash (HMap.lookup q defs) (HMap.lookup q idefs) of
403
[] -> fail $ "Unbound name: " ++ show q ++ " " ++ showQNameId q
405
ds -> fail $ "Ambiguous name: " ++ show q
408
| treatAbstractly' q' env =
409
case makeAbstract d of
411
Nothing -> typeError $ NotInScope [qnameToConcrete q]
412
-- the above can happen since the scope checker is a bit sloppy with 'abstract'
413
| otherwise = return d
415
q' = case theDef d of
416
-- Hack to make abstract constructors work properly. The constructors
417
-- live in a module with the same name as the datatype, but for 'abstract'
418
-- purposes they're considered to be in the same module as the datatype.
419
Constructor{} -> dropLastModule q
422
dropLastModule q@QName{ qnameModule = m } =
423
q{ qnameModule = mnameFromList $ init' $ mnameToList m }
425
init' [] = {-'-} __IMPOSSIBLE__
464
class (Functor m, Applicative m, Monad m) => HasConstInfo m where
465
-- | Lookup the definition of a name. The result is a closed thing, all free
466
-- variables have been abstracted over.
467
getConstInfo :: QName -> m Definition
469
{-# SPECIALIZE getConstInfo :: QName -> TCM Definition #-}
471
instance HasConstInfo (TCMT IO) where
472
getConstInfo q = join $ pureTCM $ \st env ->
473
let defs = sigDefinitions $ stSignature st
474
idefs = sigDefinitions $ stImports st
475
in case catMaybes [HMap.lookup q defs, HMap.lookup q idefs] of
476
[] -> fail $ "Unbound name: " ++ show q ++ " " ++ showQNameId q
478
ds -> fail $ "Ambiguous name: " ++ show q
481
| treatAbstractly' q' env =
482
case makeAbstract d of
484
Nothing -> notInScope $ qnameToConcrete q
485
-- the above can happen since the scope checker is a bit sloppy with 'abstract'
486
| otherwise = return d
488
q' = case theDef d of
489
-- Hack to make abstract constructors work properly. The constructors
490
-- live in a module with the same name as the datatype, but for 'abstract'
491
-- purposes they're considered to be in the same module as the datatype.
492
Constructor{} -> dropLastModule q
495
dropLastModule q@QName{ qnameModule = m } =
496
q{ qnameModule = mnameFromList $ init' $ mnameToList m }
498
init' [] = {-'-} __IMPOSSIBLE__
501
{-# INLINE getConInfo #-}
502
{-# SPECIALIZE getConstInfo :: QName -> TCM Definition #-}
503
getConInfo :: MonadTCM tcm => ConHead -> tcm Definition
504
getConInfo = liftTCM . getConstInfo . conName
428
506
-- | Look up the polarity of a definition.
429
507
getPolarity :: QName -> TCM [Polarity]
430
508
getPolarity q = defPolarity <$> getConstInfo q
433
getPolarity :: QName -> TCM [Polarity]
435
defn <- theDef <$> getConstInfo q
437
Function{ funPolarity = p } -> return p
438
Datatype{ dataPolarity = p } -> return p
439
Record{ recPolarity = p } -> return p
443
510
-- | Look up polarity of a definition and compose with polarity
444
511
-- represented by 'Comparison'.
445
512
getPolarity' :: Comparison -> QName -> TCM [Polarity]
453
517
setPolarity :: QName -> [Polarity] -> TCM ()
454
518
setPolarity q pol = modifySignature $ updateDefinition q $ updateDefPolarity $ const pol
457
setPolarity :: QName -> [Polarity] -> TCM ()
458
setPolarity q pol = do
461
setP sig = sig { sigDefinitions = HMap.adjust setPx q defs }
463
setPx def = def { theDef = setPd $ theDef def }
465
Function{} -> d { funPolarity = pol }
466
Datatype{} -> d { dataPolarity = pol }
467
Record{} -> d { recPolarity = pol }
469
defs = sigDefinitions sig
472
520
-- | Return a finite list of argument occurrences.
473
521
getArgOccurrences :: QName -> TCM [Occurrence]
474
522
getArgOccurrences d = defArgOccurrences <$> getConstInfo d
587
621
verboseS "tc.sig.inst" 30 $ do
588
622
ctx <- getContext
589
623
m <- currentModule
590
reportSLn "" 0 $ "instDef in " ++ show m ++ ": " ++ show (defName d) ++ " " ++
591
unwords (map show . take (size vs) . reverse . map (fst . unDom) $ ctx)
624
reportSLn "tc.sig.inst" 30 $
625
"instDef in " ++ show m ++ ": " ++ show (defName d) ++ " " ++
626
unwords (map show . take (size vs) . reverse . map (fst . unDom) $ ctx)
592
627
return $ d `apply` vs
594
629
-- | Give the abstract view of a definition.
595
630
makeAbstract :: Definition -> Maybe Definition
596
makeAbstract d = do def <- makeAbs $ theDef d
597
return d { theDef = def }
599
makeAbs Datatype {dataAbstr = AbstractDef} = Just Axiom
600
makeAbs Function {funAbstr = AbstractDef} = Just Axiom
601
makeAbs Constructor{conAbstr = AbstractDef} = Nothing
632
case defAbstract d of
633
ConcreteDef -> return d
635
def <- makeAbs $ theDef d
636
return d { defArgOccurrences = [] -- no positivity info for abstract things!
637
, defPolarity = [] -- no polarity info for abstract things!
641
makeAbs Datatype {} = Just Axiom
642
makeAbs Function {} = Just Axiom
643
makeAbs Constructor{} = Nothing
644
-- Andreas, 2012-11-18: Make record constructor and projections abstract.
645
makeAbs d@Record{} = Just Axiom
646
-- Q: what about primitive?
604
649
-- | Enter abstract mode. Abstract definition in the current module are transparent.
605
650
inAbstractMode :: TCM a -> TCM a
634
679
current = envCurrentModule env
635
680
m = qnameModule q
682
-- | Get type of a constant, instantiated to the current context.
637
683
typeOfConst :: QName -> TCM Type
638
684
typeOfConst q = defType <$> (instantiateDef =<< getConstInfo q)
686
-- | Get relevance of a constant.
640
687
relOfConst :: QName -> TCM Relevance
641
688
relOfConst q = defRelevance <$> getConstInfo q
690
-- | Get colors of a constant.
691
colOfConst :: QName -> TCM [Color]
692
colOfConst q = defColors <$> getConstInfo q
643
694
-- | The name must be a datatype.
644
695
sortOfConst :: QName -> TCM Sort
651
700
_ -> fail $ "Expected " ++ show q ++ " to be a datatype."
653
702
-- | Is it the name of a record projection?
654
isProjection :: QName -> TCM (Maybe (QName, Int))
656
def <- theDef <$> getConstInfo qn
703
isProjection :: QName -> TCM (Maybe Projection)
704
isProjection qn = isProjection_ . theDef <$> getConstInfo qn
706
isProjection_ :: Defn -> Maybe Projection
658
Function { funProjection = result } -> return $ result
659
_ -> return $ Nothing
709
Function { funProjection = result } -> result
712
isProperProjection :: Defn -> Bool
713
isProperProjection = isJust . (projProper <=< isProjection_)
714
-- isProperProjection = maybe False projProper . isProjection_
716
-- | Number of dropped initial arguments.
717
projectionArgs :: Defn -> Int
718
projectionArgs = maybe 0 (pred . projIndex) . isProjection_
720
-- | Apply a function @f@ to its first argument, producing the proper
721
-- postfix projection if @f@ is a projection.
722
applyDef :: QName -> I.Arg Term -> TCM Term
724
-- get the original projection, if existing
725
res <- (projProper =<<) <$> isProjection f
727
Nothing -> return $ Def f [Apply a]
728
Just f' -> return $ unArg a `applyE` [Proj f']
730
-- | @getDefType f t@ computes the type of (possibly projection-(like))
731
-- function @t@ whose first argument has type @t@.
732
-- The `parameters' for @f@ are extracted from @t@.
733
-- @Nothing@ if @f@ is projection(like) but
734
-- @t@ is not a data/record/axiom type.
736
-- Precondition: @t@ is reduced.
738
-- See also: 'Agda.TypeChecking.Datatypes.getConType'
739
getDefType :: QName -> Type -> TCM (Maybe Type)
741
def <- getConstInfo f
743
-- if @f@ is not a projection (like) function, @a@ is the correct type
744
caseMaybe (isProjection_ $ theDef def) (return $ Just a) $
745
\ (Projection{ projIndex = n }) -> do
746
-- otherwise, we have to instantiate @a@ to the "parameters" of @f@
747
let npars | n == 0 = __IMPOSSIBLE__
749
-- we get the parameters from type @t@
750
case ignoreSharing $ unEl t of
752
-- Andreas, 2013-10-22
753
-- we need to check this @Def@ is fully reduced.
754
-- If it is stuck due to disabled reductions
755
-- (because of failed termination check),
756
-- we will produce garbage parameters.
757
flip (ifM $ eligibleForProjectionLike d) (return Nothing) $ do
758
-- now we know it is reduced, we can safely take the parameters
759
let pars = fromMaybe __IMPOSSIBLE__ $ allApplyElims $ take npars es
760
-- pars <- maybe (return Nothing) return $ allApplyElims $ take npars es
761
return $ Just $ a `apply` pars