~ubuntu-branches/ubuntu/trusty/agda/trusty

« back to all changes in this revision

Viewing changes to src/full/Agda/TypeChecking/SizedTypes.hs

  • Committer: Package Import Robot
  • Author(s): Iain Lane, Kiwamu Okabe, Iain Lane
  • Date: 2013-04-10 11:46:43 UTC
  • mfrom: (4.1.5 experimental)
  • Revision ID: package-import@ubuntu.com-20130410114643-prunhsz59f0fhrdn
Tags: 2.3.2-1
[ Kiwamu Okabe ]
* New patch: Extend haskell-src-exts dependency and fix type miss.

[ Iain Lane ]
* [dfbca48] Imported Upstream version 2.3.2
* [7746bcc] Remove all patches — all upstream.
* [2cdb691] Update build-deps to match control file
* [868ebf4] agda-mode no longer depends on haskell-mode or GHCi.
  Remove dependency and update .el file accordingly
* [9e0ba22] Add agda-bin package here, as the separate package has been
  removed
* [75a240f] agda-mode needs to depend on agda-bin
* [d290f95] Allow Quickcheck up to 2.7. Fix haskeline build-dep.
* [79190e6] Add missing geniplate and parallel BDs

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
{-# LANGUAGE CPP #-}
 
1
{-# LANGUAGE CPP, PatternGuards #-}
2
2
module Agda.TypeChecking.SizedTypes where
3
3
 
4
4
import Control.Monad.Error
5
5
import Control.Monad
 
6
 
 
7
import Data.Function
6
8
import Data.List
7
9
import qualified Data.Map as Map
8
10
 
9
11
import Agda.Interaction.Options
 
12
 
10
13
import Agda.Syntax.Common
11
14
import Agda.Syntax.Internal
 
15
 
12
16
import Agda.TypeChecking.Monad
13
17
import Agda.TypeChecking.Monad.Builtin
14
18
import Agda.TypeChecking.Pretty
15
19
import Agda.TypeChecking.Reduce
16
 
import Agda.TypeChecking.MetaVars
 
20
import {-# SOURCE #-} Agda.TypeChecking.MetaVars
17
21
import Agda.TypeChecking.Substitute
18
22
import Agda.TypeChecking.Telescope
19
23
import {-# SOURCE #-} Agda.TypeChecking.Conversion
20
 
import Agda.TypeChecking.Constraints
 
24
import {-# SOURCE #-} Agda.TypeChecking.Constraints
 
25
 
21
26
import qualified Agda.Utils.Warshall as W
22
27
import Agda.Utils.List
 
28
import Agda.Utils.Maybe
23
29
import Agda.Utils.Monad
24
30
import Agda.Utils.Impossible
25
31
import Agda.Utils.Size
 
32
import Agda.Utils.Tuple
 
33
import Agda.Utils.Pretty (render)
26
34
 
27
35
#include "../undefined.h"
28
36
 
29
 
compareSizes :: Comparison -> Term -> Term -> TCM ()
30
 
compareSizes cmp u v = do
31
 
  reportSDoc "tc.conv.size" 10 $ vcat
32
 
    [ text "Comparing sizes"
33
 
    , nest 2 $ sep [ prettyTCM u <+> prettyTCM cmp
34
 
                   , prettyTCM v
35
 
                   ]
36
 
    ]
37
 
  u <- reduce u
38
 
  v <- reduce v
39
 
  reportSDoc "tc.conv.size" 15 $
40
 
      nest 2 $ sep [ text (show u) <+> prettyTCM cmp
41
 
                   , text (show v)
42
 
                   ]
 
37
builtinSizeHook :: String -> QName -> Term -> Type -> TCM ()
 
38
builtinSizeHook s q e' t = do
 
39
  when (s `elem` [builtinSizeLt, builtinSizeSuc]) $ do
 
40
    modifySignature $ updateDefinition q
 
41
      $ updateDefPolarity       (const [Covariant])
 
42
      . updateDefArgOccurrences (const [StrictPos])
 
43
  when (s == builtinSizeMax) $ do
 
44
    modifySignature $ updateDefinition q
 
45
      $ updateDefPolarity       (const [Covariant, Covariant])
 
46
      . updateDefArgOccurrences (const [StrictPos, StrictPos])
 
47
{-
 
48
      . updateDefType           (const tmax)
 
49
  where
 
50
    -- TODO: max : (i j : Size) -> Size< (suc (max i j))
 
51
    tmax =
 
52
-}
 
53
 
 
54
-- | Compute the deep size view of a term.
 
55
--   Precondition: sized types are enabled.
 
56
deepSizeView :: Term -> TCM DeepSizeView
 
57
deepSizeView v = do
 
58
  Def inf [] <- ignoreSharing <$> primSizeInf
 
59
  Def suc [] <- ignoreSharing <$> primSizeSuc
 
60
  let loop v = do
 
61
      v <- reduce v
 
62
      case ignoreSharing v of
 
63
        Def x []  | x == inf -> return $ DSizeInf
 
64
        Def x [u] | x == suc -> sizeViewSuc_ suc <$> loop (unArg u)
 
65
        Var i []             -> return $ DSizeVar i 0
 
66
        MetaV x us           -> return $ DSizeMeta x us 0
 
67
        _                    -> return $ DOtherSize v
 
68
  loop v
 
69
 
 
70
sizeMaxView :: Term -> TCM SizeMaxView
 
71
sizeMaxView v = do
 
72
  inf <- getBuiltinDefName builtinSizeInf
 
73
  suc <- getBuiltinDefName builtinSizeSuc
 
74
  max <- getBuiltinDefName builtinSizeMax
 
75
  let loop v = do
 
76
      v <- reduce v
 
77
      case v of
 
78
        Def x []      | Just x == inf -> return $ [DSizeInf]
 
79
        Def x [u]     | Just x == suc -> maxViewSuc_ (fromJust suc) <$> loop (unArg u)
 
80
        Def x [u1,u2] | Just x == max -> maxViewMax <$> loop (unArg u1) <*> loop (unArg u2)
 
81
        Var i []                      -> return $ [DSizeVar i 0]
 
82
        MetaV x us                    -> return $ [DSizeMeta x us 0]
 
83
        _                             -> return $ [DOtherSize v]
 
84
  loop v
 
85
 
 
86
-- | Account for subtyping @Size< i =< Size@
 
87
--   Preconditions:
 
88
--   @m = x els1@, @n = y els2@, @m@ and @n@ are not equal.
 
89
trySizeUniv :: Comparison -> Type -> Term -> Term
 
90
  -> QName -> [Elim] -> QName -> [Elim] -> TCM ()
 
91
trySizeUniv cmp t m n x els1 y els2 = do
 
92
  let failure = typeError $ UnequalTerms cmp m n t
 
93
      forceInfty u = compareSizes CmpEq (unArg u) =<< primSizeInf
 
94
  (size, sizelt) <- flip catchError (const failure) $ do
 
95
     Def size   _ <- ignoreSharing <$> primSize
 
96
     Def sizelt _ <- ignoreSharing <$> primSizeLt
 
97
     return (size, sizelt)
 
98
  case (cmp, els1, els2) of
 
99
     (CmpLeq, [_], [])  | x == sizelt && y == size -> return ()
 
100
     (_, [Apply u], []) | x == sizelt && y == size -> forceInfty u
 
101
     (_, [], [Apply u]) | x == size && y == sizelt -> forceInfty u
 
102
     _                                             -> failure
 
103
 
 
104
-- | Compare two sizes. Only with --sized-types.
 
105
compareSizes :: Comparison -> Term -> Term -> TCM ()
 
106
compareSizes cmp u v = do
 
107
  reportSDoc "tc.conv.size" 10 $ vcat
 
108
    [ text "Comparing sizes"
 
109
    , nest 2 $ sep [ prettyTCM u <+> prettyTCM cmp
 
110
                   , prettyTCM v
 
111
                   ]
 
112
    ]
 
113
{-
 
114
  u <- reduce u
 
115
  v <- reduce v
 
116
  reportSDoc "tc.conv.size" 15 $
 
117
      nest 2 $ sep [ text (show u) <+> prettyTCM cmp
 
118
                   , text (show v)
 
119
                   ]
 
120
-}
 
121
  us <- sizeMaxView u
 
122
  vs <- sizeMaxView v
 
123
  compareMaxViews cmp us vs
 
124
 
 
125
compareMaxViews :: Comparison -> SizeMaxView -> SizeMaxView -> TCM ()
 
126
compareMaxViews cmp us vs = case (cmp, us, vs) of
 
127
  (CmpLeq, _, (DSizeInf : _)) -> return ()
 
128
  (cmp,   [u], [v]) -> compareSizeViews cmp u v
 
129
  (CmpLeq, us, [v]) -> forM_ us $ \ u -> compareSizeViews cmp u v
 
130
  (CmpLeq, us, vs)  -> forM_ us $ \ u -> compareBelowMax u vs
 
131
  (CmpEq,  us, vs)  -> compareMaxViews CmpLeq us vs >> compareMaxViews CmpLeq vs us
 
132
--  _ -> typeError $ NotImplemented "compareMaxViews"
 
133
 
 
134
-- | @compareBelowMax u vs@ checks @u <= max vs@.  Precondition: @size vs >= 2@
 
135
compareBelowMax :: DeepSizeView -> SizeMaxView -> TCM ()
 
136
compareBelowMax u vs =
 
137
  alt (dontAssignMetas $ alts $ map (compareSizeViews CmpLeq u) vs) $ do
 
138
    u <- unDeepSizeView u
 
139
    v <- unMaxView vs
 
140
    size <- sizeType
 
141
    addConstraint $ ValueCmp CmpLeq size u v
 
142
  where alt  c1 c2 = c1 `catchError` const c2
 
143
        alts []     = __IMPOSSIBLE__
 
144
        alts [c]    = c
 
145
        alts (c:cs) = c `alt` alts cs
 
146
 
 
147
compareSizeViews :: Comparison -> DeepSizeView -> DeepSizeView -> TCM ()
 
148
compareSizeViews cmp s1' s2' = do
 
149
  size <- sizeType
 
150
  let (s1, s2) = removeSucs (s1', s2')
 
151
      withUnView cont = do
 
152
        u <- unDeepSizeView s1
 
153
        v <- unDeepSizeView s2
 
154
        cont u v
 
155
      failure = withUnView $ \ u v -> typeError $ UnequalTerms cmp u v size
 
156
      continue cmp = withUnView $ compareAtom cmp size
 
157
  case (cmp, s1, s2) of
 
158
    (CmpLeq, _,            DSizeInf)   -> return ()
 
159
    (CmpEq,  DSizeInf,     DSizeInf)   -> return ()
 
160
    (CmpEq,  DSizeVar{},   DSizeInf)   -> failure
 
161
    (_    ,  DSizeInf,     DSizeVar{}) -> failure
 
162
    (_    ,  DSizeInf,     _         ) -> continue CmpEq
 
163
    (CmpLeq, DSizeVar i n, DSizeVar j m) | i == j -> unless (n <= m) failure
 
164
    (CmpLeq, DSizeVar i n, DSizeVar j m) | i /= j -> do
 
165
       res <- isBounded i
 
166
       case res of
 
167
         BoundedNo -> failure
 
168
         BoundedLt u' -> do
 
169
            -- now we have i < u', in the worst case i+1 = u'
 
170
            -- and we want to check i+n <= v
 
171
            v <- unDeepSizeView s2
 
172
            if n > 0 then do
 
173
              u'' <- sizeSuc (n - 1) u'
 
174
              compareSizes cmp u'' v
 
175
             else compareSizes cmp u' =<< sizeSuc 1 v
 
176
    (CmpLeq, s1,        s2)         -> withUnView $ \ u v -> do
 
177
      unlessM (trivial u v) $ addConstraint $ ValueCmp CmpLeq size u v
 
178
    (CmpEq, s1, s2) -> continue cmp
 
179
 
 
180
{-
 
181
-- | Compare two sizes. Only with --sized-types.
 
182
compareSizes :: Comparison -> Term -> Term -> TCM ()
 
183
compareSizes cmp u v = do
 
184
  reportSDoc "tc.conv.size" 10 $ vcat
 
185
    [ text "Comparing sizes"
 
186
    , nest 2 $ sep [ prettyTCM u <+> prettyTCM cmp
 
187
                   , prettyTCM v
 
188
                   ]
 
189
    ]
 
190
  u <- reduce u
 
191
  v <- reduce v
 
192
  reportSDoc "tc.conv.size" 15 $
 
193
      nest 2 $ sep [ text (show u) <+> prettyTCM cmp
 
194
                   , text (show v)
 
195
                   ]
 
196
  s1'  <- deepSizeView u
 
197
  s2'  <- deepSizeView v
 
198
  size <- sizeType
 
199
  let failure = typeError $ UnequalTerms cmp u v size
 
200
      (s1, s2) = removeSucs (s1', s2')
 
201
      continue cmp = do
 
202
        u <- unDeepSizeView s1
 
203
        v <- unDeepSizeView s2
 
204
        compareAtom cmp size u v
 
205
  case (cmp, s1, s2) of
 
206
    (CmpLeq, _,            DSizeInf)   -> return ()
 
207
    (CmpEq,  DSizeInf,     DSizeInf)   -> return ()
 
208
    (CmpEq,  DSizeVar{},   DSizeInf)   -> failure
 
209
    (_    ,  DSizeInf,     DSizeVar{}) -> failure
 
210
    (_    ,  DSizeInf,     _         ) -> continue CmpEq
 
211
    (CmpLeq, DSizeVar i n, DSizeVar j m) | i == j -> unless (n <= m) failure
 
212
    (CmpLeq, DSizeVar i n, DSizeVar j m) | i /= j -> do
 
213
       res <- isBounded i
 
214
       case res of
 
215
         BoundedNo -> failure
 
216
         BoundedLt u' ->
 
217
            -- now we have i < u', in the worst case i+1 = u'
 
218
            -- and we want to check i+n <= v
 
219
            if n > 0 then do
 
220
              u'' <- sizeSuc (n - 1) u'
 
221
              compareSizes cmp u'' v
 
222
             else compareSizes cmp u' =<< sizeSuc 1 v
 
223
    (CmpLeq, s1,        s2)         -> do
 
224
      u <- unDeepSizeView s1
 
225
      v <- unDeepSizeView s2
 
226
      unlessM (trivial u v) $ addConstraint $ ValueCmp CmpLeq size u v
 
227
    (CmpEq, s1, s2) -> continue cmp
 
228
-}
 
229
{-
43
230
  s1   <- sizeView u
44
231
  s2   <- sizeView v
45
232
  size <- sizeType
51
237
    (_,      SizeInf,   SizeSuc v) -> compareSizes CmpEq u v
52
238
    (_,      SizeSuc u, SizeSuc v) -> compareSizes cmp u v
53
239
    (CmpLeq, _,         _)         ->
54
 
      ifM (trivial u v) (return ()) $
55
 
        addConstraint $ ValueCmp CmpLeq size u v
 
240
      unlessM (trivial u v) $ addConstraint $ ValueCmp CmpLeq size u v
56
241
    _ -> compareAtom cmp size u v
 
242
-}
 
243
 
 
244
isBounded :: Nat -> TCM BoundedSize
 
245
isBounded i = do
 
246
  t <- reduce =<< typeOfBV i
 
247
  case ignoreSharing $ unEl t of
 
248
    Def x [u] -> do
 
249
      sizelt <- getBuiltin' builtinSizeLt
 
250
      return $ if (Just (Def x []) == sizelt) then BoundedLt $ unArg u else BoundedNo
 
251
    _ -> return BoundedNo
57
252
 
58
253
trivial :: Term -> Term -> TCM Bool
59
254
trivial u v = do
60
255
    a <- sizeExpr u
61
256
    b <- sizeExpr v
 
257
    let triv = case (a, b) of
 
258
          -- Andreas, 2012-02-24  filtering out more trivial constraints fixes
 
259
          -- test/lib-succeed/SizeInconsistentMeta4.agda
 
260
          ((e, n), (e', n')) -> e == e' && n <= n'
 
261
        {-
 
262
          ((Rigid i, n), (Rigid j, m)) -> i == j && n <= m
 
263
          _ -> False
 
264
        -}
62
265
    reportSDoc "tc.conv.size" 15 $
63
 
      nest 2 $ sep [ text (show a) <+> text "<="
 
266
      nest 2 $ sep [ if triv then text "trivial constraint" else empty
 
267
                   , text (show a) <+> text "<="
64
268
                   , text (show b)
65
269
                   ]
66
 
    return $ case (a, b) of
67
 
      ((Rigid i, n), (Rigid j, m)) -> i == j && n <= m
68
 
      _ -> False
 
270
    return triv
69
271
  `catchError` \_ -> return False
70
272
 
 
273
-- | Whenever we create a bounded size meta, add a constraint
 
274
--   expressing the bound.
 
275
--   In @boundedSizeMetaHook v tel a@, @tel@ includes the current context.
 
276
boundedSizeMetaHook :: Term -> Telescope -> Type -> TCM ()
 
277
boundedSizeMetaHook v tel0 a = do
 
278
  res <- isSizeType a
 
279
  case res of
 
280
    Just (BoundedLt u) -> do
 
281
      n <- getContextSize
 
282
      let tel | n > 0     = telFromList $ genericDrop n $ telToList tel0
 
283
              | otherwise = tel0
 
284
      addCtxTel tel $ do
 
285
        v <- sizeSuc 1 $ raise (size tel) v `apply` teleArgs tel
 
286
        -- compareSizes CmpLeq v u
 
287
        size <- sizeType
 
288
        addConstraint $ ValueCmp CmpLeq size v u
 
289
    _ -> return ()
 
290
 
 
291
-- | Test whether a problem consists only of size constraints.
 
292
isSizeProblem :: ProblemId -> TCM Bool
 
293
isSizeProblem pid = andM . map (isSizeConstraint . theConstraint) =<< getConstraintsForProblem pid
 
294
 
 
295
-- | Test is a constraint speaks about sizes.
 
296
isSizeConstraint :: Closure Constraint -> TCM Bool
 
297
isSizeConstraint (Closure{ clValue = ValueCmp _ s _ _ }) = isJust <$> isSizeType s
 
298
isSizeConstraint _ = return False
 
299
 
71
300
-- | Find the size constraints.
72
 
getSizeConstraints :: TCM [SizeConstraint]
 
301
getSizeConstraints :: TCM [Closure Constraint]
73
302
getSizeConstraints = do
74
303
  cs   <- getAllConstraints
75
 
  size <- sizeType
76
 
  let sizeConstraints cl@(Closure{ clValue = ValueCmp CmpLeq s _ _ })
77
 
        | s == size = [cl]
78
 
      sizeConstraints _ = []
79
 
  scs <- mapM computeSizeConstraint $ concatMap (sizeConstraints . theConstraint) cs
80
 
  return [ c | Just c <- scs ]
 
304
  test <- isSizeTypeTest
 
305
  let sizeConstraint cl@Closure{ clValue = ValueCmp CmpLeq s _ _ }
 
306
              | isJust (test s) = Just cl
 
307
      sizeConstraint _ = Nothing
 
308
  return $ mapMaybe (sizeConstraint . theConstraint) cs
81
309
 
82
310
getSizeMetas :: TCM [(MetaId, Int)]
83
311
getSizeMetas = do
84
312
  ms <- getOpenMetas
85
 
  sz <- sizeType
 
313
  test <- isSizeTypeTest
86
314
  let sizeCon m = do
 
315
        let nothing  = return []
87
316
        mi <- lookupMeta m
88
317
        case mvJudgement mi of
89
318
          HasType _ a -> do
90
319
            TelV tel b <- telView =<< instantiateFull a
91
 
            if b /= sz
92
 
              then return []
93
 
              else return [(m, size tel)]
94
 
          _ -> return []
 
320
            case test b of
 
321
              Nothing -> nothing
 
322
              Just _  -> return [(m, size tel)]
 
323
          _ -> nothing
95
324
  concat <$> mapM sizeCon ms
96
325
 
97
 
data SizeExpr = SizeMeta MetaId [CtxId]
98
 
              | Rigid CtxId
 
326
{- ROLLED BACK
 
327
getSizeMetas :: TCM ([(MetaId, Int)], [SizeConstraint])
 
328
getSizeMetas = do
 
329
  ms <- getOpenMetas
 
330
  test <- isSizeTypeTest
 
331
  let sizeCon m = do
 
332
        let nothing  = return ([], [])
 
333
        mi <- lookupMeta m
 
334
        case mvJudgement mi of
 
335
          HasType _ a -> do
 
336
            TelV tel b <- telView =<< instantiateFull a
 
337
            let noConstr = return ([(m, size tel)], [])
 
338
            case test b of
 
339
              Nothing            -> nothing
 
340
              Just BoundedNo     -> noConstr
 
341
              Just (BoundedLt u) -> noConstr
 
342
{- WORKS NOT
 
343
              Just (BoundedLt u) -> flip catchError (const $ noConstr) $ do
 
344
                -- we assume the metavariable is used in an
 
345
                -- extension of its creation context
 
346
                ctxIds <- getContextId
 
347
                let a = SizeMeta m $ take (size tel) $ reverse ctxIds
 
348
                (b, n) <- sizeExpr u
 
349
                return ([(m, size tel)], [Leq a (n-1) b])
 
350
-}
 
351
          _ -> nothing
 
352
  (mss, css) <- unzip <$> mapM sizeCon ms
 
353
  return (concat mss, concat css)
 
354
-}
99
355
 
100
 
data SizeConstraint = Leq SizeExpr Int SizeExpr
 
356
-- | Atomic size expressions.
 
357
data SizeExpr
 
358
  = SizeMeta MetaId [Int] -- ^ A size meta applied to de Bruijn levels.
 
359
  | Rigid Int             -- ^ A de Bruijn level.
 
360
  deriving (Eq)
101
361
 
102
362
instance Show SizeExpr where
103
363
  show (SizeMeta m _) = "X" ++ show (fromIntegral m :: Int)
104
 
  show (Rigid i) = "c" ++ show (fromIntegral i :: Int)
 
364
  show (Rigid i)      = "c" ++ show i
 
365
 
 
366
-- | Size constraints we can solve.
 
367
data SizeConstraint
 
368
  = Leq SizeExpr Int SizeExpr -- ^ @Leq a +n b@ represents @a =< b + n@.
 
369
                              --   @Leq a -n b@ represents @a + n =< b@.
105
370
 
106
371
instance Show SizeConstraint where
107
372
  show (Leq a n b)
110
374
    | n > 0     = show a ++ " =< " ++ show b ++ " + " ++ show n
111
375
    | otherwise = show a ++ " + " ++ show (-n) ++ " =< " ++ show b
112
376
 
113
 
computeSizeConstraint :: Closure Constraint -> TCM (Maybe SizeConstraint)
114
 
computeSizeConstraint cl =
115
 
  enterClosure cl $ \c ->
116
 
    case c of
 
377
-- | Compute a set of size constraints that all live in the same context
 
378
--   from constraints over terms of type size that may live in different
 
379
--   contexts.
 
380
--
 
381
--   cf. 'Agda.TypeChecking.LevelConstraints.simplifyLevelConstraint'
 
382
computeSizeConstraints :: [Closure Constraint] -> TCM [SizeConstraint]
 
383
computeSizeConstraints [] = return [] -- special case to avoid maximum []
 
384
computeSizeConstraints cs = do
 
385
  scs <- mapM computeSizeConstraint leqs
 
386
  return [ c | Just c <- scs ]
 
387
  where
 
388
    -- get the constraints plus contexts they are defined in
 
389
    unClosure cl = (envContext $ clEnv cl, clValue cl)
 
390
    (gammas, ls) = unzip $ map unClosure cs
 
391
    -- compute the longest context (common water level)
 
392
    gamma        = maximumBy (compare `on` size) gammas
 
393
    waterLevel   = size gamma
 
394
    -- convert deBruijn indices to deBruijn levels to
 
395
    -- enable comparing constraints under different contexts
 
396
    leqs = zipWith raise (map ((waterLevel -) . size) gammas) ls
 
397
 
 
398
-- | Turn a constraint over de Bruijn levels into a size constraint.
 
399
computeSizeConstraint :: Constraint -> TCM (Maybe SizeConstraint)
 
400
computeSizeConstraint c = case c of
117
401
      ValueCmp CmpLeq _ u v -> do
 
402
          reportSDoc "tc.size.solve" 50 $ sep
 
403
            [ text "converting size constraint"
 
404
            , prettyTCM c
 
405
            ]
118
406
          (a, n) <- sizeExpr u
119
407
          (b, m) <- sizeExpr v
120
408
          return $ Just $ Leq a (m - n) b
121
 
        `catchError` \err -> case errError err of
 
409
        `catchError` \err -> case err of
122
410
          PatternErr _ -> return Nothing
123
411
          _            -> throwError err
124
412
      _ -> __IMPOSSIBLE__
125
413
 
 
414
-- | Turn a term with de Bruijn levels into a size expression with offset.
 
415
--
 
416
--   Throws a 'patternViolation' if the term isn't a proper size expression.
126
417
sizeExpr :: Term -> TCM (SizeExpr, Int)
127
418
sizeExpr u = do
128
419
  u <- reduce u -- Andreas, 2009-02-09.
129
420
                -- This is necessary to surface the solutions of metavariables.
 
421
  reportSDoc "tc.conv.size" 60 $ text "sizeExpr:" <+> prettyTCM u
130
422
  s <- sizeView u
131
423
  case s of
132
 
    SizeSuc u -> do
133
 
      (e, n) <- sizeExpr u
134
 
      return (e, n + 1)
135
 
    SizeInf -> patternViolation
136
 
    OtherSize u -> case u of
137
 
      Var i []  -> do
138
 
        cxt <- getContextId
139
 
        return (Rigid (cxt !! fromIntegral i), 0)
140
 
      MetaV m args
141
 
        | all isVar args && distinct args -> do
142
 
          cxt <- getContextId
143
 
          return (SizeMeta m [ cxt !! fromIntegral i | Arg _ _ (Var i []) <- args ], 0)
 
424
    SizeInf     -> patternViolation
 
425
    SizeSuc u   -> mapSnd (+1) <$> sizeExpr u
 
426
    OtherSize u -> case ignoreSharing u of
 
427
      Var i []  -> return (Rigid i, 0)  -- i is already a de Bruijn level.
 
428
      MetaV m args | Just xs <- mapM isVar args, fastDistinct xs
 
429
                -> return (SizeMeta m xs, 0)
144
430
      _ -> patternViolation
145
431
  where
146
 
    isVar (Arg _ _ (Var _ [])) = True
147
 
    isVar _ = False
 
432
    isVar v = case ignoreSharing $ unArg v of
 
433
      Var i [] -> Just i
 
434
      _        -> Nothing
148
435
 
149
 
flexibleVariables :: SizeConstraint -> [(MetaId, [CtxId])]
 
436
-- | Compute list of size metavariables with their arguments
 
437
--   appearing in a constraint.
 
438
flexibleVariables :: SizeConstraint -> [(MetaId, [Int])]
150
439
flexibleVariables (Leq a _ b) = flex a ++ flex b
151
440
  where
152
441
    flex (Rigid _)       = []
155
443
 
156
444
haveSizedTypes :: TCM Bool
157
445
haveSizedTypes = do
158
 
    Def _ [] <- primSize
159
 
    Def _ [] <- primSizeInf
160
 
    Def _ [] <- primSizeSuc
 
446
    Def _ [] <- ignoreSharing <$> primSize
 
447
    Def _ [] <- ignoreSharing <$> primSizeInf
 
448
    Def _ [] <- ignoreSharing <$> primSizeSuc
161
449
    optSizedTypes <$> pragmaOptions
162
450
  `catchError` \_ -> return False
163
451
 
 
452
-- | Convert size constraint into form where each meta is applied
 
453
--   to levels @0,1,..,n-1@ where @n@ is the arity of that meta.
 
454
--
 
455
--   @X[σ] <= t@ beomes @X[id] <= t[σ^-1]@
 
456
--
 
457
--   @X[σ] ≤ Y[τ]@ becomes @X[id] ≤ Y[τ[σ^-1]]@ or @X[σ[τ^1]] ≤ Y[id]@
 
458
--   whichever is defined.  If none is defined, we give up.
 
459
--
 
460
canonicalizeSizeConstraint :: SizeConstraint -> Maybe SizeConstraint
 
461
canonicalizeSizeConstraint c@(Leq a n b) =
 
462
  case (a,b) of
 
463
    (Rigid{}, Rigid{})       -> return c
 
464
    (SizeMeta m xs, Rigid i) -> do
 
465
      j <- findIndex (==i) xs
 
466
      return $ Leq (SizeMeta m [0..size xs-1]) n (Rigid j)
 
467
    (Rigid i, SizeMeta m xs) -> do
 
468
      j <- findIndex (==i) xs
 
469
      return $ Leq (Rigid j) n (SizeMeta m [0..size xs-1])
 
470
    (SizeMeta m xs, SizeMeta l ys)
 
471
         -- try to invert xs on ys
 
472
       | Just ys' <- mapM (\ y -> findIndex (==y) xs) ys ->
 
473
           return $ Leq (SizeMeta m [0..size xs-1]) n (SizeMeta l ys')
 
474
         -- try to invert ys on xs
 
475
       | Just xs' <- mapM (\ x -> findIndex (==x) ys) xs ->
 
476
           return $ Leq (SizeMeta m xs') n (SizeMeta l [0..size ys-1])
 
477
         -- give up
 
478
       | otherwise -> Nothing
 
479
 
164
480
solveSizeConstraints :: TCM ()
165
481
solveSizeConstraints = whenM haveSizedTypes $ do
166
 
  cs <- getSizeConstraints
 
482
  reportSLn "tc.size.solve" 70 $ "Considering to solve size constraints"
 
483
  cs0 <- getSizeConstraints
 
484
  cs <- computeSizeConstraints cs0
167
485
  ms <- getSizeMetas
 
486
{- ROLLED BACK
 
487
  cs0 <- getSizeConstraints
 
488
  cs1 <- computeSizeConstraints cs0
 
489
  (ms,cs2) <- getSizeMetas
 
490
  let cs = cs2 ++ cs1
 
491
-}
168
492
  when (not (null cs) || not (null ms)) $ do
169
493
  reportSLn "tc.size.solve" 10 $ "Solving size constraints " ++ show cs
170
494
 
171
 
  let metas0 = map mkMeta $ groupOn fst $ concatMap flexibleVariables cs
 
495
  cs <- return $ mapMaybe canonicalizeSizeConstraint cs
 
496
  reportSLn "tc.size.solve" 10 $ "Canonicalized constraints: " ++ show cs
 
497
 
 
498
  let -- Error for giving up
 
499
      cannotSolve = typeError . GenericDocError =<<
 
500
        vcat (text "Cannot solve size constraints" : map prettyTCM cs0)
 
501
 
 
502
{- OLD, before canonicalize
 
503
 
 
504
      -- Ensure that each occurrence of a meta is applied to the same
 
505
      -- arguments ("flexible variables").
 
506
      -- Andreas, 2012-10-16 this is now redundant
 
507
      mkMeta :: [(MetaId, [Int])] -> TCM (MetaId, [Int])
172
508
      mkMeta ms@((m, xs) : _)
173
 
        | allEqual (map snd ms) = (m, xs)
174
 
        | otherwise             = error $ "Inconsistent meta: " ++ show m ++ " " ++ show (map snd ms)
 
509
        | allEqual (map snd ms) = return (m, xs)
 
510
        | otherwise             = do
 
511
            reportSLn "tc.size.solve" 20 $
 
512
              "Size meta variable " ++ show m ++ " not always applied to same arguments: " ++ show (nub (map snd ms))
 
513
            cannotSolve
175
514
      mkMeta _ = __IMPOSSIBLE__
176
515
 
177
 
      mkFlex (m, xs) = W.NewFlex (fromIntegral m) $ \i -> fromIntegral i `elem` xs
 
516
  metas0 <- mapM mkMeta $ groupOn fst $ concatMap flexibleVariables cs
 
517
 
 
518
 
 
519
  let mkFlex (m, xs) = W.NewFlex (fromIntegral m) $ \i -> fromIntegral i `elem` xs
 
520
-}
 
521
 
 
522
  let metas0 :: [(MetaId, Int)]  -- meta id + arity
 
523
      metas0 = nub $ map (mapSnd length) $ concatMap flexibleVariables cs
 
524
 
 
525
      mkFlex (m, ar) = W.NewFlex (fromIntegral m) $ \i -> fromIntegral i < ar
178
526
 
179
527
      mkConstr (Leq a n b)  = W.Arc (mkNode a) n (mkNode b)
180
 
      mkNode (Rigid i)      = W.Rigid $ W.RVar $ fromIntegral i
 
528
      mkNode (Rigid i)      = W.Rigid $ W.RVar i
181
529
      mkNode (SizeMeta m _) = W.Flex $ fromIntegral m
182
530
 
183
531
      found (m, _) = elem m $ map fst metas0
184
532
 
 
533
      -- Compute unconstrained metas
 
534
      metas1 = filter (not . found) ms
 
535
 
 
536
{- OLD, before canonicalize
185
537
  -- Compute unconstrained metas
186
538
  let metas1 = map mkMeta' $ filter (not . found) ms
187
539
      mkMeta' (m, n) = (m, [0..fromIntegral n - 1])
 
540
-}
188
541
 
189
542
  let metas = metas0 ++ metas1
190
543
 
191
544
  reportSLn "tc.size.solve" 15 $ "Metas: " ++ show metas0 ++ ", " ++ show metas1
192
545
 
193
 
  verboseS "tc.size.solve" 20 $ do
194
 
    let meta (m, _) = do
195
 
          j <- mvJudgement <$> lookupMeta m
196
 
          reportSDoc "" 0 $ prettyTCM j
197
 
    mapM_ meta metas
 
546
  verboseS "tc.size.solve" 20 $
 
547
      -- debug print the type of all size metas
 
548
      forM_ metas $ \ (m, _) ->
 
549
          reportSDoc "" 0 $ prettyTCM =<< mvJudgement <$> lookupMeta m
198
550
 
 
551
  -- run the Warshall solver
199
552
  case W.solve $ map mkFlex metas ++ map mkConstr cs of
200
 
    Nothing  -> do
201
 
      typeError $ GenericError $ "Unsolvable size constraints: " ++ show cs
 
553
    Nothing  -> cannotSolve
202
554
    Just sol -> do
203
555
      reportSLn "tc.size.solve" 10 $ "Solved constraints: " ++ show sol
204
 
      inf <- primSizeInf
205
 
      s <- primSizeSuc
 
556
      s     <- primSizeSuc
 
557
      infty <- primSizeInf
206
558
      let suc v = s `apply` [defaultArg v]
207
559
          plus v 0 = v
208
560
          plus v n = suc $ plus v (n - 1)
209
561
 
210
562
          inst (i, e) = do
211
 
            let m = fromIntegral i
 
563
 
 
564
            let m = fromIntegral i  -- meta variable identifier
 
565
                ar = maybe __IMPOSSIBLE__ id $ lookup m metas  -- meta var arity
 
566
 
 
567
{- OLD
212
568
                args = case lookup m metas of
213
569
                  Just xs -> xs
214
570
                  Nothing -> __IMPOSSIBLE__
215
 
 
 
571
-}
 
572
 
 
573
                term (W.SizeConst W.Infinite) = infty
 
574
                term (W.SizeVar j n) | j < ar = plus (var $ ar - j - 1) n
 
575
                term _                        = __IMPOSSIBLE__
 
576
 
 
577
{- OLD
216
578
                term (W.SizeConst (W.Finite _)) = __IMPOSSIBLE__
217
 
                term (W.SizeConst W.Infinite) = primSizeInf
218
579
                term (W.SizeVar j n) = case findIndex (==fromIntegral j) $ reverse args of
219
 
                  Just x -> return $ plus (Var (fromIntegral x) []) n
 
580
                  Just x -> return $ plus (var x) n
220
581
                  Nothing -> __IMPOSSIBLE__
221
 
 
222
 
                lam _ v = Lam NotHidden $ Abs "s" v
223
 
 
224
 
            b <- term e
225
 
            let v = foldr lam b args -- TODO: correct hiding
 
582
-}
 
583
                lam _ v = Lam NotHidden $ Abs "s" v -- hiding does not matter
 
584
 
 
585
                -- convert size expression to term and abstract
 
586
                v = flip (foldr lam) [0..ar-1] $ term e
226
587
 
227
588
            reportSDoc "tc.size.solve" 20 $ sep
228
589
              [ text (show m) <+> text ":="
229
590
              , nest 2 $ prettyTCM v
230
591
              ]
231
592
 
232
 
            assignTerm m v
 
593
            -- Andreas, 2012-09-25: do not assign interaction metas to \infty
 
594
            let isInf (W.SizeConst W.Infinite) = True
 
595
                isInf _                        = False
 
596
            unlessM (isInteractionMeta m `and2M` return (isInf e)) $
 
597
              assignTerm m v
233
598
 
234
599
      mapM_ inst $ Map.toList sol
235
600
 
 
601
      -- Andreas, 2012-09-19
 
602
      -- The returned solution might not be consistent with
 
603
      -- the hypotheses on rigid vars (j : Size< i).
 
604
      -- Thus, we double check that all size constraints
 
605
      -- have been solved correctly.
 
606
      flip catchError (const cannotSolve) $
 
607
        noConstraints $
 
608
          forM_ cs0 $ \ cl -> enterClosure cl solveConstraint