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

Isabelle/HOL translation: recursive translation of the whole project #2977

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ env:
RISC0_VM_VERSION: v1.0.1
ANOMA_VERSION: f52cd44235f35a907c22c428ce1fdf3237c97927
JUST_ARGS: runtimeCcArg=$CC runtimeLibtoolArg=$LIBTOOL
STACK_BUILD_ARGS: --pedantic -j4 --ghc-options=-j
STACK_BUILD_ARGS: --pedantic -j4 --ghc-options=-j --stack-yaml=stack.yaml

jobs:
pre-commit:
Expand Down
34 changes: 26 additions & 8 deletions app/App.hs
Original file line number Diff line number Diff line change
Expand Up @@ -261,19 +261,37 @@ runPipeline opts input_ =
runPipelineLogger opts input_
. inject

runPipelineUpTo ::
(Members '[App, EmbedIO, Logger, TaggedLock] r, EntryPointOptions opts) =>
Bool ->
opts ->
Maybe (AppPath File) ->
Sem (PipelineEff r) a ->
Sem r (a, [a])
runPipelineUpTo bNonRecursive opts input_ a
| bNonRecursive = do
r <- runPipeline opts input_ a
return (r, [])
| otherwise = runPipelineUpToRecursive opts input_ a

runPipelineHtml ::
(Members '[App, EmbedIO, Logger, TaggedLock] r) =>
Bool ->
Maybe (AppPath File) ->
Sem r (InternalTypedResult, [InternalTypedResult])
runPipelineHtml bNonRecursive input_
| bNonRecursive = do
r <- runPipelineNoOptions input_ upToInternalTyped
return (r, [])
| otherwise = do
args <- askArgs
entry <- getEntryPoint' args input_
runReader defaultPipelineOptions (runPipelineHtmlEither entry) >>= fromRightJuvixError
runPipelineHtml bNonRecursive input_ = runPipelineUpTo bNonRecursive () input_ upToInternalTyped

runPipelineUpToRecursive ::
(Members '[App, EmbedIO, Logger, TaggedLock] r, EntryPointOptions opts) =>
opts ->
Maybe (AppPath File) ->
Sem (PipelineEff r) a ->
Sem r (a, [a])
runPipelineUpToRecursive opts input_ a = do
args <- askArgs
entry <- getEntryPoint' args input_
let entry' = applyOptions opts entry
runReader defaultPipelineOptions (runPipelineRecursiveEither entry' (inject a)) >>= fromRightJuvixError

runPipelineOptions :: (Members '[App] r) => Sem (Reader PipelineOptions ': r) a -> Sem r a
runPipelineOptions m = do
Expand Down
44 changes: 25 additions & 19 deletions app/Commands/Isabelle.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,28 @@ runCommand ::
Sem r ()
runCommand opts = do
let inputFile = opts ^. isabelleInputFile
res <- runPipeline opts inputFile upToIsabelle
let thy = res ^. resultTheory
comments = res ^. resultComments
outputDir <- fromAppPathDir (opts ^. isabelleOutputDir)
if
| opts ^. isabelleStdout -> do
renderStdOut (ppOutDefault comments thy)
putStrLn ""
| otherwise -> do
ensureDir outputDir
let file :: Path Rel File
file =
relFile
( unpack (thy ^. theoryName . namePretty)
<.> isabelleFileExt
)
absPath :: Path Abs File
absPath = outputDir <//> file
writeFileEnsureLn absPath (ppPrint comments thy <> "\n")
(r, rs) <- runPipelineUpTo (opts ^. isabelleNonRecursive) opts inputFile upToIsabelle
let pkg = r ^. resultModuleId . moduleIdPackage
mapM_ (translateTyped opts pkg) (r : rs)

translateTyped :: (Members AppEffects r) => IsabelleOptions -> Text -> Result -> Sem r ()
translateTyped opts pkg res
| res ^. resultModuleId . moduleIdPackage == pkg = do
let thy = res ^. resultTheory
comments = res ^. resultComments
outputDir <- fromAppPathDir (opts ^. isabelleOutputDir)
if
| opts ^. isabelleStdout ->
renderStdOutLn (ppOutDefault comments thy)
| otherwise -> do
ensureDir outputDir
let file :: Path Rel File
file =
relFile
( unpack (thy ^. theoryName . namePretty)
<.> isabelleFileExt
)
absPath :: Path Abs File
absPath = outputDir <//> file
writeFileEnsureLn absPath (ppPrint comments thy <> "\n")
| otherwise = return ()
8 changes: 7 additions & 1 deletion app/Commands/Isabelle/Options.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import CommonOptions
import Juvix.Compiler.Pipeline.EntryPoint

data IsabelleOptions = IsabelleOptions
{ _isabelleInputFile :: Maybe (AppPath File),
{ _isabelleNonRecursive :: Bool,
_isabelleInputFile :: Maybe (AppPath File),
_isabelleOutputDir :: AppPath Dir,
_isabelleStdout :: Bool,
_isabelleOnlyTypes :: Bool
Expand All @@ -15,6 +16,11 @@ makeLenses ''IsabelleOptions

parseIsabelle :: Parser IsabelleOptions
parseIsabelle = do
_isabelleNonRecursive <-
switch
( long "non-recursive"
<> help "Do not process imported modules recursively"
)
_isabelleOutputDir <-
parseGenericOutputDir
( value "isabelle"
Expand Down
10 changes: 5 additions & 5 deletions package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ author:
Lukasz Czajka,
Github's contributors,
]
tested-with: ghc == 9.8.2
tested-with: ghc == 9.10.1
homepage: https://juvix.org
bug-reports: https://github.com/anoma/juvix/issues
description: The Juvix compiler
Expand Down Expand Up @@ -52,7 +52,7 @@ dependencies:
- aeson-pretty == 0.8.*
- ansi-terminal == 1.1.*
- array == 0.5.*
- base == 4.19.*
- base == 4.20.*
- base16-bytestring == 1.0.*
- base64-bytestring == 1.2.*
- bitvec == 1.1.*
Expand All @@ -68,14 +68,14 @@ dependencies:
- edit-distance == 0.2.*
- effectful == 2.3.*
- effectful-core == 2.3.*
- effectful-th == 1.0.*
- effectful-th == 1.0.0.2
- exceptions == 0.10.*
- extra == 1.7.*
- file-embed == 0.0.*
- filelock == 0.1.*
- filepath == 1.4.*
- flatparse == 0.5.*
- ghc == 9.8.2
- ghc == 9.10.1
- githash == 0.1.*
- hashable == 1.4.*
- language-c == 0.9.*
Expand All @@ -102,7 +102,7 @@ dependencies:
- stm == 2.5.*
- Stream == 0.4.*
- string-interpolate == 0.3.*
- template-haskell == 2.21.*
- template-haskell == 2.22.*
- temporary == 1.3.*
- text == 2.1.*
- th-utilities == 0.2.*
Expand Down
2 changes: 1 addition & 1 deletion src/Juvix/Compiler/Backend/Isabelle/Pretty/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ instance PrettyCode RecordField where

ppImports :: [Name] -> Sem r [Doc Ann]
ppImports ns =
return $ map (dquotes . pretty) $ filter (not . Text.isPrefixOf "Stdlib/") $ map (Text.replace "." "/" . (^. namePretty)) ns
return $ map pretty $ filter (not . Text.isPrefixOf "Stdlib_" . (^. namePretty)) ns

instance PrettyCode Theory where
ppCode Theory {..} = do
Expand Down
73 changes: 53 additions & 20 deletions src/Juvix/Compiler/Backend/Isabelle/Translation/FromTyped.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,19 @@ fromInternal [email protected] {..} = do
goModule :: Bool -> Internal.InfoTable -> Internal.Module -> Theory
goModule onlyTypes infoTable Internal.Module {..} =
Theory
{ _theoryName = overNameText toIsabelleName _moduleName,
_theoryImports = map (^. Internal.importModuleName) (_moduleBody ^. Internal.moduleImports),
{ _theoryName = overNameText toIsabelleTheoryName _moduleName,
_theoryImports =
map
(overNameText toIsabelleTheoryName . (^. Internal.importModuleName))
(_moduleBody ^. Internal.moduleImports),
_theoryStatements = case _modulePragmas ^. pragmasIsabelleIgnore of
Just (PragmaIsabelleIgnore True) -> []
_ -> concatMap goMutualBlock (_moduleBody ^. Internal.moduleStatements)
}
where
toIsabelleName :: Text -> Text
toIsabelleName name = case reverse $ filter (/= "") $ T.splitOn "." name of
h : _ -> h
[] -> impossible
toIsabelleTheoryName :: Text -> Text
toIsabelleTheoryName name =
quote . Text.intercalate "_" $ filter (/= "") $ T.splitOn "." name

isTypeDef :: Statement -> Bool
isTypeDef = \case
Expand Down Expand Up @@ -195,8 +197,8 @@ goModule onlyTypes infoTable Internal.Module {..} =
}
where
argnames =
map (overNameText quote) $ filterTypeArgs 0 ty $ map (fromMaybe (defaultName (getLoc name) "_") . (^. Internal.argInfoName)) argsInfo
name' = overNameText quote name
map quoteName $ filterTypeArgs 0 ty $ map (fromMaybe (defaultName (getLoc name) "_") . (^. Internal.argInfoName)) argsInfo
name' = quoteName name
loc = getLoc name

isFunction :: [Name] -> Internal.Expression -> Maybe Internal.Expression -> Bool
Expand Down Expand Up @@ -376,18 +378,18 @@ goModule onlyTypes infoTable Internal.Module {..} =

goTypeIden :: Internal.Iden -> Type
goTypeIden = \case
Internal.IdenFunction name -> mkIndType (overNameText quote name) []
Internal.IdenFunction name -> mkIndType (quoteName name) []
Internal.IdenConstructor name -> error ("unsupported type: constructor " <> Internal.ppTrace name)
Internal.IdenVar name -> TyVar $ TypeVar (overNameText quote name)
Internal.IdenAxiom name -> mkIndType (overNameText quote name) []
Internal.IdenInductive name -> mkIndType (overNameText quote name) []
Internal.IdenVar name -> TyVar $ TypeVar (quoteName name)
Internal.IdenAxiom name -> mkIndType (quoteName name) []
Internal.IdenInductive name -> mkIndType (quoteName name) []

goTypeApp :: Internal.Application -> Type
goTypeApp app = mkIndType name params
where
(ind, args) = Internal.unfoldApplication app
params = map goType (toList args)
name = overNameText quote $ case ind of
name = quoteName $ case ind of
Internal.ExpressionIden (Internal.IdenFunction n) -> n
Internal.ExpressionIden (Internal.IdenAxiom n) -> n
Internal.ExpressionIden (Internal.IdenInductive n) -> n
Expand Down Expand Up @@ -416,8 +418,8 @@ goModule onlyTypes infoTable Internal.Module {..} =
setNameText "None" name
Just Internal.BuiltinMaybeJust ->
setNameText "Some" name
_ -> overNameText quote name
Nothing -> overNameText quote name
_ -> quoteName name
Nothing -> quoteName name

getArgtys :: Internal.ConstructorInfo -> [Internal.FunctionParameter]
getArgtys ctrInfo = fst $ Internal.unfoldFunType $ ctrInfo ^. Internal.constructorInfoType
Expand All @@ -430,8 +432,8 @@ goModule onlyTypes infoTable Internal.Module {..} =
Just funInfo ->
case funInfo ^. Internal.functionInfoPragmas . pragmasIsabelleFunction of
Just PragmaIsabelleFunction {..} -> setNameText _pragmaIsabelleFunctionName name
Nothing -> overNameText quote name
Nothing -> overNameText quote name
Nothing -> quoteName name
Nothing -> quoteName name
x -> x

lookupName :: forall r. (Member (Reader NameMap) r) => Name -> Sem r Expression
Expand Down Expand Up @@ -490,8 +492,8 @@ goModule onlyTypes infoTable Internal.Module {..} =
Nothing -> return $ ExprIden (goConstrName name)
Internal.IdenVar name -> do
lookupName name
Internal.IdenAxiom name -> return $ ExprIden (overNameText quote name)
Internal.IdenInductive name -> return $ ExprIden (overNameText quote name)
Internal.IdenAxiom name -> return $ ExprIden (quoteName name)
Internal.IdenInductive name -> return $ ExprIden (quoteName name)

goApplication :: Internal.Application -> Sem r Expression
goApplication [email protected] {..}
Expand Down Expand Up @@ -1217,9 +1219,40 @@ goModule onlyTypes infoTable Internal.Module {..} =
++ map (^. Internal.inductiveInfoName . namePretty) (HashMap.elems (infoTable ^. Internal.infoInductives))
++ map (^. Internal.axiomInfoDef . Internal.axiomName . namePretty) (HashMap.elems (infoTable ^. Internal.infoAxioms))

quoteName :: Name -> Name
quoteName name = overNameText goNameText name
where
goNameText :: Text -> Text
goNameText txt
| Text.elem '.' txt =
let idenName = snd $ Text.breakOnEnd "." txt
modulePath = name ^. nameId . nameIdModuleId . moduleIdPath
modulePathText = Text.intercalate "." (modulePath ^. modulePathKeyDir ++ [modulePath ^. modulePathKeyName])
moduleName' = toIsabelleTheoryName modulePathText
idenName' = quote idenName
in moduleName' <> "." <> idenName'
| otherwise = quote txt

quote :: Text -> Text
quote = quote' . Text.filter isLatin1 . Text.filter (isLetter .||. isDigit .||. (== '_') .||. (== '\''))
quote txt0
| Text.elem '.' txt0 = moduleName' <> "." <> idenName'
| otherwise = quote'' txt0
where
(moduleName, idenName) = Text.breakOnEnd "." txt0
moduleName' = toIsabelleTheoryName (removeLastDot moduleName)
idenName' = quote'' idenName

removeLastDot :: Text -> Text
removeLastDot txt
| Text.last txt == '.' = Text.init txt
| otherwise = txt

quote'' :: Text -> Text
quote'' =
quote'
. Text.filter isLatin1
. Text.filter (isLetter .||. isDigit .||. (== '_') .||. (== '\''))

quote' :: Text -> Text
quote' txt
| HashSet.member txt reservedNames = quote' (prime txt)
Expand Down
Loading
Loading