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

« back to all changes in this revision

Viewing changes to src/full/Agda/Interaction/Imports.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 #-}
 
1
{-# LANGUAGE CPP           #-}
2
2
{-# LANGUAGE TupleSections #-}
3
3
 
4
4
{-| This module deals with finding imported modules and loading their
8
8
 
9
9
import Prelude
10
10
 
11
 
import Control.Monad.Error
12
11
import Control.Monad.Reader
13
12
import Control.Monad.State
14
13
import qualified Control.Exception as E
23
22
import Data.Monoid (mempty, mappend)
24
23
import Data.Map (Map)
25
24
import Data.Set (Set)
 
25
 
26
26
import System.Directory (doesFileExist, getModificationTime, removeFile)
27
27
import System.FilePath ((</>))
28
28
 
 
29
import qualified Text.PrettyPrint.Boxes as Boxes
 
30
 
29
31
import Paths_Agda (getDataFileName)
30
32
 
31
33
import qualified Agda.Syntax.Abstract as A
40
42
import Agda.TypeChecking.Errors
41
43
import Agda.TypeChecking.Reduce
42
44
import Agda.TypeChecking.Monad
 
45
import Agda.TypeChecking.Monad.Base.KillRange  -- killRange for Signature
43
46
import Agda.TypeChecking.Serialise
 
47
import Agda.TypeChecking.Telescope
44
48
import Agda.TypeChecking.Primitive
45
49
import Agda.TypeChecking.Monad.Benchmark (billTop, reimburseTop)
46
50
import qualified Agda.TypeChecking.Monad.Benchmark as Bench
55
58
import Agda.Interaction.Highlighting.Generate
56
59
import Agda.Interaction.Highlighting.Vim
57
60
 
 
61
import Agda.Utils.Except ( MonadError(catchError, throwError) )
58
62
import Agda.Utils.FileName
 
63
import Agda.Utils.Lens
59
64
import Agda.Utils.Monad
 
65
import Agda.Utils.Null (unlessNullM)
60
66
import Agda.Utils.IO.Binary
61
67
import Agda.Utils.Pretty
62
 
import Agda.Utils.Fresh
63
68
import Agda.Utils.Time
64
69
import Agda.Utils.Hash
65
70
import qualified Agda.Utils.Trie as Trie
66
71
 
67
 
#include "../undefined.h"
 
72
#include "undefined.h"
68
73
import Agda.Utils.Impossible
69
74
 
 
75
-- | Are we loading the interface for the user-loaded file
 
76
--   or for an import?
 
77
data MainInterface
 
78
  = MainInterface     -- ^ Interface for main file.
 
79
  | NotMainInterface  -- ^ Interface for imported file.
 
80
  deriving (Eq, Show)
 
81
 
70
82
-- | Merge an interface into the current proof state.
71
83
mergeInterface :: Interface -> TCM ()
72
84
mergeInterface i = do
73
 
    let sig     = iSignature i
74
 
        builtin = Map.toList $ iBuiltin i
75
 
        prim    = [ x | (_,Prim x) <- builtin ]
76
 
        bi      = Map.fromList [ (x,Builtin t) | (x,Builtin t) <- builtin ]
 
85
    let sig     = iSignature i
 
86
        builtin = Map.toList $ iBuiltin i
 
87
        prim    = [ x | (_,Prim x) <- builtin ]
 
88
        bi      = Map.fromList [ (x,Builtin t) | (x,Builtin t) <- builtin ]
77
89
    bs <- gets stBuiltinThings
78
90
    reportSLn "import.iface.merge" 10 $ "Merging interface"
79
91
    reportSLn "import.iface.merge" 20 $
92
104
    reportSLn "import.iface.merge" 20 $
93
105
      "  Rebinding primitives " ++ show prim
94
106
    prim <- Map.fromList <$> mapM rebind prim
95
 
    modify $ \st -> st { stImportedBuiltins = stImportedBuiltins st `Map.union` prim
96
 
                       }
 
107
    stImportedBuiltins %= (`Map.union` prim)
97
108
    where
98
 
        rebind (x, q) = do
99
 
            PrimImpl _ pf <- lookupPrimitiveFunction x
100
 
            return (x, Prim $ pf { primFunName = q })
 
109
        rebind (x, q) = do
 
110
            PrimImpl _ pf <- lookupPrimitiveFunction x
 
111
            return (x, Prim $ pf { primFunName = q })
101
112
 
102
113
addImportedThings ::
103
114
  Signature -> BuiltinThings PrimFun -> Set String -> A.PatternSynDefns -> TCM ()
104
 
addImportedThings isig ibuiltin hsImports patsyns =
105
 
  modify $ \st -> st
106
 
    { stImports          = unionSignatures [stImports st, isig]
107
 
    , stImportedBuiltins = Map.union (stImportedBuiltins st) ibuiltin
108
 
    , stHaskellImports   = Set.union (stHaskellImports st) hsImports
109
 
    , stPatternSynImports = Map.union (stPatternSynImports st) patsyns
110
 
    }
 
115
addImportedThings isig ibuiltin hsImports patsyns = do
 
116
  stImports %= \imp -> unionSignatures [imp, isig]
 
117
  stImportedBuiltins %= \imp -> Map.union imp ibuiltin
 
118
  stHaskellImports %= \imp -> Set.union imp hsImports
 
119
  stPatternSynImports %= \imp -> Map.union imp patsyns
 
120
  addSignatureInstances isig
111
121
 
112
122
-- | Scope checks the given module. A proper version of the module
113
123
-- name (with correct definition sites) is returned.
144
154
    case mm of
145
155
        -- A module with warnings should never be allowed to be
146
156
        -- imported from another module.
147
 
        Just mi | not (miWarnings mi) -> do
 
157
        Just mi | not (miWarnings mi) -> do
148
158
          reportSLn "import.visit" 10 $ "  Already visited " ++ render (pretty x)
149
159
          return (miInterface mi, NoWarnings)
150
 
        _ -> do
 
160
        _ -> do
151
161
          reportSLn "import.visit" 5 $ "  Getting interface for " ++ render (pretty x)
152
162
          r@(i, wt) <- getIface
153
163
          reportSLn "import.visit" 5 $ "  Now we've looked at " ++ render (pretty x)
162
172
--   or the file passed on the command line.
163
173
--
164
174
--   First, the primitive modules are imported.
 
175
--   Then, @getInterface'@ is called to do the main work.
165
176
 
166
177
typeCheckMain :: AbsolutePath -> TCM (Interface, MaybeWarnings)
167
178
typeCheckMain f = do
186
196
          moduleName $ mkAbsolute $
187
197
            libpath </> "prim" </> "Agda" </> "Primitive.agda"
188
198
  reportSLn "import.main" 10 $ "Done importing the primitive modules."
189
 
  typeCheck f
190
 
 
191
 
--
192
 
 
193
 
typeCheck :: AbsolutePath -> TCM (Interface, MaybeWarnings)
194
 
typeCheck f = do
 
199
 
 
200
  -- Now do the type checking via getInterface.
195
201
  m <- moduleName f
196
 
  getInterface' m True
 
202
  getInterface' m MainInterface
197
203
 
 
204
-- | Tries to return the interface associated to the given (imported) module.
 
205
--   The time stamp of the relevant interface file is also returned.
 
206
--   Calls itself recursively for the imports of the given module.
 
207
--   May type check the module.
 
208
--   An error is raised if a warning is encountered.
 
209
--
 
210
--   Do not use this for the main file, use 'typeCheckMain' instead.
198
211
 
199
212
getInterface :: ModuleName -> TCM Interface
200
213
getInterface = getInterface_ . toTopLevelModuleName
201
214
 
 
215
-- | See 'getInterface'.
 
216
 
202
217
getInterface_ :: C.TopLevelModuleName -> TCM Interface
203
218
getInterface_ x = do
204
 
  (i, wt) <- getInterface' x False
 
219
  (i, wt) <- getInterface' x NotMainInterface
205
220
  case wt of
206
 
    SomeWarnings w  -> typeError $ warningsToError w
 
221
    SomeWarnings w  -> warningsToError w
207
222
    NoWarnings      -> return i
208
223
 
209
224
-- | A more precise variant of 'getInterface'. If warnings are
210
225
-- encountered then they are returned instead of being turned into
211
226
-- errors.
212
227
 
213
 
getInterface' :: C.TopLevelModuleName
214
 
              -> Bool  -- ^ If type checking is necessary, should all
215
 
                       -- state changes inflicted by 'createInterface'
216
 
                       -- be preserved?
217
 
              -> TCM (Interface, MaybeWarnings)
218
 
getInterface' x includeStateChanges =
219
 
  withIncreasedModuleNestingLevel $
 
228
getInterface'
 
229
  :: C.TopLevelModuleName
 
230
  -> MainInterface
 
231
     -- ^ If type checking is necessary,
 
232
     --   should all state changes inflicted by 'createInterface' be preserved?
 
233
  -> TCM (Interface, MaybeWarnings)
 
234
getInterface' x isMain = do
 
235
  withIncreasedModuleNestingLevel $ do
220
236
  -- Preserve the pragma options unless includeStateChanges is True.
221
 
  bracket_ (stPragmaOptions <$> get)
 
237
  bracket_ (use stPragmaOptions)
222
238
           (unless includeStateChanges . setPragmaOptions) $ do
223
239
   -- Forget the pragma options (locally).
224
 
   setCommandLineOptions . stPersistentOptions . stPersistent =<< get
 
240
   setCommandLineOptions . stPersistentOptions . stPersistentState =<< get
225
241
 
226
242
   alreadyVisited x $ addImportCycleCheck x $ do
227
243
    file <- findFile x  -- requires source to exist
251
261
      "  " ++ render (pretty x) ++ " is " ++
252
262
      (if uptodate then "" else "not ") ++ "up-to-date."
253
263
 
 
264
    -- Andreas, 2014-10-20 AIM XX:
 
265
    -- Always retype-check the main file to get the iInsideScope
 
266
    -- which is no longer serialized.
254
267
    (stateChangesIncluded, (i, wt)) <-
255
 
      if uptodate then skip file else typeCheckThe file
 
268
      if uptodate && isMain == NotMainInterface then skip file else typeCheckThe file
256
269
 
257
270
    -- Ensure that the given module name matches the one in the file.
258
271
    let topLevelName = toTopLevelModuleName $ iModuleName i
270
283
        ifTopLevelAndHighlightingLevelIs NonInteractive $
271
284
          highlightFromInterface i file
272
285
 
273
 
    modify (\s -> s { stCurrentModule = Just $ iModuleName i })
 
286
    stCurrentModule .= Just (iModuleName i)
274
287
 
275
288
    -- Interfaces are only stored if no warnings were encountered.
276
289
    case wt of
280
293
    return (i, wt)
281
294
 
282
295
    where
 
296
      includeStateChanges = isMain == MainInterface
 
297
 
283
298
      isCached file = do
284
299
        let ifile = filePath $ toIFile file
285
300
        exist <- liftIO $ doesFileExistCaseSensitive ifile
325
340
 
326
341
        -- Check that it's the right version
327
342
        case mi of
328
 
          Nothing       -> do
 
343
          Nothing       -> do
329
344
            reportSLn "import.iface" 5 $ "  bad interface, re-type checking"
330
345
            typeCheckThe file
331
 
          Just i        -> do
 
346
          Just i        -> do
332
347
 
333
348
            reportSLn "import.iface" 5 $ "  imports: " ++ show (iImportedModules i)
334
349
 
337
352
            -- If any of the imports are newer we need to retype check
338
353
            if hs /= map snd (iImportedModules i)
339
354
              then do
340
 
                -- liftIO close -- Close the interface file. See above.
 
355
                -- liftIO close -- Close the interface file. See above.
341
356
                typeCheckThe file
342
357
              else do
343
358
                unless cached $ chaseMsg "Skipping" (Just ifile)
368
383
            return (True, r)
369
384
           else do
370
385
            ms       <- getImportPath
371
 
            nesting  <- envModuleNestingLevel <$> ask
372
 
            mf       <- stModuleToSource <$> get
 
386
            nesting  <- asks envModuleNestingLevel
 
387
            range    <- asks envRange
 
388
            call     <- asks envCall
 
389
            mf       <- use stModuleToSource
373
390
            vs       <- getVisitedModules
374
391
            ds       <- getDecodedModules
375
 
            opts     <- stPersistentOptions . stPersistent <$> get
 
392
            opts     <- stPersistentOptions . stPersistentState <$> get
376
393
            isig     <- getImportedSignature
377
 
            ibuiltin <- gets stImportedBuiltins
 
394
            ibuiltin <- use stImportedBuiltins
378
395
            ipatsyns <- getPatternSynImports
379
396
            ho       <- getInteractionOutputCallback
380
397
            -- Every interface is treated in isolation. Note: Changes
386
403
            r <- freshTCM $
387
404
                   withImportPath ms $
388
405
                   local (\e -> e { envModuleNestingLevel = nesting
 
406
                                    -- Andreas, 2014-08-18:
 
407
                                    -- Preserve the range of import statement
 
408
                                    -- for reporting termination errors in
 
409
                                    -- imported modules:
 
410
                                  , envRange              = range
 
411
                                  , envCall               = call
389
412
                                  }) $ do
390
413
                     setDecodedModules ds
391
414
                     setCommandLineOptions opts
392
415
                     setInteractionOutputCallback ho
393
 
                     modify $ \s -> s { stModuleToSource     = mf
394
 
                                      }
 
416
                     stModuleToSource .= mf
395
417
                     setVisitedModules vs
396
418
                     addImportedThings isig ibuiltin Set.empty ipatsyns
397
419
 
398
420
                     r  <- withMsgs $ createInterface file x
399
 
                     mf <- stModuleToSource <$> get
 
421
                     mf <- use stModuleToSource
400
422
                     ds <- getDecodedModules
401
423
                     return (r, do
402
 
                        modify $ \s -> s { stModuleToSource = mf }
 
424
                        stModuleToSource .= mf
403
425
                        setDecodedModules ds
404
426
                        case r of
405
427
                          (i, NoWarnings) -> storeDecodedModule i
467
489
writeInterface :: FilePath -> Interface -> TCM ()
468
490
writeInterface file i = do
469
491
    reportSLn "import.iface.write" 5  $ "Writing interface file " ++ file ++ "."
 
492
    -- Andreas, Makoto, 2014-10-18 AIM XX:
 
493
    -- iInsideScope is bloating the interface files, so we do not serialize it?
 
494
    i <- return $
 
495
      i { iInsideScope  = emptyScopeInfo
 
496
        }
470
497
    encodeFile file i
471
498
    reportSLn "import.iface.write" 5 $ "Wrote interface file."
472
499
    reportSLn "import.iface.write" 50 $ "  hash = " ++ show (iFullHash i) ++ ""
490
517
  -> TCM (Interface, MaybeWarnings)
491
518
createInterface file mname =
492
519
  local (\e -> e { envCurrentPath = file }) $ do
493
 
    modFile       <- stModuleToSource <$> get
 
520
    modFile       <- use stModuleToSource
494
521
    fileTokenInfo <- billTop Bench.Highlighting $ generateTokenInfo file
495
 
    modify $ \st -> st { stTokens = fileTokenInfo }
 
522
    stTokens .= fileTokenInfo
496
523
 
497
524
    reportSLn "import.iface.create" 5 $
498
525
      "Creating interface for " ++ render (pretty mname) ++ "."
549
576
    billTop Bench.Highlighting $ do
550
577
 
551
578
      -- Move any remaining token highlighting to stSyntaxInfo.
552
 
      ifTopLevelAndHighlightingLevelIs NonInteractive $
553
 
        printHighlightingInfo . stTokens =<< get
554
 
      modify $ \st ->
555
 
        st { stTokens     = mempty
556
 
           , stSyntaxInfo = stSyntaxInfo st `mappend` stTokens st
557
 
           }
 
579
      toks <- use stTokens
 
580
      ifTopLevelAndHighlightingLevelIs NonInteractive $ printHighlightingInfo toks
 
581
      stTokens .= mempty
 
582
      stSyntaxInfo %= \inf -> inf `mappend` toks
558
583
 
559
584
      whenM (optGenerateVimFile <$> commandLineOptions) $
560
585
        -- Generate Vim file.
565
590
    reportSLn "scope.top" 50 $ "SCOPE " ++ show (insideScope topLevel)
566
591
 
567
592
    -- Serialization.
568
 
    syntaxInfo <- stSyntaxInfo <$> get
 
593
    syntaxInfo <- use stSyntaxInfo
569
594
    i <- billTop Bench.Serialization $ do
570
595
      buildInterface file topLevel syntaxInfo previousHsImports options
571
596
 
572
597
    -- TODO: It would be nice if unsolved things were highlighted
573
598
    -- after every mutual block.
574
599
 
575
 
    termErrs            <- Fold.toList <$> stTermErrs <$> get
576
600
    unsolvedMetas       <- List.nub <$> (mapM getMetaRange =<< getOpenMetas)
577
601
    unsolvedConstraints <- getAllConstraints
578
602
    interactionPoints   <- getInteractionPoints
580
604
    ifTopLevelAndHighlightingLevelIs NonInteractive $
581
605
      printUnsolvedInfo
582
606
 
583
 
    r <- if and [ null termErrs, null unsolvedMetas, null unsolvedConstraints, null interactionPoints ]
 
607
    r <- if and [ null unsolvedMetas, null unsolvedConstraints, null interactionPoints ]
584
608
     then billTop Bench.Serialization $ do
585
609
      -- The file was successfully type-checked (and no warnings were
586
610
      -- encountered), so the interface should be written out.
587
611
      let ifile = filePath $ toIFile file
588
612
      writeInterface ifile i
589
613
      return (i, NoWarnings)
590
 
     else
591
 
      return (i, SomeWarnings $ Warnings termErrs unsolvedMetas unsolvedConstraints)
 
614
     else do
 
615
      return (i, SomeWarnings $ Warnings unsolvedMetas unsolvedConstraints)
592
616
 
593
617
    -- Profiling: Print statistics.
 
618
    printStatistics 30 (Just mname) =<< getStatistics
 
619
 
 
620
    -- Get the statistics of the current module
 
621
    -- and add it to the accumulated statistics.
 
622
    localStatistics <- getStatistics
 
623
    lensAccumStatistics %= Map.unionWith (+) localStatistics
594
624
    verboseS "profile" 1 $ do
595
 
      stats <- Map.toList <$> getStatistics
596
 
      case stats of
597
 
        []      -> return ()
598
 
        _       -> reportS "profile" 1 $ unlines $
599
 
          [ "Ticks for " ++ show (pretty mname) ] ++
600
 
          [ "  " ++ s ++ " = " ++ show n
601
 
          | (s, n) <- sortBy (compare `on` snd) stats ]
 
625
      reportSLn "import.iface" 5 $ "Accumulated statistics."
602
626
 
603
627
    return r
604
628
 
623
647
    let scope = scope' { scopeCurrent = m }
624
648
    -- Andreas, 2014-05-03: killRange did not result in significant reduction
625
649
    -- of .agdai file size, and lost a few seconds performance on library-test.
626
 
    -- sig     <- killRange <$> getSignature
627
 
    sig     <- getSignature
628
 
    builtin <- gets stLocalBuiltins
 
650
    -- Andreas, Makoto, 2014-10-18 AIM XX: repeating the experiment
 
651
    -- with discarding also the nameBindingSite in QName:
 
652
    -- Saves 10% on serialization time (and file size)!
 
653
    sig     <- killRange <$> getSignature
 
654
    builtin <- use stLocalBuiltins
629
655
    ms      <- getImports
630
656
    mhs     <- mapM (\ m -> (m,) <$> moduleHash m) $ Set.toList ms
631
657
    hsImps  <- getHaskellImports
632
658
    patsyns <- getPatternSyns
633
659
    h       <- liftIO $ hashFile file
634
 
    let builtin' = Map.mapWithKey (\ x b -> (x,) . primFunName <$> b) builtin
 
660
    let builtin' = Map.mapWithKey (\ x b -> (x,) . primFunName <$> b) builtin
635
661
    reportSLn "import.iface" 7 "  instantiating all meta variables"
636
662
    i <- instantiateFull $ Interface
637
663
      { iSourceHash      = h
675
701
    newExist <- doesFileExist new
676
702
    oldExist <- doesFileExist old
677
703
    if not (newExist && oldExist)
678
 
        then return newExist
679
 
        else do
680
 
            newT <- getModificationTime new
681
 
            oldT <- getModificationTime old
682
 
            return $ newT >= oldT
 
704
        then return newExist
 
705
        else do
 
706
            newT <- getModificationTime new
 
707
            oldT <- getModificationTime old
 
708
            return $ newT >= oldT