ScopeFromInterface.hs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. {-# LANGUAGE DeriveDataTypeable #-}
  2. {-# LANGUAGE FlexibleContexts #-}
  3. {-# LANGUAGE LambdaCase #-}
  4. {-# LANGUAGE ScopedTypeVariables #-}
  5. -- | Read the scope of an interface file.
  6. module Main where
  7. ------------------------------------------------------------------------------
  8. -- Haskell imports
  9. import qualified Control.Exception as E
  10. import Control.Monad.Except
  11. import qualified Data.ByteString.Lazy as BS
  12. import qualified Data.List as List
  13. import Data.Map (Map)
  14. import qualified Data.Map as Map
  15. import Data.Maybe
  16. import Data.Typeable (Typeable)
  17. import System.Environment ( getArgs )
  18. ------------------------------------------------------------------------------
  19. -- Agda library imports
  20. import Agda.Interaction.Options ( defaultOptions )
  21. import Agda.Syntax.Abstract.Name ( ModuleName )
  22. import Agda.Syntax.Scope.Base ( Scope, ScopeInfo, publicModules )
  23. import Agda.TypeChecking.Monad
  24. import Agda.TypeChecking.Serialise
  25. import Agda.TypeChecking.Serialise.Base
  26. import Agda.Utils.Functor
  27. import Agda.Utils.Hash ( Hash )
  28. import Agda.Utils.IO.Binary ( readBinaryFile' )
  29. import Agda.Utils.Null
  30. import Agda.Utils.Pretty
  31. import Agda.Utils.Impossible
  32. ------------------------------------------------------------------------------
  33. data TruncatedInterface = TruncatedInterface
  34. { tiSourceHash :: Hash
  35. -- ^ Hash of the source code.
  36. , tiImportedModules :: [(ModuleName, Hash)]
  37. -- ^ Imported modules and their hashes.
  38. , tiModuleName :: ModuleName
  39. -- ^ Module name of this interface.
  40. , tiScope :: Map ModuleName Scope
  41. -- ^ Scope defined by this module. (Not serialized.)
  42. , tiInsideScope :: ScopeInfo
  43. -- ^ Scope after we loaded this interface.
  44. } deriving (Typeable)
  45. instance EmbPrj TruncatedInterface where
  46. icod_ = __IMPOSSIBLE__
  47. value = vcase $ \case
  48. (a : b : c : d : e : _) -> valuN TruncatedInterface a b c d e
  49. _ -> __IMPOSSIBLE__
  50. ------------------------------------------------------------------------------
  51. main :: IO ()
  52. main = do
  53. _ <- liftIO . runTCMTop . mainTCM =<< getArgs
  54. return ()
  55. mainTCM :: [String] -> TCM ()
  56. mainTCM args = do
  57. setCommandLineOptions defaultOptions
  58. let f = fromMaybe "ScopeFromInterface.agdai" $ listToMaybe args
  59. readTruncatedInterface f >>= \case
  60. Just i -> processInterface i
  61. Nothing -> throwError $ Exception empty $ text "Cannot read interface file"
  62. processInterface :: TruncatedInterface -> TCM ()
  63. processInterface i = liftIO $ do
  64. -- print $ tiSourceHash i
  65. -- print $ tiImportedModules i
  66. -- print $ tiModuleName i
  67. -- print $ tiScope i
  68. -- putStrLn $ "Number of public modules: " ++ show (Map.size $ tiScope i)
  69. -- putStrLn $ render $ pretty $ tiInsideScope i
  70. -- print $ tiInsideScope i
  71. putStrLn "Imported modules:"
  72. mapM_ putStrLn $ List.sort $ map (render . pretty . fst) $ tiImportedModules i
  73. putStrLn ""
  74. -- putStrLn "Scope"
  75. forM_ (Map.toList $ tiScope i) $ \ (_m, s) -> do
  76. putStrLn $ render $ pretty s
  77. -- | Cut-and-paste from 'Agda.Interaction.Imports.readInterface'.
  78. readTruncatedInterface :: FilePath -> TCM (Maybe TruncatedInterface)
  79. readTruncatedInterface file = do
  80. -- Decode the interface file
  81. (s, close) <- liftIO $ readBinaryFile' file
  82. do mi <- liftIO . E.evaluate =<< decodeTruncatedInterface s
  83. -- Close the file. Note
  84. -- ⑴ that evaluate ensures that i is evaluated to WHNF (before
  85. -- the next IO operation is executed), and
  86. -- ⑵ that decode returns Nothing if an error is encountered,
  87. -- so it is safe to close the file here.
  88. liftIO close
  89. -- Reconstruct @iScope@.
  90. return $ mi <&> \ i -> i{ tiScope = publicModules $ tiInsideScope i }
  91. -- Catch exceptions and close
  92. `catchError` \e -> liftIO close >> handler e
  93. -- Catch exceptions
  94. `catchError` handler
  95. where
  96. handler = \case
  97. IOException _ _ e -> do
  98. reportSLn "" 0 $ "IO exception: " ++ show e
  99. return Nothing -- Work-around for file locking bug.
  100. -- TODO: What does this refer to? Please
  101. -- document.
  102. e -> throwError e
  103. -- | Cut-and-paste from 'Agda.TypeChecking.Serialize.decodeInterface'.
  104. decodeTruncatedInterface :: BS.ByteString -> TCM (Maybe TruncatedInterface)
  105. decodeTruncatedInterface s = decode $ BS.drop 16 s