~ubuntu-branches/ubuntu/wily/agda/wily-proposed

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Iain Lane, d5cf60f
  • Date: 2015-05-20 13:08:33 UTC
  • mfrom: (1.1.7)
  • Revision ID: package-import@ubuntu.com-20150520130833-cdcmhagwsouna237
Tags: 2.4.2.2-2
[d5cf60f] Depend on ${shlibs:Depends}, to get libc (& maybe other) deps

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
{-# LANGUAGE CPP                  #-}
 
2
{-# LANGUAGE FlexibleInstances    #-}
 
3
{-# LANGUAGE PatternGuards        #-}
 
4
{-# LANGUAGE TypeSynonymInstances #-}
 
5
 
 
6
module Agda.TypeChecking.Unquote where
 
7
 
 
8
import Control.Applicative
 
9
import Control.Monad.State (evalState, get, put)
 
10
import Control.Monad.Writer (execWriterT, tell)
 
11
import Control.Monad.Trans (lift)
 
12
 
 
13
import Data.Char
 
14
import Data.Maybe (fromMaybe)
 
15
import Data.Traversable (traverse)
 
16
 
 
17
import Agda.Syntax.Common
 
18
import Agda.Syntax.Internal as I
 
19
import Agda.Syntax.Literal
 
20
import Agda.Syntax.Position
 
21
import Agda.Syntax.Translation.InternalToAbstract
 
22
 
 
23
import Agda.TypeChecking.CompiledClause
 
24
import Agda.TypeChecking.Datatypes ( getConHead )
 
25
import Agda.TypeChecking.DropArgs
 
26
import Agda.TypeChecking.Free
 
27
import Agda.TypeChecking.Level
 
28
import Agda.TypeChecking.Monad
 
29
import Agda.TypeChecking.Monad.Builtin
 
30
import Agda.TypeChecking.Monad.Exception
 
31
import Agda.TypeChecking.Pretty
 
32
import Agda.TypeChecking.Reduce
 
33
import Agda.TypeChecking.Reduce.Monad
 
34
import Agda.TypeChecking.Substitute
 
35
 
 
36
import Agda.Utils.Except
 
37
import Agda.Utils.Impossible
 
38
import Agda.Utils.Monad ( ifM )
 
39
import Agda.Utils.Permutation ( Permutation(Perm) )
 
40
import Agda.Utils.String ( Str(Str), unStr )
 
41
import Agda.Utils.VarSet (VarSet)
 
42
import qualified Agda.Utils.VarSet as Set
 
43
 
 
44
#include "undefined.h"
 
45
 
 
46
agdaTermType :: TCM Type
 
47
agdaTermType = El (mkType 0) <$> primAgdaTerm
 
48
 
 
49
qNameType :: TCM Type
 
50
qNameType = El (mkType 0) <$> primQName
 
51
 
 
52
type UnquoteM = ExceptionT UnquoteError TCM
 
53
 
 
54
runUnquoteM :: UnquoteM a -> TCM (Either UnquoteError a)
 
55
runUnquoteM = runExceptionT
 
56
 
 
57
isCon :: ConHead -> TCM Term -> UnquoteM Bool
 
58
isCon con tm = do t <- lift tm
 
59
                  case ignoreSharing t of
 
60
                    Con con' _ -> return (con == con')
 
61
                    _ -> return False
 
62
 
 
63
{-unquoteFailedGeneric :: String -> UnquoteM a
 
64
unquoteFailedGeneric msg = typeError . GenericError $ "Unable to unquote the " ++ msg
 
65
 
 
66
unquoteFailed :: String -> String -> Term -> TCM a
 
67
unquoteFailed kind msg t = do doc <- prettyTCM t
 
68
                              unquoteFailedGeneric $ "term (" ++ show doc ++ ") of type " ++ kind ++ ".\nReason: " ++ msg ++ "."
 
69
-}
 
70
class Unquote a where
 
71
  unquote :: Term -> UnquoteM a
 
72
 
 
73
unquoteH :: Unquote a => I.Arg Term -> UnquoteM a
 
74
unquoteH a | isHidden a && isRelevant a =
 
75
    unquote $ unArg a
 
76
unquoteH a = throwException $ BadVisibility "hidden"  a
 
77
 
 
78
unquoteN :: Unquote a => I.Arg Term -> UnquoteM a
 
79
unquoteN a | notHidden a && isRelevant a =
 
80
    unquote $ unArg a
 
81
unquoteN a = throwException $ BadVisibility "visible" a
 
82
 
 
83
choice :: Monad m => [(m Bool, m a)] -> m a -> m a
 
84
choice [] dflt = dflt
 
85
choice ((mb, mx) : mxs) dflt = ifM mb mx $ choice mxs dflt
 
86
 
 
87
ensureDef :: QName -> UnquoteM QName
 
88
ensureDef x = do
 
89
  i <- (theDef <$> getConstInfo x) `catchError` \_ -> return Axiom  -- for recursive unquoteDecl
 
90
  case i of
 
91
    Constructor{} -> do
 
92
      def <- lift $ prettyTCM =<< primAgdaTermDef
 
93
      con <- lift $ prettyTCM =<< primAgdaTermCon
 
94
      throwException $ ConInsteadOfDef x (show def) (show con)
 
95
    _ -> return x
 
96
 
 
97
ensureCon :: QName -> UnquoteM QName
 
98
ensureCon x = do
 
99
  i <- (theDef <$> getConstInfo x) `catchError` \_ -> return Axiom  -- for recursive unquoteDecl
 
100
  case i of
 
101
    Constructor{} -> return x
 
102
    _ -> do
 
103
      def <- lift $ prettyTCM =<< primAgdaTermDef
 
104
      con <- lift $ prettyTCM =<< primAgdaTermCon
 
105
      throwException $ DefInsteadOfCon x (show def) (show con)
 
106
 
 
107
pickName :: Type -> String
 
108
pickName a =
 
109
  case unEl a of
 
110
    Pi{}   -> "f"
 
111
    Sort{} -> "A"
 
112
    Def d _ | c:_ <- show (qnameName d),
 
113
              isAlpha c -> [toLower c]
 
114
    _    -> "_"
 
115
 
 
116
instance Unquote I.ArgInfo where
 
117
  unquote t = do
 
118
    t <- lift $ reduce t
 
119
    case ignoreSharing t of
 
120
      Con c [h,r] -> do
 
121
        choice
 
122
          [(c `isCon` primArgArgInfo, ArgInfo <$> unquoteN h <*> unquoteN r <*> return [])]
 
123
          __IMPOSSIBLE__
 
124
      Con c _ -> __IMPOSSIBLE__
 
125
      _ -> throwException $ NotAConstructor "ArgInfo" t
 
126
 
 
127
instance Unquote a => Unquote (I.Arg a) where
 
128
  unquote t = do
 
129
    t <- lift $ reduce t
 
130
    case ignoreSharing t of
 
131
      Con c [info,x] -> do
 
132
        choice
 
133
          [(c `isCon` primArgArg, Arg <$> unquoteN info <*> unquoteN x)]
 
134
          __IMPOSSIBLE__
 
135
      Con c _ -> __IMPOSSIBLE__
 
136
      _ -> throwException $ NotAConstructor "Arg" t
 
137
 
 
138
-- Andreas, 2013-10-20: currently, post-fix projections are not part of the
 
139
-- quoted syntax.
 
140
instance Unquote a => Unquote (Elim' a) where
 
141
  unquote t = Apply <$> unquote t
 
142
 
 
143
instance Unquote Integer where
 
144
  unquote t = do
 
145
    t <- lift $ reduce t
 
146
    case ignoreSharing t of
 
147
      Lit (LitInt _ n) -> return n
 
148
      _ -> throwException $ NotALiteral "Integer" t
 
149
 
 
150
instance Unquote Double where
 
151
  unquote t = do
 
152
    t <- lift $ reduce t
 
153
    case ignoreSharing t of
 
154
      Lit (LitFloat _ x) -> return x
 
155
      _ -> throwException $ NotALiteral "Float" t
 
156
 
 
157
instance Unquote Char where
 
158
  unquote t = do
 
159
    t <- lift $ reduce t
 
160
    case ignoreSharing t of
 
161
      Lit (LitChar _ x) -> return x
 
162
      _ -> throwException $ NotALiteral "Char" t
 
163
 
 
164
instance Unquote Str where
 
165
  unquote t = do
 
166
    t <- lift $ reduce t
 
167
    case ignoreSharing t of
 
168
      Lit (LitString _ x) -> return (Str x)
 
169
      _ -> throwException $ NotALiteral "String" t
 
170
 
 
171
instance Unquote a => Unquote [a] where
 
172
  unquote t = do
 
173
    t <- lift $ reduce t
 
174
    case ignoreSharing t of
 
175
      Con c [x,xs] -> do
 
176
        choice
 
177
          [(c `isCon` primCons, (:) <$> unquoteN x <*> unquoteN xs)]
 
178
          __IMPOSSIBLE__
 
179
      Con c [] -> do
 
180
        choice
 
181
          [(c `isCon` primNil, return [])]
 
182
          __IMPOSSIBLE__
 
183
      Con c _ -> __IMPOSSIBLE__
 
184
      _ -> throwException $ NotAConstructor "List" t
 
185
 
 
186
instance Unquote Hiding where
 
187
  unquote t = do
 
188
    t <- lift $ reduce t
 
189
    case ignoreSharing t of
 
190
      Con c [] -> do
 
191
        choice
 
192
          [(c `isCon` primHidden,  return Hidden)
 
193
          ,(c `isCon` primInstance, return Instance)
 
194
          ,(c `isCon` primVisible, return NotHidden)]
 
195
          __IMPOSSIBLE__
 
196
      Con c vs -> __IMPOSSIBLE__
 
197
      _        -> throwException $ NotAConstructor "Hiding" t
 
198
 
 
199
instance Unquote Relevance where
 
200
  unquote t = do
 
201
    t <- lift $ reduce t
 
202
    case ignoreSharing t of
 
203
      Con c [] -> do
 
204
        choice
 
205
          [(c `isCon` primRelevant,   return Relevant)
 
206
          ,(c `isCon` primIrrelevant, return Irrelevant)]
 
207
          __IMPOSSIBLE__
 
208
      Con c vs -> __IMPOSSIBLE__
 
209
      _        -> throwException $ NotAConstructor "Relevance" t
 
210
 
 
211
instance Unquote QName where
 
212
  unquote t = do
 
213
    t <- lift $ reduce t
 
214
    case ignoreSharing t of
 
215
      Lit (LitQName _ x) -> return x
 
216
      _                  -> throwException $ NotALiteral "QName" t
 
217
 
 
218
instance Unquote ConHead where
 
219
  unquote t = lift . getConHead =<< ensureCon =<< unquote t
 
220
 
 
221
instance Unquote a => Unquote (Abs a) where
 
222
  unquote t = Abs "_" <$> unquote t
 
223
 
 
224
instance Unquote Sort where
 
225
  unquote t = do
 
226
    t <- lift $ reduce t
 
227
    case ignoreSharing t of
 
228
      Con c [] -> do
 
229
        choice
 
230
          [(c `isCon` primAgdaSortUnsupported, pure $ Type $ Max [Plus 0 $ UnreducedLevel $ hackReifyToMeta])]
 
231
          __IMPOSSIBLE__
 
232
      Con c [u] -> do
 
233
        choice
 
234
          [(c `isCon` primAgdaSortSet, Type <$> unquoteN u)
 
235
          ,(c `isCon` primAgdaSortLit, Type . levelMax . (:[]) . ClosedLevel <$> unquoteN u)]
 
236
          __IMPOSSIBLE__
 
237
      Con c _ -> __IMPOSSIBLE__
 
238
      _ -> throwException $ NotAConstructor "Sort" t
 
239
 
 
240
instance Unquote Level where
 
241
  unquote l = Max . (:[]) . Plus 0 . UnreducedLevel <$> unquote l
 
242
 
 
243
instance Unquote Type where
 
244
  unquote t = do
 
245
    t <- lift $ reduce t
 
246
    case ignoreSharing t of
 
247
      Con c [s, u] -> do
 
248
        choice
 
249
          [(c `isCon` primAgdaTypeEl, El <$> unquoteN s <*> unquoteN u)]
 
250
          __IMPOSSIBLE__
 
251
      Con c _ -> __IMPOSSIBLE__
 
252
      _ -> throwException $ NotAConstructor "Type" t
 
253
 
 
254
instance Unquote Literal where
 
255
  unquote t = do
 
256
    t <- lift $ reduce t
 
257
    case ignoreSharing t of
 
258
      Con c [x] ->
 
259
        choice
 
260
          [ (c `isCon` primAgdaLitNat,    LitInt    noRange <$> unquoteN x)
 
261
          , (c `isCon` primAgdaLitFloat,  LitFloat  noRange <$> unquoteN x)
 
262
          , (c `isCon` primAgdaLitChar,   LitChar   noRange <$> unquoteN x)
 
263
          , (c `isCon` primAgdaLitString, LitString noRange . unStr <$> unquoteN x)
 
264
          , (c `isCon` primAgdaLitQName,  LitQName  noRange <$> unquoteN x) ]
 
265
          __IMPOSSIBLE__
 
266
      Con c _ -> __IMPOSSIBLE__
 
267
      _ -> throwException $ NotAConstructor "Literal" t
 
268
 
 
269
instance Unquote Term where
 
270
  unquote t = do
 
271
    t <- lift $ reduce t
 
272
    case ignoreSharing t of
 
273
      Con c [] ->
 
274
        choice
 
275
          [(c `isCon` primAgdaTermUnsupported, pure hackReifyToMeta)]
 
276
          __IMPOSSIBLE__
 
277
 
 
278
      Con c [x] -> do
 
279
        choice
 
280
          [ (c `isCon` primAgdaTermSort,   Sort <$> unquoteN x)
 
281
          , (c `isCon` primAgdaTermLit,    Lit <$> unquoteN x) ]
 
282
          __IMPOSSIBLE__
 
283
 
 
284
      Con c [x, y] ->
 
285
        choice
 
286
          [ (c `isCon` primAgdaTermVar, Var <$> (fromInteger <$> unquoteN x) <*> unquoteN y)
 
287
          , (c `isCon` primAgdaTermCon, Con <$> unquoteN x <*> unquoteN y)
 
288
          , (c `isCon` primAgdaTermDef, Def <$> (ensureDef =<< unquoteN x) <*> unquoteN y)
 
289
          , (c `isCon` primAgdaTermLam, Lam <$> (flip setHiding defaultArgInfo <$> unquoteN x) <*> unquoteN y)
 
290
          , (c `isCon` primAgdaTermPi,  mkPi <$> (domFromArg <$> unquoteN x) <*> unquoteN y)
 
291
          , (c `isCon` primAgdaTermExtLam, mkExtLam <$> unquoteN x <*> unquoteN y) ]
 
292
          __IMPOSSIBLE__
 
293
        where
 
294
          mkExtLam = ExtLam
 
295
          mkPi a (Abs _ b) = Pi a (Abs x b)
 
296
            where x | 0 `freeIn` b = pickName (unDom a)
 
297
                    | otherwise    = "_"
 
298
          mkPi _ NoAbs{} = __IMPOSSIBLE__
 
299
 
 
300
      Con{} -> __IMPOSSIBLE__
 
301
      Lit{} -> __IMPOSSIBLE__
 
302
      _ -> throwException $ NotAConstructor "Term" t
 
303
 
 
304
instance Unquote Pattern where
 
305
  unquote t = do
 
306
    t <- lift $ reduce t
 
307
    case ignoreSharing t of
 
308
      Con c [] -> do
 
309
        choice
 
310
          [ (c `isCon` primAgdaPatVar,    pure (VarP "x"))
 
311
          , (c `isCon` primAgdaPatAbsurd, pure (VarP "()"))
 
312
          , (c `isCon` primAgdaPatDot,    pure (DotP hackReifyToMeta))
 
313
          ] __IMPOSSIBLE__
 
314
      Con c [x] -> do
 
315
        choice
 
316
          [ (c `isCon` primAgdaPatProj, ProjP <$> unquoteN x)
 
317
          , (c `isCon` primAgdaPatLit,  LitP  <$> unquoteN x) ]
 
318
          __IMPOSSIBLE__
 
319
      Con c [x, y] -> do
 
320
        choice
 
321
          [ (c `isCon` primAgdaPatCon, flip ConP Nothing <$> unquoteN x <*> (map (fmap unnamed) <$> unquoteN y)) ]
 
322
          __IMPOSSIBLE__
 
323
      Con c _ -> __IMPOSSIBLE__
 
324
      _ -> throwException $ NotAConstructor "Pattern" t
 
325
 
 
326
data UnquotedFunDef = UnQFun Type [Clause]
 
327
 
 
328
instance Unquote Clause where
 
329
  unquote t = do
 
330
    t <- lift $ reduce t
 
331
    case ignoreSharing t of
 
332
      Con c [x] -> do
 
333
        choice
 
334
          [ (c `isCon` primAgdaClauseAbsurd, mkClause Nothing <$> unquoteN x) ]
 
335
          __IMPOSSIBLE__
 
336
      Con c [x, y] -> do
 
337
        choice
 
338
          [ (c `isCon` primAgdaClauseClause, checkClause =<< mkClause . Just <$> unquoteN y <*> unquoteN x) ]
 
339
          __IMPOSSIBLE__
 
340
      Con c _ -> __IMPOSSIBLE__
 
341
      _ -> throwException $ NotAConstructor "Clause" t
 
342
    where
 
343
      mkClause :: Maybe Term -> [I.Arg Pattern] -> I.Clause
 
344
      mkClause b ps0 =
 
345
        Clause { clauseRange     = noRange
 
346
               , clauseTel       = dummyTel n'
 
347
               , clausePerm      = Perm n vs
 
348
               , namedClausePats = ps
 
349
               , clauseBody      = mkBody n b
 
350
               , clauseType      = Nothing }
 
351
        where
 
352
          ps = map (fmap unnamed) ps0
 
353
          n  = vars True ps  -- with dot patterns
 
354
          n' = vars False ps -- without dot patterns
 
355
          dummyTel 0 = EmptyTel
 
356
          dummyTel n = ExtendTel (defaultDom typeDontCare) (Abs "x" $ dummyTel (n - 1))
 
357
          mkBody 0 b = maybe NoBody Body b
 
358
          mkBody n b = Bind $ Abs "x" $ mkBody (n - 1) b
 
359
          vars d ps = sum $ map (vars' d . namedArg) ps
 
360
          vars' d (ConP _ _ ps) = vars d ps
 
361
          vars' d VarP{}      = 1
 
362
          vars' d DotP{}      = if d then 1 else 0
 
363
          vars' d LitP{}      = 0
 
364
          vars' d ProjP{}     = 0
 
365
 
 
366
          vs = evalState (execWriterT $ mapM_ (computePerm . namedArg) ps) 0
 
367
          next = do n <- get; put (n + 1); return n
 
368
 
 
369
          computePerm (ConP _ _ ps) = mapM_ (computePerm . namedArg) ps
 
370
          computePerm VarP{}        = tell . (:[]) =<< next
 
371
          computePerm DotP{}        = () <$ next
 
372
          computePerm LitP{}        = return ()
 
373
          computePerm ProjP{}       = return ()
 
374
 
 
375
      checkClause :: I.Clause -> UnquoteM I.Clause
 
376
      checkClause cl@Clause{ clausePerm = Perm n vs , clauseBody = body } = do
 
377
        let freevs    = allVars $ freeVars $ fromMaybe __IMPOSSIBLE__ $ getBody body
 
378
            propervs  = Set.fromList $ map ((n-1)-) vs
 
379
            dottedvs  = Set.difference (Set.fromList [0..n-1]) propervs
 
380
            offending = Set.intersection freevs dottedvs
 
381
        Agda.TypeChecking.Monad.reportSDoc "tc.unquote.clause.dotvars" 30 $ vcat
 
382
          [ text $ "checkClause "
 
383
          , nest 2 $ text $ "free vars:      " ++ show freevs
 
384
          , nest 2 $ text $ "dotted vars:    " ++ show dottedvs
 
385
          , nest 2 $ text $ "offending vars: " ++ show offending
 
386
          ]
 
387
        if Set.null offending
 
388
          then return cl
 
389
          else throwException $ RhsUsesDottedVar (Set.toList offending) t
 
390
 
 
391
instance Unquote UnquotedFunDef where
 
392
  unquote t = do
 
393
    t <- lift $ reduce t
 
394
    case ignoreSharing t of
 
395
      Con c [x, y] -> do
 
396
        choice
 
397
          [ (c `isCon` primAgdaFunDefCon, UnQFun <$> unquoteN x <*> unquoteN y) ]
 
398
          __IMPOSSIBLE__
 
399
      Con c _ -> __IMPOSSIBLE__
 
400
      _ -> throwException $ NotAConstructor "Pattern" t
 
401
 
 
402
reifyUnquoted :: Reify a e => a -> TCM e
 
403
reifyUnquoted = nowReifyingUnquoted . disableDisplayForms . withShowAllArguments . reify