Skip to content

Commit

Permalink
check modification time
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaszcz committed Mar 22, 2024
1 parent 2e00642 commit 3c29a26
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 17 deletions.
52 changes: 35 additions & 17 deletions src/Juvix/Compiler/Pipeline/Driver.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ where

import Data.HashMap.Strict qualified as HashMap
import Data.List.NonEmpty qualified as NonEmpty
import Data.Time
import Juvix.Compiler.Concrete (ImportCycle (ImportCycle), ScoperError (ErrImportCycle))
import Juvix.Compiler.Concrete.Data.Highlight
import Juvix.Compiler.Concrete.Language
Expand Down Expand Up @@ -201,43 +202,59 @@ processModule' (EntryIndex entry) = do
let buildDir = resolveAbsBuildDir root (entry ^. entryPointBuildDir)
relPath = fromJust $ replaceExtension ".jvo" $ fromJust $ stripProperPrefix $(mkAbsDir "/") sourcePath
absPath = buildDir Path.</> relPath
sha256 <- SHA256.digestFile sourcePath
m :: Maybe Store.ModuleInfo <- loadFromFile absPath
case m of
Just info
| info ^. Store.moduleInfoSHA256 == sha256
&& info ^. Store.moduleInfoOptions == opts
| info ^. Store.moduleInfoOptions == opts
&& info ^. Store.moduleInfoFieldSize == entry ^. entryPointFieldSize -> do
(changed, mtab) <- processImports'' entry (info ^. Store.moduleInfoImports)
-- We need to check whether any of the recursive imports is fragile,
-- not only the direct ones, because identifiers may be re-exported
-- (with `open public`).
let fragile = any (^. Store.moduleInfoFragile) (HashMap.elems $ mtab ^. Store.moduleTable)
mtime <- getModificationTime' sourcePath
if
| changed && fragile ->
recompile sha256 absPath
| otherwise ->
return (PipelineResult info mtab False)
| mtime == info ^. Store.moduleInfoModificationTime ->
reload (Just mtime) Nothing info absPath
| otherwise -> do
sha256 <- SHA256.digestFile sourcePath
if
| info ^. Store.moduleInfoSHA256 == sha256 ->
reload (Just mtime) (Just sha256) info absPath
| otherwise ->
recompile (Just mtime) (Just sha256) absPath
_ ->
recompile sha256 absPath
recompile Nothing Nothing absPath
where
root = entry ^. entryPointRoot
sourcePath = fromJust $ entry ^. entryPointModulePath
opts = StoredModule.fromEntryPoint entry

recompile :: Text -> Path Abs File -> Sem r (PipelineResult Store.ModuleInfo)
recompile sha256 absPath = do
res <- processModule'' sha256 entry
reload :: Maybe UTCTime -> Maybe Text -> Store.ModuleInfo -> Path Abs File -> Sem r (PipelineResult Store.ModuleInfo)
reload mtime msha256 info absPath = do
(changed, mtab) <- processImports'' entry (info ^. Store.moduleInfoImports)
-- We need to check whether any of the recursive imports is fragile,
-- not only the direct ones, because identifiers may be re-exported
-- (with `open public`).
let fragile = any (^. Store.moduleInfoFragile) (HashMap.elems $ mtab ^. Store.moduleTable)
if
| changed && fragile ->
-- TODO: we only need to check if the fragile modules changed, not the direct imports
recompile mtime msha256 absPath
| otherwise ->
return (PipelineResult info mtab False)

recompile :: Maybe UTCTime -> Maybe Text -> Path Abs File -> Sem r (PipelineResult Store.ModuleInfo)
recompile mtime msha256 absPath = do
time <- maybe (getModificationTime' sourcePath) return mtime
sha256 <- maybe (SHA256.digestFile sourcePath) return msha256
res <- processModule'' time sha256 entry
saveToFile absPath (res ^. pipelineResult)
return res

processModule'' ::
forall r.
(Members '[Reader ImportParents, Error JuvixError, Files, GitClone, PathResolver, MCache] r) =>
UTCTime ->
Text ->
EntryPoint ->
Sem r (PipelineResult Store.ModuleInfo)
processModule'' sha256 entry = over pipelineResult mkModuleInfo <$> processFileToStoredCore' entry
processModule'' time sha256 entry = over pipelineResult mkModuleInfo <$> processFileToStoredCore' entry
where
mkModuleInfo :: Core.CoreResult -> Store.ModuleInfo
mkModuleInfo Core.CoreResult {..} =
Expand All @@ -249,6 +266,7 @@ processModule'' sha256 entry = over pipelineResult mkModuleInfo <$> processFileT
_moduleInfoOptions = StoredOptions.fromEntryPoint entry,
_moduleInfoFragile = Core.moduleIsFragile _coreResultModule,
_moduleInfoSHA256 = sha256,
_moduleInfoModificationTime = time,
_moduleInfoFieldSize = entry ^. entryPointFieldSize
}
where
Expand Down
3 changes: 3 additions & 0 deletions src/Juvix/Compiler/Store/Language.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module Juvix.Compiler.Store.Language where

import Data.Time
import Juvix.Compiler.Concrete.Language (TopModulePath)
import Juvix.Compiler.Store.Core.Data.InfoTable qualified as Core
import Juvix.Compiler.Store.Internal.Language
Expand All @@ -12,12 +13,14 @@ data ModuleInfo = ModuleInfo
{ _moduleInfoScopedModule :: ScopedModule,
_moduleInfoInternalModule :: InternalModule,
_moduleInfoCoreTable :: Core.InfoTable,
-- | Direct imports
_moduleInfoImports :: [TopModulePath],
_moduleInfoOptions :: Options,
-- | True if any module depending on this module requires recompilation
-- whenever this module is changed
_moduleInfoFragile :: Bool,
_moduleInfoSHA256 :: Text,
_moduleInfoModificationTime :: UTCTime,
_moduleInfoFieldSize :: Natural
}
deriving stock (Generic)
Expand Down
2 changes: 2 additions & 0 deletions src/Juvix/Data/Effect/Files/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module Juvix.Data.Effect.Files.Base
)
where

import Data.Time
import Juvix.Data.Uid
import Juvix.Prelude.Base
import Juvix.Prelude.Prepath
Expand Down Expand Up @@ -41,6 +42,7 @@ data Files :: Effect where
RemoveFile' :: Path Abs File -> Files m ()
RenameFile' :: Path Abs File -> Path Abs File -> Files m ()
CopyFile' :: Path Abs File -> Path Abs File -> Files m ()
GetModificationTime' :: Path Abs File -> Files m UTCTime
JuvixConfigDir :: Files m (Path Abs Dir)
CanonicalDir :: Path Abs Dir -> Prepath Dir -> Files m (Path Abs Dir)
NormalizeDir :: Path b Dir -> Files m (Path Abs Dir)
Expand Down
1 change: 1 addition & 0 deletions src/Juvix/Data/Effect/Files/IO.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ runFilesIO = interpret helper
RemoveFile' f -> Path.removeFile f
RenameFile' p1 p2 -> Path.renameFile p1 p2
CopyFile' p1 p2 -> Path.copyFile p1 p2
GetModificationTime' p -> getModificationTime p
JuvixConfigDir -> juvixConfigDirIO
CanonicalDir root d -> prepathToAbsDir root d
NormalizeDir p -> canonicalizePath p
Expand Down
3 changes: 3 additions & 0 deletions src/Juvix/Data/Effect/Files/Pure.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module Juvix.Data.Effect.Files.Pure where

import Data.HashMap.Strict qualified as HashMap
import Data.Time
import Data.Time.Calendar.OrdinalDate
import Data.Tree
import Juvix.Data.Effect.Files.Base
import Juvix.Extra.Version
Expand Down Expand Up @@ -83,6 +85,7 @@ re cwd = interpretTop $ \case
RemoveFile' p -> removeFileHelper p
RenameFile' p1 p2 -> renameFileHelper p1 p2
CopyFile' p1 p2 -> copyFileHelper p1 p2
GetModificationTime' _ -> return $ UTCTime (fromOrdinalDate 0 0) 0
JuvixConfigDir -> return juvixConfigDirPure
CanonicalDir root d -> return (canonicalDirPure root d)
NormalizeDir p -> return (absDir (cwd' </> toFilePath p))
Expand Down
6 changes: 6 additions & 0 deletions src/Juvix/Extra/Serialize.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ where
import Data.HashMap.Strict qualified as HashMap
import Data.HashSet qualified as HashSet
import Data.Serialize as S
import Data.Time
import Data.Time.Format.ISO8601
import Juvix.Data.Effect.Files
import Juvix.Data.Effect.TaggedLock
import Juvix.Prelude.Base
Expand All @@ -26,6 +28,10 @@ instance Serialize Text where

get = pack <$> S.get

instance Serialize UTCTime where
put t = S.put (iso8601Show t)
get = S.get >>= iso8601ParseM

instance (Serialize a) => Serialize (NonEmpty a)

instance (Hashable k, Serialize k, Serialize a) => Serialize (HashMap k a) where
Expand Down

0 comments on commit 3c29a26

Please sign in to comment.