Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cryptol Projects #1526

Merged
merged 35 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
50b313b
Name main modules using their file path
qsctr Jun 7, 2023
6c2e2ff
Disallow parameterized main modules
qsctr Jun 7, 2023
b83bffa
Slightly modify main module name formatting
qsctr Jun 7, 2023
4a47230
Tweak unnamed module naming again
qsctr Jun 8, 2023
d581f12
Update tests for Main module name change
qsctr Jun 8, 2023
0b11877
Implement project config file, loading all modules
qsctr Jun 15, 2023
2191f4d
Revert "Update tests for Main module name change"
qsctr Jun 21, 2023
33826df
Name parameterized main modules in tests
qsctr Jun 21, 2023
8ada88a
Change displayed name of main modules back to Main
qsctr Jun 21, 2023
6a376ab
Projects: Add caching for loading modules
qsctr Jul 12, 2023
6d58175
Projects: Switch to HsYAML for config file parsing
qsctr Jul 19, 2023
ccfc450
This should be just refactoring and comments.
yav Feb 13, 2024
141e60b
fixup test results
glguy Nov 1, 2024
136cf54
More refactoring.
yav Feb 13, 2024
0a3e69d
Comments and wibbles
yav Feb 13, 2024
40305d0
Read cache file strictly, otherwise we can't overwrite it.
yav Feb 13, 2024
9431d4d
Ignore `.` and `..`
yav Feb 13, 2024
73ddf4d
Move printing to monad
yav Feb 13, 2024
088fa60
Add a function for catching errors.
yav Feb 13, 2024
5093908
Simplify things a bit.
yav Feb 27, 2024
55a76f9
Project load with docstrings checkpoint
glguy Nov 22, 2024
423c3df
Cache docstring results
glguy Dec 17, 2024
e1538d9
update mtl version bound
glguy Dec 17, 2024
1cd50c3
update json rendering to include fingerprints
glguy Dec 17, 2024
8a68c08
backport tryError
glguy Dec 17, 2024
13ff72a
restore mtl version for the recent GHCs
glguy Dec 17, 2024
67a4d29
fixup errors
glguy Dec 18, 2024
233168c
Nicer error printing
glguy Dec 18, 2024
ecfdd4c
Add flag to explicitly refresh the project
glguy Dec 19, 2024
dd7dbf5
update fingerprint in test case
glguy Dec 19, 2024
6f296d2
Add project structure documentation
glguy Dec 19, 2024
7f4c6c0
test fixup
glguy Dec 20, 2024
37addd3
test fixes
glguy Dec 20, 2024
c9719a5
incorporate project documentation info refman
glguy Dec 20, 2024
a49bcf5
changelog entry
glguy Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
* The REPL properly supports tab completion for the `:t` and `:check` commands.
([#1780](https://github.com/GaloisInc/cryptol/issues/1780))

* Add support for incrementally loading projects via cryptol's `--project`
flag as documented in the reference manual.
([#1641](https://github.com/GaloisInc/cryptol/issues/1641))

# 3.2.0 -- 2024-08-20

## Language changes
Expand Down
2 changes: 1 addition & 1 deletion cryptol-remote-api/python/tests/cryptol/test_filedeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def test_FileDeps(self) -> None:
connect(verify=False)
path = str(Path('tests','cryptol','test-files','Id.cry'))
result = file_deps(path,True)
self.assertEqual(result['fingerprint'],"8A49C6A461AF276DF56C4FE4279BCFC51D891214")
self.assertEqual(result['fingerprint'],"8316fb4e38d33ec3b9f89d355597c058b2e4baf653bf18dc4ead7e166a8a32f8")
self.assertEqual(result['foreign'],[])
self.assertEqual(result['imports'],['Cryptol'])
self.assertEqual(result['includes'],[])
Expand Down
2 changes: 1 addition & 1 deletion cryptol-remote-api/src/CryptolServer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,6 @@ validateServerState =
InMem{} -> continue
InFile file ->
do fp <- fingerprintFile file
if fp == Just (fiFingerprint (lmFileInfo lm))
if fp == Right (fiFingerprint (lmFileInfo lm))
then continue
else return False
6 changes: 4 additions & 2 deletions cryptol-remote-api/src/CryptolServer/Exceptions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,19 @@ cryptolError modErr warns =
CantFindFile path ->
(20050, [ ("path", jsonString path)
])
BadUtf8 path ue ->
BadUtf8 path fp ue ->
(20010, [ ("path", jsonShow path)
, ("error", jsonShow ue)
, ("fingerprint", jsonShow fp)
])
OtherIOError path exn ->
(20060, [ ("path", jsonString path)
, ("error", jsonShow exn)
])
ModuleParseError source message ->
ModuleParseError source fp message ->
(20540, [ ("source", jsonShow source)
, ("error", jsonShow message)
, ("fingerprint", jsonShow fp)
])
RecursiveModules mods ->
(20550, [ ("modules", jsonList (reverse (map jsonPretty mods)))
Expand Down
3 changes: 2 additions & 1 deletion cryptol-remote-api/src/CryptolServer/FileDeps.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module CryptolServer.FileDeps
import Data.Text (Text)
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.Map.Strict as Map

import qualified Data.Aeson as JSON
import Data.Aeson (FromJSON(..),ToJSON(..),(.=),(.:))
Expand Down Expand Up @@ -67,7 +68,7 @@ instance ToJSON FileDeps where
InFile f -> toJSON f
InMem l _ -> JSON.object [ "internal" .= l ]
, "fingerprint" .= fingerprintHexString (fiFingerprint fi)
, "includes" .= Set.toList (fiIncludeDeps fi)
, "includes" .= Map.keys (fiIncludeDeps fi)
, "imports" .= map (show . pp) (Set.toList (fiImportDeps fi))
, "foreign" .= Map.toList (fiForeignDeps fi)
]
Expand Down
30 changes: 21 additions & 9 deletions cryptol-repl-internal/REPL/Haskeline.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

module REPL.Haskeline where

import qualified Cryptol.Project as Project
import Cryptol.REPL.Command
import Cryptol.REPL.Monad
import Cryptol.REPL.Trie
Expand Down Expand Up @@ -131,22 +132,33 @@ loadCryRC cryrc =
else return status

-- | Haskeline-specific repl implementation.
repl :: Cryptolrc -> ReplMode -> Bool -> Bool -> REPL () -> IO CommandResult
repl cryrc replMode callStacks stopOnError begin =
repl ::
Cryptolrc ->
Maybe Project.Config ->
Bool {- ^ refresh project -} ->
ReplMode -> Bool -> Bool -> REPL () -> IO CommandResult
repl cryrc projectConfig projectRefresh replMode callStacks stopOnError begin =
runREPL isBatch callStacks stdoutLogger replAction

where
-- this flag is used to suppress the logo and prompts
isBatch = case replMode of
InteractiveRepl -> False
Batch _ -> True
InteractiveBatch _ -> True
isBatch =
case projectConfig of
Just _ -> True
Nothing ->
case replMode of
InteractiveRepl -> False
Batch _ -> True
InteractiveBatch _ -> True

replAction =
do status <- loadCryRC cryrc
if crSuccess status
then begin >> crySession replMode stopOnError
else return status
if crSuccess status then do
begin
case projectConfig of
Just config -> loadProjectREPL projectRefresh config
Nothing -> crySession replMode stopOnError
else return status

-- | Try to set the history file.
setHistoryFile :: Settings REPL -> IO (Settings REPL)
Expand Down
11 changes: 9 additions & 2 deletions cryptol.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ library
array >= 0.4,
containers >= 0.5,
criterion-measurement,
cryptohash-sha1 >= 0.11 && < 0.12,
cryptohash-sha256 >= 0.11 && < 0.12,
deepseq >= 1.3,
directory >= 1.2.2.0,
exceptions,
Expand All @@ -63,6 +63,7 @@ library
gitrev >= 1.0,
ghc-prim,
GraphSCC >= 1.0.4,
heredoc >= 0.2,
language-c99,
language-c99-simple,
libBF >= 0.6 && < 0.7,
Expand All @@ -80,6 +81,7 @@ library
strict,
text >= 1.1,
tf-random >= 0.5,
toml-parser >= 2.0 && <2.1,
transformers-base >= 0.4,
vector,
mtl >= 2.2.1,
Expand Down Expand Up @@ -238,7 +240,12 @@ library
Cryptol.REPL.Help,
Cryptol.REPL.Browse,
Cryptol.REPL.Monad,
Cryptol.REPL.Trie
Cryptol.REPL.Trie,

Cryptol.Project
Cryptol.Project.Config
Cryptol.Project.Monad
Cryptol.Project.Cache

Other-modules: Cryptol.Parser.LexerUtils,
Cryptol.Parser.ParserUtils,
Expand Down
87 changes: 66 additions & 21 deletions cryptol/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

{-# LANGUAGE CPP #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where

Expand All @@ -18,6 +19,7 @@ import Cryptol.REPL.Monad (REPL,updateREPLTitle,setUpdateREPLTitle,
io,prependSearchPath,setSearchPath,parseSearchPath)
import qualified Cryptol.REPL.Monad as REPL
import Cryptol.ModuleSystem.Env(ModulePath(..))
import qualified Cryptol.Project as Project

import REPL.Haskeline
import REPL.Logo
Expand All @@ -26,6 +28,7 @@ import Cryptol.Utils.PP
import Cryptol.Version (displayVersion)

import Control.Monad (when, void)
import Data.Maybe (isJust, isNothing)
import GHC.IO.Encoding (setLocaleEncoding, utf8)
import System.Console.GetOpt
(OptDescr(..),ArgOrder(..),ArgDescr(..),getOpt,usageInfo)
Expand All @@ -47,6 +50,8 @@ data Options = Options
, optVersion :: Bool
, optHelp :: Bool
, optBatch :: ReplMode
, optProject :: Maybe FilePath
, optProjectRefresh :: Bool
, optCallStacks :: Bool
, optCommands :: [String]
, optColorMode :: ColorMode
Expand All @@ -62,6 +67,8 @@ defaultOptions = Options
, optVersion = False
, optHelp = False
, optBatch = InteractiveRepl
, optProject = Nothing
, optProjectRefresh = False
, optCallStacks = True
, optCommands = []
, optColorMode = AutoColor
Expand All @@ -79,6 +86,13 @@ options =
, Option "" ["interactive-batch"] (ReqArg setInteractiveBatchScript "FILE")
"run the script provided and exit, but behave as if running an interactive session"

, Option "p" ["project"] (ReqArg setProject "CRYPROJECT")
("Load and verify a Cryptol project using the provided project "
++ "configuration file or directory containing 'cryproject.toml'")

, Option "" ["refresh-project"] (NoArg setProjectRefresh)
"Ignore a pre-existing cache file when loading a project."

, Option "e" ["stop-on-error"] (NoArg setStopOnError)
"stop script execution as soon as an error occurs."

Expand Down Expand Up @@ -137,6 +151,12 @@ setBatchScript path = modify $ \ opts -> opts { optBatch = Batch path }
setInteractiveBatchScript :: String -> OptParser Options
setInteractiveBatchScript path = modify $ \ opts -> opts { optBatch = InteractiveBatch path }

setProject :: String -> OptParser Options
setProject path = modify $ \opts -> opts { optProject = Just path }

setProjectRefresh :: OptParser Options
setProjectRefresh = modify $ \opts -> opts { optProjectRefresh = True }

-- | Set the color mode of the terminal output.
setColorMode :: String -> OptParser Options
setColorMode "auto" = modify $ \ opts -> opts { optColorMode = AutoColor }
Expand Down Expand Up @@ -225,11 +245,14 @@ main = do
| optVersion opts -> displayVersion putStrLn
| otherwise -> do
(opts', mCleanup) <- setupCmdScript opts
status <- repl (optCryptolrc opts')
(optBatch opts')
(optCallStacks opts')
(optStopOnError opts')
(setupREPL opts')
(opts'', mConfig) <- setupProject opts'
status <- repl (optCryptolrc opts'')
mConfig
(optProjectRefresh opts'')
(optBatch opts'')
(optCallStacks opts'')
(optStopOnError opts'')
(setupREPL opts'')
case mCleanup of
Nothing -> return ()
Just cmdFile -> removeFile cmdFile
Expand All @@ -249,7 +272,27 @@ setupCmdScript opts =
hClose h
when (optBatch opts /= InteractiveRepl) $
putStrLn "[warning] --command argument specified; ignoring batch file"
return (opts { optBatch = InteractiveBatch path }, Just path)
when (isJust (optProject opts)) $
putStrLn $
"[warning] --command argument specified; "
++ "ignoring project configuration file"
return
( opts { optBatch = InteractiveBatch path, optProject = Nothing }
, Just path )

setupProject :: Options -> IO (Options, Maybe Project.Config)
setupProject opts =
case optProject opts of
Nothing -> pure (opts, Nothing)
Just path -> do
when (optBatch opts /= InteractiveRepl) $
putStrLn "[warning] --project argument specified; ignoring batch file"
Project.loadConfig path >>= \case
Left err -> do
print $ pp err
exitFailure
Right config ->
pure (opts { optBatch = InteractiveRepl }, Just config)

setupREPL :: Options -> REPL ()
setupREPL opts = do
Expand Down Expand Up @@ -281,18 +324,20 @@ setupREPL opts = do
Batch file -> prependSearchPath [ takeDirectory file ]
_ -> return ()

case optLoad opts of
[] -> loadPrelude `REPL.catch` \x -> io $ print $ pp x
[l] -> void (loadCmd l) `REPL.catch` \x -> do
io $ print $ pp x
-- If the requested file fails to load, load the prelude instead...
loadPrelude `REPL.catch` \y -> do
io $ print $ pp y
-- ... but make sure the loaded module is set to the file
-- we tried, instead of the Prelude
REPL.setEditPath l
REPL.setLoadedMod REPL.LoadedModule
{ REPL.lFocus = Nothing
, REPL.lPath = InFile l
}
_ -> io $ putStrLn "Only one file may be loaded at the command line."
when (isNothing (optProject opts)) $
case optLoad opts of
[] -> loadPrelude `REPL.catch` \x -> io $ print $ pp x
[l] -> void (loadCmd l) `REPL.catch` \x -> do
io $ print $ pp x
-- If the requested file fails to load,
-- load the prelude instead...
loadPrelude `REPL.catch` \y -> do
io $ print $ pp y
-- ... but make sure the loaded module is set to the file
-- we tried, instead of the Prelude
REPL.setEditPath l
REPL.setLoadedMod REPL.LoadedModule
{ REPL.lFocus = Nothing
, REPL.lPath = InFile l
}
_ -> io $ putStrLn "Only one file may be loaded at the command line."
Loading
Loading