mirror of
https://github.com/anoma/juvix.git
synced 2024-09-11 16:26:33 +03:00
JuvixReg to CASM translation (#2671)
* Closes #2562 Checklist --------- - [x] Translation from JuvixReg to CASM - [x] CASM runtime - [x] Juvix to CASM pipeline: combine the right transformations and check prerequisites - [x] CLI commands: add target `casm` to the `compile` commands - [x] Tests: - [x] Test the translation from JuvixReg to CASM - [x] Test the entire pipeline from Juvix to CASM
This commit is contained in:
parent
b615fde186
commit
0f713c7c84
@ -29,6 +29,7 @@ runCommand opts@CompileOptions {..} = do
|
|||||||
TargetReg -> Compile.runRegPipeline arg
|
TargetReg -> Compile.runRegPipeline arg
|
||||||
TargetNockma -> Compile.runNockmaPipeline arg
|
TargetNockma -> Compile.runNockmaPipeline arg
|
||||||
TargetAnoma -> Compile.runAnomaPipeline arg
|
TargetAnoma -> Compile.runAnomaPipeline arg
|
||||||
|
TargetCasm -> Compile.runCasmPipeline arg
|
||||||
|
|
||||||
writeCoreFile :: (Members '[EmbedIO, App, TaggedLock] r) => Compile.PipelineArg -> Sem r ()
|
writeCoreFile :: (Members '[EmbedIO, App, TaggedLock] r) => Compile.PipelineArg -> Sem r ()
|
||||||
writeCoreFile pa@Compile.PipelineArg {..} = do
|
writeCoreFile pa@Compile.PipelineArg {..} = do
|
||||||
|
@ -6,7 +6,10 @@ import Commands.Extra.Compile qualified as Compile
|
|||||||
import Juvix.Compiler.Asm.Translation.FromSource qualified as Asm
|
import Juvix.Compiler.Asm.Translation.FromSource qualified as Asm
|
||||||
import Juvix.Compiler.Backend qualified as Backend
|
import Juvix.Compiler.Backend qualified as Backend
|
||||||
import Juvix.Compiler.Backend.C qualified as C
|
import Juvix.Compiler.Backend.C qualified as C
|
||||||
|
import Juvix.Compiler.Casm.Data.Result qualified as Casm
|
||||||
|
import Juvix.Compiler.Casm.Pretty qualified as Casm
|
||||||
import Juvix.Compiler.Reg.Pretty qualified as Reg
|
import Juvix.Compiler.Reg.Pretty qualified as Reg
|
||||||
|
import Juvix.Prelude.Pretty
|
||||||
|
|
||||||
runCommand :: forall r. (Members '[EmbedIO, App, TaggedLock] r) => AsmCompileOptions -> Sem r ()
|
runCommand :: forall r. (Members '[EmbedIO, App, TaggedLock] r) => AsmCompileOptions -> Sem r ()
|
||||||
runCommand opts = do
|
runCommand opts = do
|
||||||
@ -34,6 +37,15 @@ runCommand opts = do
|
|||||||
tab' <- getRight r
|
tab' <- getRight r
|
||||||
let code = Reg.ppPrint tab' tab'
|
let code = Reg.ppPrint tab' tab'
|
||||||
writeFileEnsureLn regFile code
|
writeFileEnsureLn regFile code
|
||||||
|
TargetCasm -> do
|
||||||
|
casmFile <- Compile.outputFile opts file
|
||||||
|
r <-
|
||||||
|
runReader entryPoint
|
||||||
|
. runError @JuvixError
|
||||||
|
. asmToCasm
|
||||||
|
$ tab
|
||||||
|
Casm.Result {..} <- getRight r
|
||||||
|
writeFileEnsureLn casmFile (toPlainText $ Casm.ppProgram _resultCode)
|
||||||
_ ->
|
_ ->
|
||||||
case run $ runReader entryPoint $ runError $ asmToMiniC tab of
|
case run $ runReader entryPoint $ runError $ asmToMiniC tab of
|
||||||
Left err -> exitJuvixError err
|
Left err -> exitJuvixError err
|
||||||
@ -57,6 +69,7 @@ runCommand opts = do
|
|||||||
TargetWasm32Wasi -> return Backend.TargetCWasm32Wasi
|
TargetWasm32Wasi -> return Backend.TargetCWasm32Wasi
|
||||||
TargetNative64 -> return Backend.TargetCNative64
|
TargetNative64 -> return Backend.TargetCNative64
|
||||||
TargetReg -> return Backend.TargetReg
|
TargetReg -> return Backend.TargetReg
|
||||||
|
TargetCasm -> return Backend.TargetCairo
|
||||||
TargetNockma -> err "Nockma"
|
TargetNockma -> err "Nockma"
|
||||||
TargetAnoma -> err "Anoma"
|
TargetAnoma -> err "Anoma"
|
||||||
TargetTree -> err "JuvixTree"
|
TargetTree -> err "JuvixTree"
|
||||||
|
@ -15,7 +15,8 @@ asmSupportedTargets =
|
|||||||
NonEmpty.fromList
|
NonEmpty.fromList
|
||||||
[ TargetWasm32Wasi,
|
[ TargetWasm32Wasi,
|
||||||
TargetNative64,
|
TargetNative64,
|
||||||
TargetReg
|
TargetReg,
|
||||||
|
TargetCasm
|
||||||
]
|
]
|
||||||
|
|
||||||
parseAsmCompileOptions :: Parser AsmCompileOptions
|
parseAsmCompileOptions :: Parser AsmCompileOptions
|
||||||
|
@ -23,6 +23,7 @@ runCommand opts = do
|
|||||||
TargetTree -> runTreePipeline arg
|
TargetTree -> runTreePipeline arg
|
||||||
TargetNockma -> runNockmaPipeline arg
|
TargetNockma -> runNockmaPipeline arg
|
||||||
TargetAnoma -> runAnomaPipeline arg
|
TargetAnoma -> runAnomaPipeline arg
|
||||||
|
TargetCasm -> runCasmPipeline arg
|
||||||
where
|
where
|
||||||
getFile :: Sem r (Path Abs File)
|
getFile :: Sem r (Path Abs File)
|
||||||
getFile = getMainFile (opts ^. compileInputFile)
|
getFile = getMainFile (opts ^. compileInputFile)
|
||||||
|
@ -8,11 +8,14 @@ import Juvix.Compiler.Backend qualified as Backend
|
|||||||
import Juvix.Compiler.Backend.C qualified as C
|
import Juvix.Compiler.Backend.C qualified as C
|
||||||
import Juvix.Compiler.Backend.Geb qualified as Geb
|
import Juvix.Compiler.Backend.Geb qualified as Geb
|
||||||
import Juvix.Compiler.Backend.VampIR.Translation qualified as VampIR
|
import Juvix.Compiler.Backend.VampIR.Translation qualified as VampIR
|
||||||
|
import Juvix.Compiler.Casm.Data.Result qualified as Casm
|
||||||
|
import Juvix.Compiler.Casm.Pretty qualified as Casm
|
||||||
import Juvix.Compiler.Core.Data.Module qualified as Core
|
import Juvix.Compiler.Core.Data.Module qualified as Core
|
||||||
import Juvix.Compiler.Core.Data.TransformationId qualified as Core
|
import Juvix.Compiler.Core.Data.TransformationId qualified as Core
|
||||||
import Juvix.Compiler.Nockma.Pretty qualified as Nockma
|
import Juvix.Compiler.Nockma.Pretty qualified as Nockma
|
||||||
import Juvix.Compiler.Reg.Pretty qualified as Reg
|
import Juvix.Compiler.Reg.Pretty qualified as Reg
|
||||||
import Juvix.Compiler.Tree.Pretty qualified as Tree
|
import Juvix.Compiler.Tree.Pretty qualified as Tree
|
||||||
|
import Juvix.Prelude.Pretty
|
||||||
import System.FilePath (takeBaseName)
|
import System.FilePath (takeBaseName)
|
||||||
|
|
||||||
data PipelineArg = PipelineArg
|
data PipelineArg = PipelineArg
|
||||||
@ -45,6 +48,7 @@ getEntry PipelineArg {..} = do
|
|||||||
TargetTree -> Backend.TargetTree
|
TargetTree -> Backend.TargetTree
|
||||||
TargetNockma -> Backend.TargetNockma
|
TargetNockma -> Backend.TargetNockma
|
||||||
TargetAnoma -> Backend.TargetAnoma
|
TargetAnoma -> Backend.TargetAnoma
|
||||||
|
TargetCasm -> Backend.TargetCairo
|
||||||
|
|
||||||
defaultOptLevel :: Int
|
defaultOptLevel :: Int
|
||||||
defaultOptLevel
|
defaultOptLevel
|
||||||
@ -168,3 +172,15 @@ runAnomaPipeline pa@PipelineArg {..} = do
|
|||||||
tab' <- getRight r
|
tab' <- getRight r
|
||||||
let code = Nockma.ppSerialize tab'
|
let code = Nockma.ppSerialize tab'
|
||||||
writeFileEnsureLn nockmaFile code
|
writeFileEnsureLn nockmaFile code
|
||||||
|
|
||||||
|
runCasmPipeline :: (Members '[Embed IO, App, TaggedLock] r) => PipelineArg -> Sem r ()
|
||||||
|
runCasmPipeline pa@PipelineArg {..} = do
|
||||||
|
entryPoint <- getEntry pa
|
||||||
|
casmFile <- Compile.outputFile _pipelineArgOptions _pipelineArgFile
|
||||||
|
r <-
|
||||||
|
runReader entryPoint
|
||||||
|
. runError @JuvixError
|
||||||
|
. coreToCasm
|
||||||
|
$ _pipelineArgModule
|
||||||
|
Casm.Result {..} <- getRight r
|
||||||
|
writeFileEnsureLn casmFile (toPlainText $ Casm.ppProgram _resultCode)
|
||||||
|
@ -19,7 +19,8 @@ coreSupportedTargets =
|
|||||||
TargetVampIR,
|
TargetVampIR,
|
||||||
TargetTree,
|
TargetTree,
|
||||||
TargetAsm,
|
TargetAsm,
|
||||||
TargetReg
|
TargetReg,
|
||||||
|
TargetCasm
|
||||||
]
|
]
|
||||||
|
|
||||||
parseCoreCompileOptions :: Parser CoreCompileOptions
|
parseCoreCompileOptions :: Parser CoreCompileOptions
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
module Commands.Dev.Reg where
|
module Commands.Dev.Reg where
|
||||||
|
|
||||||
import Commands.Base
|
import Commands.Base
|
||||||
|
import Commands.Dev.Reg.Compile as Compile
|
||||||
import Commands.Dev.Reg.Options
|
import Commands.Dev.Reg.Options
|
||||||
import Commands.Dev.Reg.Read as Read
|
import Commands.Dev.Reg.Read as Read
|
||||||
import Commands.Dev.Reg.Run as Run
|
import Commands.Dev.Reg.Run as Run
|
||||||
|
|
||||||
runCommand :: forall r. (Members '[EmbedIO, App, TaggedLock] r) => RegCommand -> Sem r ()
|
runCommand :: forall r. (Members '[EmbedIO, App, TaggedLock] r) => RegCommand -> Sem r ()
|
||||||
runCommand = \case
|
runCommand = \case
|
||||||
|
Compile opts -> Compile.runCommand opts
|
||||||
Run opts -> Run.runCommand opts
|
Run opts -> Run.runCommand opts
|
||||||
Read opts -> Read.runCommand opts
|
Read opts -> Read.runCommand opts
|
||||||
|
79
app/Commands/Dev/Reg/Compile.hs
Normal file
79
app/Commands/Dev/Reg/Compile.hs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
module Commands.Dev.Reg.Compile where
|
||||||
|
|
||||||
|
import Commands.Base
|
||||||
|
import Commands.Dev.Reg.Compile.Options
|
||||||
|
import Commands.Extra.Compile qualified as Compile
|
||||||
|
import Juvix.Compiler.Backend qualified as Backend
|
||||||
|
import Juvix.Compiler.Backend.C qualified as C
|
||||||
|
import Juvix.Compiler.Casm.Data.Result qualified as Casm
|
||||||
|
import Juvix.Compiler.Casm.Pretty qualified as Casm
|
||||||
|
import Juvix.Compiler.Reg.Translation.FromSource qualified as Reg
|
||||||
|
import Juvix.Prelude.Pretty
|
||||||
|
|
||||||
|
runCommand :: forall r. (Members '[EmbedIO, App, TaggedLock] r) => CompileOptions -> Sem r ()
|
||||||
|
runCommand opts = do
|
||||||
|
file <- getFile
|
||||||
|
s <- readFile file
|
||||||
|
case Reg.runParser file s of
|
||||||
|
Left err -> exitJuvixError (JuvixError err)
|
||||||
|
Right tab -> do
|
||||||
|
ep <- getEntryPoint (AppPath (preFileFromAbs file) True)
|
||||||
|
tgt <- getTarget (opts ^. compileTarget)
|
||||||
|
let entryPoint :: EntryPoint
|
||||||
|
entryPoint =
|
||||||
|
ep
|
||||||
|
{ _entryPointTarget = tgt,
|
||||||
|
_entryPointDebug = opts ^. compileDebug
|
||||||
|
}
|
||||||
|
case opts ^. compileTarget of
|
||||||
|
TargetCasm -> do
|
||||||
|
casmFile <- Compile.outputFile opts file
|
||||||
|
r <-
|
||||||
|
runReader entryPoint
|
||||||
|
. runError @JuvixError
|
||||||
|
. regToCasm
|
||||||
|
$ tab
|
||||||
|
Casm.Result {..} <- getRight r
|
||||||
|
writeFileEnsureLn casmFile (toPlainText $ Casm.ppProgram _resultCode)
|
||||||
|
_ ->
|
||||||
|
case run $ runReader entryPoint $ runError $ regToMiniC tab of
|
||||||
|
Left err -> exitJuvixError err
|
||||||
|
Right C.MiniCResult {..} -> do
|
||||||
|
buildDir <- askBuildDir
|
||||||
|
ensureDir buildDir
|
||||||
|
cFile <- inputCFile file
|
||||||
|
writeFileEnsureLn cFile _resultCCode
|
||||||
|
outfile <- Compile.outputFile opts file
|
||||||
|
Compile.runCommand
|
||||||
|
opts
|
||||||
|
{ _compileInputFile = Just (AppPath (preFileFromAbs cFile) False),
|
||||||
|
_compileOutputFile = Just (AppPath (preFileFromAbs outfile) False)
|
||||||
|
}
|
||||||
|
where
|
||||||
|
getFile :: Sem r (Path Abs File)
|
||||||
|
getFile = getMainFile (opts ^. compileInputFile)
|
||||||
|
|
||||||
|
getTarget :: CompileTarget -> Sem r Backend.Target
|
||||||
|
getTarget = \case
|
||||||
|
TargetWasm32Wasi -> return Backend.TargetCWasm32Wasi
|
||||||
|
TargetNative64 -> return Backend.TargetCNative64
|
||||||
|
TargetCasm -> return Backend.TargetCairo
|
||||||
|
TargetReg -> err "JuvixReg"
|
||||||
|
TargetNockma -> err "Nockma"
|
||||||
|
TargetAnoma -> err "Anoma"
|
||||||
|
TargetTree -> err "JuvixTree"
|
||||||
|
TargetGeb -> err "GEB"
|
||||||
|
TargetVampIR -> err "VampIR"
|
||||||
|
TargetCore -> err "JuvixCore"
|
||||||
|
TargetAsm -> err "JuvixAsm"
|
||||||
|
where
|
||||||
|
err :: Text -> Sem r a
|
||||||
|
err tgt = exitMsg (ExitFailure 1) ("error: " <> tgt <> " target not supported for JuvixReg")
|
||||||
|
|
||||||
|
inputCFile :: (Members '[App] r) => Path Abs File -> Sem r (Path Abs File)
|
||||||
|
inputCFile inputFileCompile = do
|
||||||
|
buildDir <- askBuildDir
|
||||||
|
return (buildDir <//> outputMiniCFile)
|
||||||
|
where
|
||||||
|
outputMiniCFile :: Path Rel File
|
||||||
|
outputMiniCFile = replaceExtension' ".c" (filename inputFileCompile)
|
23
app/Commands/Dev/Reg/Compile/Options.hs
Normal file
23
app/Commands/Dev/Reg/Compile/Options.hs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
module Commands.Dev.Reg.Compile.Options
|
||||||
|
( module Commands.Dev.Reg.Compile.Options,
|
||||||
|
module Commands.Extra.Compile.Options,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Commands.Extra.Compile.Options
|
||||||
|
import CommonOptions
|
||||||
|
import Data.List.NonEmpty qualified as NonEmpty
|
||||||
|
|
||||||
|
regSupportedTargets :: NonEmpty CompileTarget
|
||||||
|
regSupportedTargets =
|
||||||
|
NonEmpty.fromList
|
||||||
|
[ TargetWasm32Wasi,
|
||||||
|
TargetNative64,
|
||||||
|
TargetCasm
|
||||||
|
]
|
||||||
|
|
||||||
|
parseRegCompileOptions :: Parser CompileOptions
|
||||||
|
parseRegCompileOptions =
|
||||||
|
parseCompileOptions
|
||||||
|
regSupportedTargets
|
||||||
|
(parseInputFile FileExtJuvixReg)
|
@ -1,11 +1,13 @@
|
|||||||
module Commands.Dev.Reg.Options where
|
module Commands.Dev.Reg.Options where
|
||||||
|
|
||||||
|
import Commands.Dev.Reg.Compile.Options
|
||||||
import Commands.Dev.Reg.Read.Options
|
import Commands.Dev.Reg.Read.Options
|
||||||
import Commands.Dev.Reg.Run.Options
|
import Commands.Dev.Reg.Run.Options
|
||||||
import CommonOptions
|
import CommonOptions
|
||||||
|
|
||||||
data RegCommand
|
data RegCommand
|
||||||
= Run RegRunOptions
|
= Compile CompileOptions
|
||||||
|
| Run RegRunOptions
|
||||||
| Read RegReadOptions
|
| Read RegReadOptions
|
||||||
deriving stock (Data)
|
deriving stock (Data)
|
||||||
|
|
||||||
@ -13,16 +15,26 @@ parseRegCommand :: Parser RegCommand
|
|||||||
parseRegCommand =
|
parseRegCommand =
|
||||||
hsubparser $
|
hsubparser $
|
||||||
mconcat
|
mconcat
|
||||||
[ commandRun,
|
[ commandCompile,
|
||||||
|
commandRun,
|
||||||
commandRead
|
commandRead
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
|
commandCompile :: Mod CommandFields RegCommand
|
||||||
|
commandCompile = command "compile" compileInfo
|
||||||
|
|
||||||
commandRun :: Mod CommandFields RegCommand
|
commandRun :: Mod CommandFields RegCommand
|
||||||
commandRun = command "run" runInfo
|
commandRun = command "run" runInfo
|
||||||
|
|
||||||
commandRead :: Mod CommandFields RegCommand
|
commandRead :: Mod CommandFields RegCommand
|
||||||
commandRead = command "read" readInfo
|
commandRead = command "read" readInfo
|
||||||
|
|
||||||
|
compileInfo :: ParserInfo RegCommand
|
||||||
|
compileInfo =
|
||||||
|
info
|
||||||
|
(Compile <$> parseRegCompileOptions)
|
||||||
|
(progDesc "Compile a JuvixReg file")
|
||||||
|
|
||||||
runInfo :: ParserInfo RegCommand
|
runInfo :: ParserInfo RegCommand
|
||||||
runInfo =
|
runInfo =
|
||||||
info
|
info
|
||||||
|
@ -22,6 +22,7 @@ runCommand opts = do
|
|||||||
TargetTree -> return ()
|
TargetTree -> return ()
|
||||||
TargetNockma -> runNockmaPipeline arg
|
TargetNockma -> runNockmaPipeline arg
|
||||||
TargetAnoma -> runAnomaPipeline arg
|
TargetAnoma -> runAnomaPipeline arg
|
||||||
|
TargetCasm -> runCasmPipeline arg
|
||||||
where
|
where
|
||||||
getFile :: Sem r (Path Abs File)
|
getFile :: Sem r (Path Abs File)
|
||||||
getFile = getMainFile (opts ^. compileInputFile)
|
getFile = getMainFile (opts ^. compileInputFile)
|
||||||
|
@ -6,9 +6,12 @@ import Commands.Extra.Compile qualified as Compile
|
|||||||
import Juvix.Compiler.Asm.Pretty qualified as Asm
|
import Juvix.Compiler.Asm.Pretty qualified as Asm
|
||||||
import Juvix.Compiler.Backend qualified as Backend
|
import Juvix.Compiler.Backend qualified as Backend
|
||||||
import Juvix.Compiler.Backend.C qualified as C
|
import Juvix.Compiler.Backend.C qualified as C
|
||||||
|
import Juvix.Compiler.Casm.Data.Result qualified as Casm
|
||||||
|
import Juvix.Compiler.Casm.Pretty qualified as Casm
|
||||||
import Juvix.Compiler.Nockma.Pretty qualified as Nockma
|
import Juvix.Compiler.Nockma.Pretty qualified as Nockma
|
||||||
import Juvix.Compiler.Reg.Pretty qualified as Reg
|
import Juvix.Compiler.Reg.Pretty qualified as Reg
|
||||||
import Juvix.Compiler.Tree.Data.InfoTable qualified as Tree
|
import Juvix.Compiler.Tree.Data.InfoTable qualified as Tree
|
||||||
|
import Juvix.Prelude.Pretty
|
||||||
|
|
||||||
data PipelineArg = PipelineArg
|
data PipelineArg = PipelineArg
|
||||||
{ _pipelineArgOptions :: CompileOptions,
|
{ _pipelineArgOptions :: CompileOptions,
|
||||||
@ -40,6 +43,7 @@ getEntry PipelineArg {..} = do
|
|||||||
TargetTree -> Backend.TargetTree
|
TargetTree -> Backend.TargetTree
|
||||||
TargetNockma -> Backend.TargetNockma
|
TargetNockma -> Backend.TargetNockma
|
||||||
TargetAnoma -> Backend.TargetAnoma
|
TargetAnoma -> Backend.TargetAnoma
|
||||||
|
TargetCasm -> Backend.TargetCairo
|
||||||
|
|
||||||
defaultOptLevel :: Int
|
defaultOptLevel :: Int
|
||||||
defaultOptLevel
|
defaultOptLevel
|
||||||
@ -125,3 +129,15 @@ runAnomaPipeline pa@PipelineArg {..} = do
|
|||||||
tab' <- getRight r
|
tab' <- getRight r
|
||||||
let code = Nockma.ppSerialize tab'
|
let code = Nockma.ppSerialize tab'
|
||||||
writeFileEnsureLn nockmaFile code
|
writeFileEnsureLn nockmaFile code
|
||||||
|
|
||||||
|
runCasmPipeline :: (Members '[Embed IO, App, TaggedLock] r) => PipelineArg -> Sem r ()
|
||||||
|
runCasmPipeline pa@PipelineArg {..} = do
|
||||||
|
entryPoint <- getEntry pa
|
||||||
|
casmFile <- Compile.outputFile _pipelineArgOptions _pipelineArgFile
|
||||||
|
r <-
|
||||||
|
runReader entryPoint
|
||||||
|
. runError @JuvixError
|
||||||
|
. treeToCasm
|
||||||
|
$ _pipelineArgTable
|
||||||
|
Casm.Result {..} <- getRight r
|
||||||
|
writeFileEnsureLn casmFile (toPlainText $ Casm.ppProgram _resultCode)
|
||||||
|
@ -14,7 +14,8 @@ treeSupportedTargets =
|
|||||||
TargetNative64,
|
TargetNative64,
|
||||||
TargetAsm,
|
TargetAsm,
|
||||||
TargetReg,
|
TargetReg,
|
||||||
TargetNockma
|
TargetNockma,
|
||||||
|
TargetCasm
|
||||||
]
|
]
|
||||||
|
|
||||||
parseTreeCompileOptions :: Parser CompileOptions
|
parseTreeCompileOptions :: Parser CompileOptions
|
||||||
|
@ -37,6 +37,7 @@ runCompile inputFile o = do
|
|||||||
TargetTree -> return (Right ())
|
TargetTree -> return (Right ())
|
||||||
TargetNockma -> return (Right ())
|
TargetNockma -> return (Right ())
|
||||||
TargetAnoma -> return (Right ())
|
TargetAnoma -> return (Right ())
|
||||||
|
TargetCasm -> return (Right ())
|
||||||
|
|
||||||
prepareRuntime :: forall r. (Members '[App, EmbedIO] r) => Path Abs Dir -> CompileOptions -> Sem r ()
|
prepareRuntime :: forall r. (Members '[App, EmbedIO] r) => Path Abs Dir -> CompileOptions -> Sem r ()
|
||||||
prepareRuntime buildDir o = do
|
prepareRuntime buildDir o = do
|
||||||
@ -56,6 +57,7 @@ prepareRuntime buildDir o = do
|
|||||||
TargetTree -> return ()
|
TargetTree -> return ()
|
||||||
TargetNockma -> return ()
|
TargetNockma -> return ()
|
||||||
TargetAnoma -> return ()
|
TargetAnoma -> return ()
|
||||||
|
TargetCasm -> return ()
|
||||||
where
|
where
|
||||||
wasiReleaseRuntime :: BS.ByteString
|
wasiReleaseRuntime :: BS.ByteString
|
||||||
wasiReleaseRuntime = $(FE.makeRelativeToProject "runtime/_build.wasm32-wasi/libjuvix.a" >>= FE.embedFile)
|
wasiReleaseRuntime = $(FE.makeRelativeToProject "runtime/_build.wasm32-wasi/libjuvix.a" >>= FE.embedFile)
|
||||||
@ -121,6 +123,8 @@ outputFile opts inputFile =
|
|||||||
replaceExtension' nockmaFileExt baseOutputFile
|
replaceExtension' nockmaFileExt baseOutputFile
|
||||||
TargetAnoma ->
|
TargetAnoma ->
|
||||||
replaceExtension' nockmaFileExt baseOutputFile
|
replaceExtension' nockmaFileExt baseOutputFile
|
||||||
|
TargetCasm ->
|
||||||
|
replaceExtension' casmFileExt baseOutputFile
|
||||||
|
|
||||||
clangNativeCompile ::
|
clangNativeCompile ::
|
||||||
forall r.
|
forall r.
|
||||||
|
@ -15,6 +15,7 @@ data CompileTarget
|
|||||||
| TargetTree
|
| TargetTree
|
||||||
| TargetNockma
|
| TargetNockma
|
||||||
| TargetAnoma
|
| TargetAnoma
|
||||||
|
| TargetCasm
|
||||||
deriving stock (Eq, Data, Bounded, Enum)
|
deriving stock (Eq, Data, Bounded, Enum)
|
||||||
|
|
||||||
instance Show CompileTarget where
|
instance Show CompileTarget where
|
||||||
@ -29,6 +30,7 @@ instance Show CompileTarget where
|
|||||||
TargetTree -> "tree"
|
TargetTree -> "tree"
|
||||||
TargetNockma -> "nockma"
|
TargetNockma -> "nockma"
|
||||||
TargetAnoma -> "anoma"
|
TargetAnoma -> "anoma"
|
||||||
|
TargetCasm -> "casm"
|
||||||
|
|
||||||
data CompileOptions = CompileOptions
|
data CompileOptions = CompileOptions
|
||||||
{ _compileDebug :: Bool,
|
{ _compileDebug :: Bool,
|
||||||
|
@ -11,8 +11,9 @@ function count_ext () {
|
|||||||
RUNTIME_C=$(count runtime/src/juvix)
|
RUNTIME_C=$(count runtime/src/juvix)
|
||||||
RUNTIME_VAMPIR=$(count_ext '*.pir' runtime/src/vampir)
|
RUNTIME_VAMPIR=$(count_ext '*.pir' runtime/src/vampir)
|
||||||
RUNTIME_JVT=$(count_ext '*.jvt' runtime/src/tree)
|
RUNTIME_JVT=$(count_ext '*.jvt' runtime/src/tree)
|
||||||
|
RUNTIME_CASM=$(count_ext '*.casm' runtime/src/casm)
|
||||||
|
|
||||||
RUNTIME=$((RUNTIME_C+RUNTIME_VAMPIR+RUNTIME_JVT))
|
RUNTIME=$((RUNTIME_C+RUNTIME_VAMPIR+RUNTIME_JVT+RUNTIME_CASM))
|
||||||
|
|
||||||
BACKENDC=$(count src/Juvix/Compiler/Backend/C/)
|
BACKENDC=$(count src/Juvix/Compiler/Backend/C/)
|
||||||
CAIRO=$(count src/Juvix/Compiler/Backend/Cairo/)
|
CAIRO=$(count src/Juvix/Compiler/Backend/Cairo/)
|
||||||
@ -62,6 +63,7 @@ echo " JuvixCore: $CORE LOC"
|
|||||||
echo "Runtime: $RUNTIME LOC"
|
echo "Runtime: $RUNTIME LOC"
|
||||||
echo " C runtime: $RUNTIME_C LOC"
|
echo " C runtime: $RUNTIME_C LOC"
|
||||||
echo " JuvixTree runtime: $RUNTIME_JVT LOC"
|
echo " JuvixTree runtime: $RUNTIME_JVT LOC"
|
||||||
|
echo " Cairo assembly runtime: $RUNTIME_CASM LOC"
|
||||||
echo " VampIR runtime: $RUNTIME_VAMPIR LOC"
|
echo " VampIR runtime: $RUNTIME_VAMPIR LOC"
|
||||||
echo "Other: $OTHER LOC"
|
echo "Other: $OTHER LOC"
|
||||||
echo " Application: $APP LOC"
|
echo " Application: $APP LOC"
|
||||||
@ -72,4 +74,4 @@ echo " Data: $DATA LOC"
|
|||||||
echo " Prelude: $PRELUDE LOC"
|
echo " Prelude: $PRELUDE LOC"
|
||||||
echo "Tests: $TESTS LOC"
|
echo "Tests: $TESTS LOC"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Total: $TOTAL Haskell LOC + $RUNTIME_C C LOC + $RUNTIME_JVT JuvixTree LOC + $RUNTIME_VAMPIR VampIR LOC"
|
echo "Total: $TOTAL Haskell LOC + $RUNTIME_C C LOC + $RUNTIME_JVT JuvixTree LOC + $RUNTIME_CASM CASM LOC + $RUNTIME_VAMPIR VampIR LOC"
|
||||||
|
@ -40,6 +40,7 @@ extra-source-files:
|
|||||||
- runtime/**/*.a
|
- runtime/**/*.a
|
||||||
- runtime/src/tree/*.jvt
|
- runtime/src/tree/*.jvt
|
||||||
- runtime/src/vampir/*.pir
|
- runtime/src/vampir/*.pir
|
||||||
|
- runtime/src/casm/*.casm
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- aeson-better-errors == 0.9.*
|
- aeson-better-errors == 0.9.*
|
||||||
|
99
runtime/src/casm/stdlib.casm
Normal file
99
runtime/src/casm/stdlib.casm
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
-- Juvix runtime for Cairo assembly
|
||||||
|
|
||||||
|
-- Closure layout: [ addr | 9 - sargs | 9 - argsnum | arguments... ]
|
||||||
|
-- sargs -- number of arguments stored in the closure
|
||||||
|
-- argsnum -- number of arguments left
|
||||||
|
-- sargs + argsnum = total numer of arguments for the function
|
||||||
|
-- Maximum number of function arguments: 8
|
||||||
|
|
||||||
|
-- after calling juvix_get_regs:
|
||||||
|
-- [ap - 4] == fp
|
||||||
|
-- [ap - 3] == pc
|
||||||
|
-- [ap - 2] == ap - 2
|
||||||
|
juvix_get_regs:
|
||||||
|
call juvix_get_ap_reg
|
||||||
|
ret
|
||||||
|
juvix_get_ap_reg:
|
||||||
|
ret
|
||||||
|
|
||||||
|
-- [fp - 3]: closure; [fp - 3 - k]: argument k to closure call
|
||||||
|
juvix_call_closure:
|
||||||
|
ap += 1
|
||||||
|
-- closure addr
|
||||||
|
[fp] = [[fp - 3]]
|
||||||
|
-- jmp rel (9 - argsnum)
|
||||||
|
jmp rel [[fp - 3] + 2]
|
||||||
|
[ap] = [fp - 11]; ap++
|
||||||
|
[ap] = [fp - 10]; ap++
|
||||||
|
[ap] = [fp - 9]; ap++
|
||||||
|
[ap] = [fp - 8]; ap++
|
||||||
|
[ap] = [fp - 7]; ap++
|
||||||
|
[ap] = [fp - 6]; ap++
|
||||||
|
[ap] = [fp - 5]; ap++
|
||||||
|
[ap] = [fp - 4]; ap++
|
||||||
|
-- jmp rel (9 - sargs)
|
||||||
|
jmp rel [[fp - 3] + 1]
|
||||||
|
[ap] = [[fp - 3] + 10]; ap++
|
||||||
|
[ap] = [[fp - 3] + 9]; ap++
|
||||||
|
[ap] = [[fp - 3] + 8]; ap++
|
||||||
|
[ap] = [[fp - 3] + 7]; ap++
|
||||||
|
[ap] = [[fp - 3] + 6]; ap++
|
||||||
|
[ap] = [[fp - 3] + 5]; ap++
|
||||||
|
[ap] = [[fp - 3] + 4]; ap++
|
||||||
|
[ap] = [[fp - 3] + 3]; ap++
|
||||||
|
call [fp]
|
||||||
|
ret
|
||||||
|
|
||||||
|
-- [fp - 3]: closure
|
||||||
|
-- [fp - 4]: n = the number of arguments to extend with
|
||||||
|
-- [fp - 4 - k]: argument n - k - 1 (reverse order!)
|
||||||
|
juvix_extend_closure:
|
||||||
|
ap += 6
|
||||||
|
-- 9 - sargs
|
||||||
|
[fp + 1] = [[fp - 3] + 1]
|
||||||
|
-- 9 - argsnum (expected)
|
||||||
|
[fp + 2] = [[fp - 3] + 2]
|
||||||
|
[fp + 3] = 9
|
||||||
|
-- [fp + 4] = sargs
|
||||||
|
[fp + 4] = [fp + 3] - [fp + 1]
|
||||||
|
-- [fp + 5] = 9 - n
|
||||||
|
[fp + 5] = [fp + 3] - [fp - 4]
|
||||||
|
-- copy stored args reversing them
|
||||||
|
jmp rel [fp + 1]
|
||||||
|
[ap] = [[fp - 3] + 10]; ap++
|
||||||
|
[ap] = [[fp - 3] + 9]; ap++
|
||||||
|
[ap] = [[fp - 3] + 8]; ap++
|
||||||
|
[ap] = [[fp - 3] + 7]; ap++
|
||||||
|
[ap] = [[fp - 3] + 6]; ap++
|
||||||
|
[ap] = [[fp - 3] + 5]; ap++
|
||||||
|
[ap] = [[fp - 3] + 4]; ap++
|
||||||
|
[ap] = [[fp - 3] + 3]; ap++
|
||||||
|
call juvix_get_regs
|
||||||
|
[fp] = [ap - 2] + 2
|
||||||
|
-- closure header
|
||||||
|
[ap] = [[fp - 3]]; ap++
|
||||||
|
[ap] = [fp + 1] - [fp - 4]; ap++
|
||||||
|
[ap] = [fp + 2] + [fp - 4]; ap++
|
||||||
|
-- copy stored args: jmp rel (9 - sargs)
|
||||||
|
jmp rel [fp + 1]
|
||||||
|
[ap] = [fp + 13]; ap++
|
||||||
|
[ap] = [fp + 12]; ap++
|
||||||
|
[ap] = [fp + 11]; ap++
|
||||||
|
[ap] = [fp + 10]; ap++
|
||||||
|
[ap] = [fp + 9]; ap++
|
||||||
|
[ap] = [fp + 8]; ap++
|
||||||
|
[ap] = [fp + 7]; ap++
|
||||||
|
[ap] = [fp + 6]; ap++
|
||||||
|
-- copy extra args: jmp rel (9 - extra args num)
|
||||||
|
jmp rel [fp + 5]
|
||||||
|
[ap] = [fp - 12]; ap++
|
||||||
|
[ap] = [fp - 11]; ap++
|
||||||
|
[ap] = [fp - 10]; ap++
|
||||||
|
[ap] = [fp - 9]; ap++
|
||||||
|
[ap] = [fp - 8]; ap++
|
||||||
|
[ap] = [fp - 7]; ap++
|
||||||
|
[ap] = [fp - 6]; ap++
|
||||||
|
[ap] = [fp - 5]; ap++
|
||||||
|
-- return value
|
||||||
|
[ap] = [fp]; ap++
|
||||||
|
ret
|
@ -156,18 +156,9 @@ runCodeR infoTable funInfo = goCode (funInfo ^. functionCode) >> popLastValueSta
|
|||||||
goUnop :: (Member Runtime r) => (Val -> Either Text Val) -> Sem r ()
|
goUnop :: (Member Runtime r) => (Val -> Either Text Val) -> Sem r ()
|
||||||
goUnop op = goUnop' (eitherToError . op)
|
goUnop op = goUnop' (eitherToError . op)
|
||||||
|
|
||||||
getConstantVal :: Constant -> Val
|
|
||||||
getConstantVal = \case
|
|
||||||
ConstInt i -> ValInteger i
|
|
||||||
ConstField f -> ValField f
|
|
||||||
ConstBool b -> ValBool b
|
|
||||||
ConstString s -> ValString s
|
|
||||||
ConstUnit -> ValUnit
|
|
||||||
ConstVoid -> ValVoid
|
|
||||||
|
|
||||||
getVal :: (Member Runtime r) => Value -> Sem r Val
|
getVal :: (Member Runtime r) => Value -> Sem r Val
|
||||||
getVal = \case
|
getVal = \case
|
||||||
Constant c -> return (getConstantVal c)
|
Constant c -> return (constantToValue c)
|
||||||
Ref r -> getMemVal r
|
Ref r -> getMemVal r
|
||||||
|
|
||||||
getMemVal :: forall r. (Member Runtime r) => MemRef -> Sem r Val
|
getMemVal :: forall r. (Member Runtime r) => MemRef -> Sem r Val
|
||||||
|
@ -14,6 +14,7 @@ data Target
|
|||||||
| TargetTree
|
| TargetTree
|
||||||
| TargetNockma
|
| TargetNockma
|
||||||
| TargetAnoma
|
| TargetAnoma
|
||||||
|
| TargetCairo
|
||||||
deriving stock (Data, Eq, Show)
|
deriving stock (Data, Eq, Show)
|
||||||
|
|
||||||
data Limits = Limits
|
data Limits = Limits
|
||||||
@ -97,6 +98,21 @@ getLimits tgt debug = case tgt of
|
|||||||
defaultLimits
|
defaultLimits
|
||||||
TargetAnoma ->
|
TargetAnoma ->
|
||||||
defaultLimits
|
defaultLimits
|
||||||
|
TargetCairo ->
|
||||||
|
Limits
|
||||||
|
{ _limitsMaxConstrs = 1048568,
|
||||||
|
_limitsMaxConstrArgs = 255,
|
||||||
|
_limitsMaxFunctionArgs = 8,
|
||||||
|
_limitsMaxLocalVars = 2048,
|
||||||
|
_limitsMaxClosureSize = 8 + 3,
|
||||||
|
_limitsClosureHeadSize = 3,
|
||||||
|
_limitsMaxStringSize = 0,
|
||||||
|
_limitsMaxStackDelta = 0, -- irrelevant
|
||||||
|
_limitsMaxFunctionAlloc = 0, -- irrelevant
|
||||||
|
_limitsDispatchStackSize = 0, -- irrelevant
|
||||||
|
_limitsBuiltinUIDsNum = 8,
|
||||||
|
_limitsSpecialisedApply = 3
|
||||||
|
}
|
||||||
|
|
||||||
defaultLimits :: Limits
|
defaultLimits :: Limits
|
||||||
defaultLimits =
|
defaultLimits =
|
||||||
|
@ -29,6 +29,11 @@ emptyBuilderState =
|
|||||||
_stateIdents = mempty
|
_stateIdents = mempty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runLabelInfoBuilderWithNextId :: Word -> Sem (LabelInfoBuilder ': r) a -> Sem r (LabelInfo, a)
|
||||||
|
runLabelInfoBuilderWithNextId nextSymId =
|
||||||
|
fmap (first (^. stateLabelInfo))
|
||||||
|
. runLabelInfoBuilder' emptyBuilderState {_stateNextSymbolId = nextSymId}
|
||||||
|
|
||||||
runLabelInfoBuilder :: Sem (LabelInfoBuilder ': r) a -> Sem r (LabelInfo, a)
|
runLabelInfoBuilder :: Sem (LabelInfoBuilder ': r) a -> Sem r (LabelInfo, a)
|
||||||
runLabelInfoBuilder = fmap (first (^. stateLabelInfo)) . runLabelInfoBuilder' emptyBuilderState
|
runLabelInfoBuilder = fmap (first (^. stateLabelInfo)) . runLabelInfoBuilder' emptyBuilderState
|
||||||
|
|
||||||
|
16
src/Juvix/Compiler/Casm/Data/Limits.hs
Normal file
16
src/Juvix/Compiler/Casm/Data/Limits.hs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
module Juvix.Compiler.Casm.Data.Limits where
|
||||||
|
|
||||||
|
import Juvix.Compiler.Backend
|
||||||
|
import Juvix.Compiler.Casm.Language
|
||||||
|
|
||||||
|
casmMaxFunctionArgs :: Int
|
||||||
|
casmMaxFunctionArgs = getLimits TargetCairo False ^. limitsMaxFunctionArgs
|
||||||
|
|
||||||
|
casmClosureAddrOffset :: Offset
|
||||||
|
casmClosureAddrOffset = 0
|
||||||
|
|
||||||
|
casmClosureStoredArgsOffset :: Offset
|
||||||
|
casmClosureStoredArgsOffset = 1
|
||||||
|
|
||||||
|
casmClosureArgsNumOffset :: Offset
|
||||||
|
casmClosureArgsNumOffset = 2
|
11
src/Juvix/Compiler/Casm/Data/Result.hs
Normal file
11
src/Juvix/Compiler/Casm/Data/Result.hs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module Juvix.Compiler.Casm.Data.Result where
|
||||||
|
|
||||||
|
import Juvix.Compiler.Casm.Data.LabelInfo
|
||||||
|
import Juvix.Compiler.Casm.Language
|
||||||
|
|
||||||
|
data Result = Result
|
||||||
|
{ _resultLabelInfo :: LabelInfo,
|
||||||
|
_resultCode :: [Instruction]
|
||||||
|
}
|
||||||
|
|
||||||
|
makeLenses ''Result
|
107
src/Juvix/Compiler/Casm/Extra/Base.hs
Normal file
107
src/Juvix/Compiler/Casm/Extra/Base.hs
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
module Juvix.Compiler.Casm.Extra.Base where
|
||||||
|
|
||||||
|
import Juvix.Compiler.Casm.Data.Limits
|
||||||
|
import Juvix.Compiler.Casm.Language
|
||||||
|
|
||||||
|
toOffset :: (Show a, Integral a) => a -> Offset
|
||||||
|
toOffset x
|
||||||
|
| fromIntegral v == x = v
|
||||||
|
| otherwise = error ("invalid offset: " <> show x)
|
||||||
|
where
|
||||||
|
v = fromIntegral x
|
||||||
|
|
||||||
|
adjustAp :: Int16 -> MemRef -> MemRef
|
||||||
|
adjustAp idx mr@MemRef {..} = case _memRefReg of
|
||||||
|
Ap -> MemRef Ap (_memRefOff - idx)
|
||||||
|
Fp -> mr
|
||||||
|
|
||||||
|
mkExtraBinop :: ExtraOpcode -> MemRef -> MemRef -> Value -> Instruction
|
||||||
|
mkExtraBinop op res arg1 arg2 =
|
||||||
|
ExtraBinop
|
||||||
|
InstrExtraBinop
|
||||||
|
{ _instrExtraBinopOpcode = op,
|
||||||
|
_instrExtraBinopResult = res,
|
||||||
|
_instrExtraBinopArg1 = arg1,
|
||||||
|
_instrExtraBinopArg2 = arg2,
|
||||||
|
_instrExtraBinopIncAp = False
|
||||||
|
}
|
||||||
|
|
||||||
|
mkNativeBinop :: Opcode -> MemRef -> MemRef -> Value -> Instruction
|
||||||
|
mkNativeBinop op res arg1 arg2 =
|
||||||
|
Assign
|
||||||
|
InstrAssign
|
||||||
|
{ _instrAssignResult = res,
|
||||||
|
_instrAssignValue =
|
||||||
|
Binop
|
||||||
|
BinopValue
|
||||||
|
{ _binopValueOpcode = op,
|
||||||
|
_binopValueArg1 = arg1,
|
||||||
|
_binopValueArg2 = arg2
|
||||||
|
},
|
||||||
|
_instrAssignIncAp = False
|
||||||
|
}
|
||||||
|
|
||||||
|
mkEq :: MemRef -> MemRef -> Value -> Instruction
|
||||||
|
mkEq res arg1 arg2 = mkExtraBinop FieldSub res arg1 arg2
|
||||||
|
|
||||||
|
mkIntLe :: MemRef -> MemRef -> Value -> [Instruction]
|
||||||
|
mkIntLe res arg1 arg2 = case arg2 of
|
||||||
|
Imm v ->
|
||||||
|
[mkExtraBinop IntLt res arg1 (Imm (v + 1))]
|
||||||
|
Ref mref ->
|
||||||
|
[inc, mkExtraBinop IntLt res (adjustAp 1 arg1) (Ref $ MemRef Ap (-1))]
|
||||||
|
where
|
||||||
|
inc =
|
||||||
|
Assign
|
||||||
|
InstrAssign
|
||||||
|
{ _instrAssignResult = MemRef Ap 0,
|
||||||
|
_instrAssignValue =
|
||||||
|
Binop
|
||||||
|
BinopValue
|
||||||
|
{ _binopValueArg1 = mref,
|
||||||
|
_binopValueArg2 = Imm 1,
|
||||||
|
_binopValueOpcode = FieldAdd
|
||||||
|
},
|
||||||
|
_instrAssignIncAp = True
|
||||||
|
}
|
||||||
|
Lab {} -> impossible
|
||||||
|
|
||||||
|
mkAssign :: MemRef -> RValue -> Instruction
|
||||||
|
mkAssign mr rv =
|
||||||
|
Assign
|
||||||
|
InstrAssign
|
||||||
|
{ _instrAssignResult = mr,
|
||||||
|
_instrAssignValue = rv,
|
||||||
|
_instrAssignIncAp = False
|
||||||
|
}
|
||||||
|
|
||||||
|
mkAssignAp :: RValue -> Instruction
|
||||||
|
mkAssignAp v =
|
||||||
|
Assign
|
||||||
|
InstrAssign
|
||||||
|
{ _instrAssignResult = MemRef Ap 0,
|
||||||
|
_instrAssignValue = v,
|
||||||
|
_instrAssignIncAp = True
|
||||||
|
}
|
||||||
|
|
||||||
|
mkOpArgsNum :: MemRef -> MemRef -> [Instruction]
|
||||||
|
mkOpArgsNum res v =
|
||||||
|
[ mkAssignAp (Val $ Imm $ fromIntegral casmMaxFunctionArgs + 1),
|
||||||
|
mkAssignAp (Load $ LoadValue (adjustAp 1 v) casmClosureArgsNumOffset),
|
||||||
|
mkExtraBinop FieldSub res (MemRef Ap (-2)) (Ref $ MemRef Ap (-1))
|
||||||
|
]
|
||||||
|
|
||||||
|
mkCall :: Value -> Instruction
|
||||||
|
mkCall = Call . InstrCall
|
||||||
|
|
||||||
|
mkJump :: RValue -> Instruction
|
||||||
|
mkJump tgt = Jump (InstrJump tgt False False)
|
||||||
|
|
||||||
|
mkJumpIf :: Value -> MemRef -> Instruction
|
||||||
|
mkJumpIf tgt v = JumpIf (InstrJumpIf tgt v False False)
|
||||||
|
|
||||||
|
mkJumpRel :: RValue -> Instruction
|
||||||
|
mkJumpRel tgt = Jump (InstrJump tgt True False)
|
||||||
|
|
||||||
|
mkJumpRelIf :: Value -> MemRef -> Instruction
|
||||||
|
mkJumpRelIf tgt v = JumpIf (InstrJumpIf tgt v True False)
|
32
src/Juvix/Compiler/Casm/Extra/Stdlib.hs
Normal file
32
src/Juvix/Compiler/Casm/Extra/Stdlib.hs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
module Juvix.Compiler.Casm.Extra.Stdlib where
|
||||||
|
|
||||||
|
import Data.FileEmbed qualified as FE
|
||||||
|
import Data.Text.Encoding
|
||||||
|
import Juvix.Compiler.Casm.Data.LabelInfoBuilder
|
||||||
|
import Juvix.Compiler.Casm.Language
|
||||||
|
import Juvix.Compiler.Casm.Translation.FromSource
|
||||||
|
|
||||||
|
data StdlibBuiltins = StdlibBuiltins
|
||||||
|
{ _stdlibGetRegs :: Symbol,
|
||||||
|
_stdlibCallClosure :: Symbol,
|
||||||
|
_stdlibExtendClosure :: Symbol,
|
||||||
|
_stdlibGetRegsName :: Text,
|
||||||
|
_stdlibCallClosureName :: Text,
|
||||||
|
_stdlibExtendClosureName :: Text
|
||||||
|
}
|
||||||
|
|
||||||
|
makeLenses ''StdlibBuiltins
|
||||||
|
|
||||||
|
addStdlibBuiltins :: (Member LabelInfoBuilder r) => Address -> Sem r (StdlibBuiltins, [Instruction])
|
||||||
|
addStdlibBuiltins addr = do
|
||||||
|
instrs <-
|
||||||
|
fmap (fromRight impossible) $
|
||||||
|
runParser' addr "stdlib.casm" $
|
||||||
|
decodeUtf8 $(FE.makeRelativeToProject "runtime/src/casm/stdlib.casm" >>= FE.embedFile)
|
||||||
|
let _stdlibGetRegsName :: Text = "juvix_get_regs"
|
||||||
|
_stdlibCallClosureName :: Text = "juvix_call_closure"
|
||||||
|
_stdlibExtendClosureName :: Text = "juvix_extend_closure"
|
||||||
|
_stdlibGetRegs <- fromJust <$> getIdent _stdlibGetRegsName
|
||||||
|
_stdlibCallClosure <- fromJust <$> getIdent _stdlibCallClosureName
|
||||||
|
_stdlibExtendClosure <- fromJust <$> getIdent _stdlibExtendClosureName
|
||||||
|
return (StdlibBuiltins {..}, instrs)
|
@ -19,9 +19,12 @@ import Juvix.Data.Field
|
|||||||
|
|
||||||
type Memory s = MV.MVector s (Maybe FField)
|
type Memory s = MV.MVector s (Maybe FField)
|
||||||
|
|
||||||
-- | Runs Cairo Assembly. Returns the value of `[ap - 1]` at program exit.
|
|
||||||
runCode :: LabelInfo -> [Instruction] -> FField
|
runCode :: LabelInfo -> [Instruction] -> FField
|
||||||
runCode (LabelInfo labelInfo) instrs0 = runST goCode
|
runCode = hRunCode stderr
|
||||||
|
|
||||||
|
-- | Runs Cairo Assembly. Returns the value of `[ap - 1]` at program exit.
|
||||||
|
hRunCode :: Handle -> LabelInfo -> [Instruction] -> FField
|
||||||
|
hRunCode hout (LabelInfo labelInfo) instrs0 = runST goCode
|
||||||
where
|
where
|
||||||
instrs :: Vec.Vector Instruction
|
instrs :: Vec.Vector Instruction
|
||||||
instrs = Vec.fromList instrs0
|
instrs = Vec.fromList instrs0
|
||||||
@ -48,6 +51,8 @@ runCode (LabelInfo labelInfo) instrs0 = runST goCode
|
|||||||
when (Vec.length instrs < pc) $
|
when (Vec.length instrs < pc) $
|
||||||
throwRunError ("invalid program counter: " <> show pc)
|
throwRunError ("invalid program counter: " <> show pc)
|
||||||
checkGaps mem
|
checkGaps mem
|
||||||
|
when (ap == 0) $
|
||||||
|
throwRunError "nothing to return"
|
||||||
readMem mem (ap - 1)
|
readMem mem (ap - 1)
|
||||||
| otherwise =
|
| otherwise =
|
||||||
case instrs Vec.! pc of
|
case instrs Vec.! pc of
|
||||||
@ -55,7 +60,6 @@ runCode (LabelInfo labelInfo) instrs0 = runST goCode
|
|||||||
ExtraBinop x -> goExtraBinop x pc ap fp mem
|
ExtraBinop x -> goExtraBinop x pc ap fp mem
|
||||||
Jump x -> goJump x pc ap fp mem
|
Jump x -> goJump x pc ap fp mem
|
||||||
JumpIf x -> goJumpIf x pc ap fp mem
|
JumpIf x -> goJumpIf x pc ap fp mem
|
||||||
JumpRel x -> goJumpRel x pc ap fp mem
|
|
||||||
Call x -> goCall x pc ap fp mem
|
Call x -> goCall x pc ap fp mem
|
||||||
Return -> goReturn pc ap fp mem
|
Return -> goReturn pc ap fp mem
|
||||||
Alloc x -> goAlloc x pc ap fp mem
|
Alloc x -> goAlloc x pc ap fp mem
|
||||||
@ -182,7 +186,7 @@ runCode (LabelInfo labelInfo) instrs0 = runST goCode
|
|||||||
IntMod -> fieldFromInteger fsize (fieldToInt x `rem` fieldToInt y)
|
IntMod -> fieldFromInteger fsize (fieldToInt x `rem` fieldToInt y)
|
||||||
IntLt ->
|
IntLt ->
|
||||||
fieldFromInteger fsize $
|
fieldFromInteger fsize $
|
||||||
if fieldToInt x < fieldToInt y then 1 else 0
|
if fieldToInt x < fieldToInt y then 0 else 1
|
||||||
|
|
||||||
fieldToInt :: FField -> Integer
|
fieldToInt :: FField -> Integer
|
||||||
fieldToInt f
|
fieldToInt f
|
||||||
@ -192,20 +196,17 @@ runCode (LabelInfo labelInfo) instrs0 = runST goCode
|
|||||||
v = fieldToInteger f
|
v = fieldToInteger f
|
||||||
|
|
||||||
goJump :: InstrJump -> Address -> Address -> Address -> Memory s -> ST s FField
|
goJump :: InstrJump -> Address -> Address -> Address -> Memory s -> ST s FField
|
||||||
goJump InstrJump {..} _ ap fp mem = do
|
goJump InstrJump {..} pc ap fp mem = do
|
||||||
tgt <- readValue ap fp mem _instrJumpTarget
|
tgt <- readRValue ap fp mem _instrJumpTarget
|
||||||
go (fromInteger (fieldToInteger tgt)) (ap + fromEnum _instrJumpIncAp) fp mem
|
let off = if _instrJumpRel then pc else 0
|
||||||
|
go (off + fromInteger (fieldToInteger tgt)) (ap + fromEnum _instrJumpIncAp) fp mem
|
||||||
|
|
||||||
goJumpIf :: InstrJumpIf -> Address -> Address -> Address -> Memory s -> ST s FField
|
goJumpIf :: InstrJumpIf -> Address -> Address -> Address -> Memory s -> ST s FField
|
||||||
goJumpIf InstrJumpIf {..} pc ap fp mem = do
|
goJumpIf InstrJumpIf {..} pc ap fp mem = do
|
||||||
tgt <- readValue ap fp mem _instrJumpIfTarget
|
tgt <- readValue ap fp mem _instrJumpIfTarget
|
||||||
v <- readMemRef ap fp mem _instrJumpIfValue
|
v <- readMemRef ap fp mem _instrJumpIfValue
|
||||||
go (if fieldToInteger v /= 0 then fromInteger (fieldToInteger tgt) else pc + 1) (ap + fromEnum _instrJumpIfIncAp) fp mem
|
let off = if _instrJumpIfRel then pc else 0
|
||||||
|
go (if fieldToInteger v /= 0 then off + fromInteger (fieldToInteger tgt) else pc + 1) (ap + fromEnum _instrJumpIfIncAp) fp mem
|
||||||
goJumpRel :: InstrJumpRel -> Address -> Address -> Address -> Memory s -> ST s FField
|
|
||||||
goJumpRel InstrJumpRel {..} pc ap fp mem = do
|
|
||||||
tgt <- readRValue ap fp mem _instrJumpRelTarget
|
|
||||||
go (pc + fromInteger (fieldToInteger tgt)) (ap + fromEnum _instrJumpRelIncAp) fp mem
|
|
||||||
|
|
||||||
goCall :: InstrCall -> Address -> Address -> Address -> Memory s -> ST s FField
|
goCall :: InstrCall -> Address -> Address -> Address -> Memory s -> ST s FField
|
||||||
goCall InstrCall {..} pc ap fp mem = do
|
goCall InstrCall {..} pc ap fp mem = do
|
||||||
@ -228,7 +229,7 @@ runCode (LabelInfo labelInfo) instrs0 = runST goCode
|
|||||||
goTrace :: InstrTrace -> Address -> Address -> Address -> Memory s -> ST s FField
|
goTrace :: InstrTrace -> Address -> Address -> Address -> Memory s -> ST s FField
|
||||||
goTrace InstrTrace {..} pc ap fp mem = do
|
goTrace InstrTrace {..} pc ap fp mem = do
|
||||||
v <- readRValue ap fp mem _instrTraceValue
|
v <- readRValue ap fp mem _instrTraceValue
|
||||||
GHC.unsafePerformIO (print v >> return (pure ()))
|
GHC.unsafePerformIO (hPrint hout v >> return (pure ()))
|
||||||
go (pc + 1) ap fp mem
|
go (pc + 1) ap fp mem
|
||||||
|
|
||||||
catchRunErrorIO :: a -> IO (Either CasmError a)
|
catchRunErrorIO :: a -> IO (Either CasmError a)
|
||||||
|
@ -7,10 +7,11 @@ where
|
|||||||
{-
|
{-
|
||||||
|
|
||||||
This module defines data structures for an extended subset of the Cairo Assembly
|
This module defines data structures for an extended subset of the Cairo Assembly
|
||||||
language, following Section 5 of [1]. Except the `ExtraBinop` instruction, all
|
language, following Section 5 of [1]. Except for the `ExtraBinop` instruction
|
||||||
instructions correspond to the instructions from [1]. The parser and pretty
|
and absolute conditional jumps, all instructions correspond to the instructions
|
||||||
printer implemented in `Juvix.Compiler.Casm.Translation.FromSource` and
|
from [1]. The parser and pretty printer implemented in
|
||||||
`Juvix.Compiler.Casm.Pretty` follow the syntax of [1, Section 5].
|
`Juvix.Compiler.Casm.Translation.FromSource` and `Juvix.Compiler.Casm.Pretty`
|
||||||
|
follow the syntax of [1, Section 5].
|
||||||
|
|
||||||
[1] Goldberg, Papini, Riabzev: "Cairo – a Turing-complete STARK-friendly CPU
|
[1] Goldberg, Papini, Riabzev: "Cairo – a Turing-complete STARK-friendly CPU
|
||||||
architecture" (https://ia.cr/2021/1063)
|
architecture" (https://ia.cr/2021/1063)
|
||||||
@ -78,7 +79,7 @@ data ExtraOpcode
|
|||||||
| IntMul
|
| IntMul
|
||||||
| IntDiv
|
| IntDiv
|
||||||
| IntMod
|
| IntMod
|
||||||
| -- | Sets the result to 1 if arg1 < arg2, or to 0 otherwise
|
| -- | Sets the result to zero if arg1 < arg2, or to non-zero otherwise
|
||||||
IntLt
|
IntLt
|
||||||
|
|
||||||
data Instruction
|
data Instruction
|
||||||
@ -88,7 +89,6 @@ data Instruction
|
|||||||
ExtraBinop InstrExtraBinop
|
ExtraBinop InstrExtraBinop
|
||||||
| Jump InstrJump
|
| Jump InstrJump
|
||||||
| JumpIf InstrJumpIf
|
| JumpIf InstrJumpIf
|
||||||
| JumpRel InstrJumpRel
|
|
||||||
| Call InstrCall
|
| Call InstrCall
|
||||||
| Return
|
| Return
|
||||||
| Alloc InstrAlloc
|
| Alloc InstrAlloc
|
||||||
@ -110,22 +110,20 @@ data InstrExtraBinop = InstrExtraBinop
|
|||||||
}
|
}
|
||||||
|
|
||||||
data InstrJump = InstrJump
|
data InstrJump = InstrJump
|
||||||
{ _instrJumpTarget :: Value,
|
{ _instrJumpTarget :: RValue,
|
||||||
|
_instrJumpRel :: Bool,
|
||||||
_instrJumpIncAp :: Bool
|
_instrJumpIncAp :: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
-- | Jump if value is nonzero
|
-- | Jump if value is nonzero. Boolean true is translated to zero, false to
|
||||||
|
-- non-zero.
|
||||||
data InstrJumpIf = InstrJumpIf
|
data InstrJumpIf = InstrJumpIf
|
||||||
{ _instrJumpIfTarget :: Value,
|
{ _instrJumpIfTarget :: Value,
|
||||||
_instrJumpIfValue :: MemRef,
|
_instrJumpIfValue :: MemRef,
|
||||||
|
_instrJumpIfRel :: Bool,
|
||||||
_instrJumpIfIncAp :: Bool
|
_instrJumpIfIncAp :: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
data InstrJumpRel = InstrJumpRel
|
|
||||||
{ _instrJumpRelTarget :: RValue,
|
|
||||||
_instrJumpRelIncAp :: Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
newtype InstrCall = InstrCall
|
newtype InstrCall = InstrCall
|
||||||
{ _instrCallTarget :: Value
|
{ _instrCallTarget :: Value
|
||||||
}
|
}
|
||||||
@ -148,7 +146,6 @@ makeLenses ''InstrAssign
|
|||||||
makeLenses ''InstrExtraBinop
|
makeLenses ''InstrExtraBinop
|
||||||
makeLenses ''InstrJump
|
makeLenses ''InstrJump
|
||||||
makeLenses ''InstrJumpIf
|
makeLenses ''InstrJumpIf
|
||||||
makeLenses ''InstrJumpRel
|
|
||||||
makeLenses ''InstrCall
|
makeLenses ''InstrCall
|
||||||
makeLenses ''InstrAlloc
|
makeLenses ''InstrAlloc
|
||||||
makeLenses ''InstrTrace
|
makeLenses ''InstrTrace
|
||||||
|
@ -116,20 +116,16 @@ instance PrettyCode InstrJump where
|
|||||||
ppCode InstrJump {..} = do
|
ppCode InstrJump {..} = do
|
||||||
tgt <- ppCode _instrJumpTarget
|
tgt <- ppCode _instrJumpTarget
|
||||||
incAp <- ppIncAp _instrJumpIncAp
|
incAp <- ppIncAp _instrJumpIncAp
|
||||||
return $ Str.jmp <+> tgt <> incAp
|
let rel = if _instrJumpRel then Str.rel <> space else mempty
|
||||||
|
return $ Str.jmp <+> rel <> tgt <> incAp
|
||||||
|
|
||||||
instance PrettyCode InstrJumpIf where
|
instance PrettyCode InstrJumpIf where
|
||||||
ppCode InstrJumpIf {..} = do
|
ppCode InstrJumpIf {..} = do
|
||||||
tgt <- ppCode _instrJumpIfTarget
|
tgt <- ppCode _instrJumpIfTarget
|
||||||
v <- ppCode _instrJumpIfValue
|
v <- ppCode _instrJumpIfValue
|
||||||
incAp <- ppIncAp _instrJumpIfIncAp
|
incAp <- ppIncAp _instrJumpIfIncAp
|
||||||
return $ Str.jmp <+> tgt <+> Str.if_ <+> v <+> Str.notequal <+> annotate AnnLiteralInteger "0" <> incAp
|
let rel = if _instrJumpIfRel then Str.rel <> space else mempty
|
||||||
|
return $ Str.jmp <+> rel <> tgt <+> Str.if_ <+> v <+> Str.notequal <+> annotate AnnLiteralInteger "0" <> incAp
|
||||||
instance PrettyCode InstrJumpRel where
|
|
||||||
ppCode InstrJumpRel {..} = do
|
|
||||||
tgt <- ppCode _instrJumpRelTarget
|
|
||||||
incAp <- ppIncAp _instrJumpRelIncAp
|
|
||||||
return $ Str.jmp <+> Str.rel <+> tgt <> incAp
|
|
||||||
|
|
||||||
instance PrettyCode InstrCall where
|
instance PrettyCode InstrCall where
|
||||||
ppCode InstrCall {..} = do
|
ppCode InstrCall {..} = do
|
||||||
@ -152,7 +148,6 @@ instance PrettyCode Instruction where
|
|||||||
ExtraBinop x -> ppCode x
|
ExtraBinop x -> ppCode x
|
||||||
Jump x -> ppCode x
|
Jump x -> ppCode x
|
||||||
JumpIf x -> ppCode x
|
JumpIf x -> ppCode x
|
||||||
JumpRel x -> ppCode x
|
|
||||||
Call x -> ppCode x
|
Call x -> ppCode x
|
||||||
Return -> return Str.ret
|
Return -> return Str.ret
|
||||||
Alloc x -> ppCode x
|
Alloc x -> ppCode x
|
||||||
|
@ -1 +1,377 @@
|
|||||||
module Juvix.Compiler.Casm.Translation.FromReg where
|
module Juvix.Compiler.Casm.Translation.FromReg where
|
||||||
|
|
||||||
|
import Data.HashMap.Strict qualified as HashMap
|
||||||
|
import Data.HashSet qualified as HashSet
|
||||||
|
import Juvix.Compiler.Backend
|
||||||
|
import Juvix.Compiler.Casm.Data.LabelInfoBuilder
|
||||||
|
import Juvix.Compiler.Casm.Data.Limits
|
||||||
|
import Juvix.Compiler.Casm.Data.Result
|
||||||
|
import Juvix.Compiler.Casm.Extra.Base
|
||||||
|
import Juvix.Compiler.Casm.Extra.Stdlib
|
||||||
|
import Juvix.Compiler.Casm.Language
|
||||||
|
import Juvix.Compiler.Reg.Data.InfoTable qualified as Reg
|
||||||
|
import Juvix.Compiler.Reg.Extra.Info qualified as Reg
|
||||||
|
import Juvix.Compiler.Reg.Language qualified as Reg
|
||||||
|
import Juvix.Compiler.Tree.Evaluator.Builtins qualified as Reg
|
||||||
|
import Juvix.Data.Field
|
||||||
|
|
||||||
|
fromReg :: Reg.InfoTable -> Result
|
||||||
|
fromReg tab = uncurry Result $ run $ runLabelInfoBuilderWithNextId (Reg.getNextSymbolId tab) $ do
|
||||||
|
let initialOffset :: Int = 2
|
||||||
|
(blts, binstrs) <- addStdlibBuiltins initialOffset
|
||||||
|
endSym <- freshSymbol
|
||||||
|
let endName :: Text = "__juvix_end"
|
||||||
|
endLab = LabelRef endSym (Just endName)
|
||||||
|
(addr, instrs) <- second (concat . reverse) <$> foldM (goFun blts endLab) (initialOffset + length binstrs, []) (tab ^. Reg.infoFunctions)
|
||||||
|
eassert (addr == length instrs + length binstrs + initialOffset)
|
||||||
|
registerLabelName endSym endName
|
||||||
|
registerLabelAddress endSym addr
|
||||||
|
let mainSym = fromJust $ tab ^. Reg.infoMainFunction
|
||||||
|
mainName = fromJust (HashMap.lookup mainSym (tab ^. Reg.infoFunctions)) ^. Reg.functionName
|
||||||
|
callInstr = Call $ InstrCall $ Lab $ LabelRef mainSym (Just mainName)
|
||||||
|
jmpInstr = mkJump (Val $ Lab endLab)
|
||||||
|
return $ callInstr : jmpInstr : binstrs ++ instrs ++ [Label endLab]
|
||||||
|
where
|
||||||
|
info :: Reg.ExtraInfo
|
||||||
|
info = Reg.computeExtraInfo (getLimits TargetCairo False) tab
|
||||||
|
|
||||||
|
getTagId :: Tag -> Int
|
||||||
|
getTagId tag =
|
||||||
|
1 + fromJust (HashMap.lookup tag (info ^. Reg.extraInfoCIDs))
|
||||||
|
|
||||||
|
goFun :: forall r. (Member LabelInfoBuilder r) => StdlibBuiltins -> LabelRef -> (Address, [[Instruction]]) -> Reg.FunctionInfo -> Sem r (Address, [[Instruction]])
|
||||||
|
goFun blts failLab (addr0, acc) funInfo = do
|
||||||
|
let sym = funInfo ^. Reg.functionSymbol
|
||||||
|
funName = funInfo ^. Reg.functionName
|
||||||
|
registerLabelName sym funName
|
||||||
|
registerLabelAddress sym addr0
|
||||||
|
let lab = Label $ LabelRef sym (Just funName)
|
||||||
|
code = funInfo ^. Reg.functionCode
|
||||||
|
n = fromJust $ HashMap.lookup (funInfo ^. Reg.functionSymbol) (info ^. Reg.extraInfoLocalVarsNum)
|
||||||
|
i1 = Alloc $ InstrAlloc $ Val $ Imm $ fromIntegral n
|
||||||
|
pre = [lab, i1]
|
||||||
|
addr1 = addr0 + length pre
|
||||||
|
instrs <- goCode addr1 code
|
||||||
|
return (addr1 + length instrs, (pre ++ instrs) : acc)
|
||||||
|
where
|
||||||
|
unsupported :: Text -> a
|
||||||
|
unsupported what = error ("Cairo backend: unsupported: " <> what)
|
||||||
|
|
||||||
|
goCode :: Address -> Reg.Code -> Sem r [Instruction]
|
||||||
|
goCode addr code = concat . reverse . snd <$> foldM go' (addr, []) code
|
||||||
|
where
|
||||||
|
go' :: (Address, [[Instruction]]) -> Reg.Instruction -> Sem r (Address, [[Instruction]])
|
||||||
|
go' (addr', acc') i = do
|
||||||
|
is <- goInstr addr' i
|
||||||
|
return (addr' + length is, is : acc')
|
||||||
|
|
||||||
|
goInstr :: Address -> Reg.Instruction -> Sem r [Instruction]
|
||||||
|
goInstr addr = \case
|
||||||
|
Reg.Binop x -> goBinop addr x
|
||||||
|
Reg.Unop x -> goUnop addr x
|
||||||
|
Reg.Assign x -> goAssign addr x
|
||||||
|
Reg.Alloc x -> goAlloc addr x
|
||||||
|
Reg.AllocClosure x -> goAllocClosure addr x
|
||||||
|
Reg.ExtendClosure x -> goExtendClosure addr x
|
||||||
|
Reg.Call x -> goCall addr x
|
||||||
|
Reg.TailCall x -> goTailCall addr x
|
||||||
|
Reg.CallClosures {} -> impossible
|
||||||
|
Reg.TailCallClosures {} -> impossible
|
||||||
|
Reg.Return x -> goReturn addr x
|
||||||
|
Reg.Branch x -> goBranch addr x
|
||||||
|
Reg.Case x -> goCase addr x
|
||||||
|
Reg.Trace x -> goTrace addr x
|
||||||
|
Reg.Dump -> unsupported "dump"
|
||||||
|
Reg.Failure x -> goFail addr x
|
||||||
|
Reg.Prealloc {} -> return []
|
||||||
|
Reg.Nop -> return []
|
||||||
|
Reg.Block x -> goBlock addr x
|
||||||
|
|
||||||
|
goConst :: Reg.Constant -> Integer
|
||||||
|
goConst = \case
|
||||||
|
Reg.ConstInt x -> x
|
||||||
|
Reg.ConstBool True -> 0
|
||||||
|
Reg.ConstBool False -> 1
|
||||||
|
Reg.ConstField f -> fieldToInteger f
|
||||||
|
Reg.ConstUnit -> 0
|
||||||
|
Reg.ConstVoid -> 0
|
||||||
|
Reg.ConstString {} -> unsupported "strings"
|
||||||
|
|
||||||
|
goConstrField :: Reg.ConstrField -> RValue
|
||||||
|
goConstrField Reg.ConstrField {..} =
|
||||||
|
Load $ LoadValue (goVarRef _constrFieldRef) (toOffset _constrFieldIndex + 1)
|
||||||
|
|
||||||
|
goVarRef :: Reg.VarRef -> MemRef
|
||||||
|
goVarRef Reg.VarRef {..} = case _varRefGroup of
|
||||||
|
Reg.VarGroupArgs ->
|
||||||
|
MemRef Fp (-3 - toOffset _varRefIndex)
|
||||||
|
Reg.VarGroupLocal ->
|
||||||
|
MemRef Fp (toOffset _varRefIndex)
|
||||||
|
|
||||||
|
goValue :: Reg.Value -> ([Instruction], Value)
|
||||||
|
goValue = \case
|
||||||
|
Reg.Const c -> ([], Imm $ goConst c)
|
||||||
|
Reg.CRef x -> ([mkAssignAp (goConstrField x)], Ref $ MemRef Ap (-1))
|
||||||
|
Reg.VRef x -> ([], Ref $ goVarRef x)
|
||||||
|
|
||||||
|
goRValue :: Reg.Value -> RValue
|
||||||
|
goRValue = \case
|
||||||
|
Reg.Const c -> Val $ Imm $ goConst c
|
||||||
|
Reg.CRef x -> goConstrField x
|
||||||
|
Reg.VRef x -> Val $ Ref $ goVarRef x
|
||||||
|
|
||||||
|
goLoad :: Reg.Value -> Offset -> ([Instruction], RValue)
|
||||||
|
goLoad v off = case goRValue v of
|
||||||
|
Val (Ref r) -> ([], Load $ LoadValue r off)
|
||||||
|
v' -> ([mkAssignAp v'], Load $ LoadValue (MemRef Ap (-1)) off)
|
||||||
|
|
||||||
|
goAssignValue :: MemRef -> Reg.Value -> Instruction
|
||||||
|
goAssignValue res = mkAssign res . goRValue
|
||||||
|
|
||||||
|
goAssignApValue :: Reg.Value -> Instruction
|
||||||
|
goAssignApValue = mkAssignAp . goRValue
|
||||||
|
|
||||||
|
mkBinop :: Reg.BinaryOp -> MemRef -> MemRef -> Value -> [Instruction]
|
||||||
|
mkBinop op res arg1 arg2 = case op of
|
||||||
|
Reg.OpIntAdd ->
|
||||||
|
[mkExtraBinop IntAdd res arg1 arg2]
|
||||||
|
Reg.OpIntSub ->
|
||||||
|
[mkExtraBinop IntSub res arg1 arg2]
|
||||||
|
Reg.OpIntMul ->
|
||||||
|
[mkExtraBinop IntMul res arg1 arg2]
|
||||||
|
Reg.OpIntDiv ->
|
||||||
|
[mkExtraBinop IntDiv res arg1 arg2]
|
||||||
|
Reg.OpIntMod ->
|
||||||
|
[mkExtraBinop IntMod res arg1 arg2]
|
||||||
|
Reg.OpIntLt ->
|
||||||
|
[mkExtraBinop IntLt res arg1 arg2]
|
||||||
|
Reg.OpIntLe ->
|
||||||
|
mkIntLe res arg1 arg2
|
||||||
|
Reg.OpFieldAdd ->
|
||||||
|
[mkNativeBinop FieldAdd res arg1 arg2]
|
||||||
|
Reg.OpFieldSub ->
|
||||||
|
[mkExtraBinop FieldSub res arg1 arg2]
|
||||||
|
Reg.OpFieldMul ->
|
||||||
|
[mkNativeBinop FieldMul res arg1 arg2]
|
||||||
|
Reg.OpFieldDiv ->
|
||||||
|
[mkExtraBinop FieldDiv res arg1 arg2]
|
||||||
|
Reg.OpEq ->
|
||||||
|
[mkEq res arg1 arg2]
|
||||||
|
Reg.OpStrConcat ->
|
||||||
|
unsupported "strings"
|
||||||
|
|
||||||
|
goBinop :: Address -> Reg.InstrBinop -> Sem r [Instruction]
|
||||||
|
goBinop addr x@Reg.InstrBinop {..} = case _instrBinopArg1 of
|
||||||
|
Reg.Const c1 -> case _instrBinopArg2 of
|
||||||
|
Reg.Const c2 -> case Reg.evalBinop' _instrBinopOpcode c1 c2 of
|
||||||
|
Left err -> error err
|
||||||
|
Right c ->
|
||||||
|
return [mkAssign res (Val $ Imm $ goConst c)]
|
||||||
|
_ ->
|
||||||
|
goBinop
|
||||||
|
addr
|
||||||
|
x
|
||||||
|
{ Reg._instrBinopArg1 = _instrBinopArg2,
|
||||||
|
Reg._instrBinopArg2 = _instrBinopArg1
|
||||||
|
}
|
||||||
|
Reg.CRef ctr1 ->
|
||||||
|
case _instrBinopArg2 of
|
||||||
|
Reg.CRef {} ->
|
||||||
|
return $ i : is2 ++ mkBinop _instrBinopOpcode res (MemRef Ap (-2)) (Ref $ MemRef Ap (-1))
|
||||||
|
_ -> do
|
||||||
|
eassert (null is2)
|
||||||
|
return $ i : mkBinop _instrBinopOpcode res (MemRef Ap (-1)) v2
|
||||||
|
where
|
||||||
|
i = mkAssignAp (goConstrField ctr1)
|
||||||
|
Reg.VRef var1 ->
|
||||||
|
return $ is2 ++ mkBinop _instrBinopOpcode res (goVarRef var1) v2
|
||||||
|
where
|
||||||
|
res = goVarRef _instrBinopResult
|
||||||
|
(is2, v2) = goValue _instrBinopArg2
|
||||||
|
|
||||||
|
goUnop :: Address -> Reg.InstrUnop -> Sem r [Instruction]
|
||||||
|
goUnop _ Reg.InstrUnop {..} = case _instrUnopOpcode of
|
||||||
|
Reg.OpShow -> unsupported "strings"
|
||||||
|
Reg.OpStrToInt -> unsupported "strings"
|
||||||
|
Reg.OpFieldToInt -> return [goAssignValue res _instrUnopArg]
|
||||||
|
Reg.OpIntToField -> return [goAssignValue res _instrUnopArg]
|
||||||
|
Reg.OpArgsNum -> case v of
|
||||||
|
Ref mr ->
|
||||||
|
return $ is ++ mkOpArgsNum res mr
|
||||||
|
Imm {} -> impossible
|
||||||
|
Lab {} -> impossible
|
||||||
|
where
|
||||||
|
res = goVarRef _instrUnopResult
|
||||||
|
(is, v) = goValue _instrUnopArg
|
||||||
|
|
||||||
|
goAssign :: Address -> Reg.InstrAssign -> Sem r [Instruction]
|
||||||
|
goAssign _ Reg.InstrAssign {..} =
|
||||||
|
return [goAssignValue res _instrAssignValue]
|
||||||
|
where
|
||||||
|
res = goVarRef _instrAssignResult
|
||||||
|
|
||||||
|
mkAllocCall :: MemRef -> [Instruction]
|
||||||
|
mkAllocCall res =
|
||||||
|
[ mkCall $ Lab $ LabelRef (blts ^. stdlibGetRegs) (Just (blts ^. stdlibGetRegsName)),
|
||||||
|
mkNativeBinop FieldAdd res (MemRef Ap (-2)) (Imm 2)
|
||||||
|
]
|
||||||
|
|
||||||
|
goAlloc :: Address -> Reg.InstrAlloc -> Sem r [Instruction]
|
||||||
|
goAlloc _ Reg.InstrAlloc {..} =
|
||||||
|
return $
|
||||||
|
mkAllocCall res
|
||||||
|
++ [ mkAssignAp (Val $ Imm $ fromIntegral tagId)
|
||||||
|
]
|
||||||
|
++ map goAssignApValue _instrAllocArgs
|
||||||
|
where
|
||||||
|
res = goVarRef _instrAllocResult
|
||||||
|
tagId = getTagId _instrAllocTag
|
||||||
|
|
||||||
|
goAllocClosure :: Address -> Reg.InstrAllocClosure -> Sem r [Instruction]
|
||||||
|
goAllocClosure _ Reg.InstrAllocClosure {..} =
|
||||||
|
return $
|
||||||
|
mkAllocCall res
|
||||||
|
++ [ mkAssignAp (Val $ Lab $ LabelRef _instrAllocClosureSymbol (Just funName)),
|
||||||
|
mkAssignAp (Val $ Imm $ fromIntegral $ casmMaxFunctionArgs + 1 - storedArgsNum),
|
||||||
|
mkAssignAp (Val $ Imm $ fromIntegral $ casmMaxFunctionArgs + 1 - leftArgsNum)
|
||||||
|
]
|
||||||
|
++ map goAssignApValue _instrAllocClosureArgs
|
||||||
|
where
|
||||||
|
res = goVarRef _instrAllocClosureResult
|
||||||
|
funName = Reg.lookupFunInfo tab _instrAllocClosureSymbol ^. Reg.functionName
|
||||||
|
storedArgsNum = length _instrAllocClosureArgs
|
||||||
|
leftArgsNum = _instrAllocClosureExpectedArgsNum - storedArgsNum
|
||||||
|
|
||||||
|
goExtendClosure :: Address -> Reg.InstrExtendClosure -> Sem r [Instruction]
|
||||||
|
goExtendClosure _ Reg.InstrExtendClosure {..} =
|
||||||
|
return $
|
||||||
|
map goAssignApValue _instrExtendClosureArgs
|
||||||
|
++ [ mkAssignAp (Val $ Imm $ fromIntegral $ length _instrExtendClosureArgs),
|
||||||
|
mkAssignAp (Val $ Ref val),
|
||||||
|
mkCall $ Lab $ LabelRef (blts ^. stdlibExtendClosure) (Just (blts ^. stdlibExtendClosureName)),
|
||||||
|
mkAssign res (Val $ Ref $ MemRef Ap (-1))
|
||||||
|
]
|
||||||
|
where
|
||||||
|
res = goVarRef _instrExtendClosureResult
|
||||||
|
val = goVarRef _instrExtendClosureValue
|
||||||
|
|
||||||
|
goCall' :: Instruction -> Reg.CallType -> [Reg.Value] -> [Instruction]
|
||||||
|
goCall' saveOrRet ct args = case ct of
|
||||||
|
Reg.CallFun sym ->
|
||||||
|
args'
|
||||||
|
++ [ mkCall $ Lab $ LabelRef sym (Just funName),
|
||||||
|
saveOrRet
|
||||||
|
]
|
||||||
|
where
|
||||||
|
funName = Reg.lookupFunInfo tab sym ^. Reg.functionName
|
||||||
|
Reg.CallClosure cl ->
|
||||||
|
args'
|
||||||
|
++ [ mkAssignAp (Val $ Ref $ goVarRef cl),
|
||||||
|
mkCall $ Lab $ LabelRef (blts ^. stdlibCallClosure) (Just (blts ^. stdlibCallClosureName)),
|
||||||
|
saveOrRet
|
||||||
|
]
|
||||||
|
where
|
||||||
|
args' = map goAssignApValue (reverse args)
|
||||||
|
|
||||||
|
goCall :: Address -> Reg.InstrCall -> Sem r [Instruction]
|
||||||
|
goCall _ Reg.InstrCall {..} =
|
||||||
|
return $
|
||||||
|
goCall' (mkAssign res (Val $ Ref $ MemRef Ap (-1))) _instrCallType _instrCallArgs
|
||||||
|
where
|
||||||
|
res = goVarRef _instrCallResult
|
||||||
|
|
||||||
|
-- There is no way to make "proper" tail calls in Cairo, because
|
||||||
|
-- the only way to set the `fp` register is via the `call` instruction.
|
||||||
|
-- So we just translate tail calls into `call` followed by `ret`.
|
||||||
|
goTailCall :: Address -> Reg.InstrTailCall -> Sem r [Instruction]
|
||||||
|
goTailCall _ Reg.InstrTailCall {..} =
|
||||||
|
return $
|
||||||
|
goCall' Return _instrTailCallType _instrTailCallArgs
|
||||||
|
|
||||||
|
goReturn :: Address -> Reg.InstrReturn -> Sem r [Instruction]
|
||||||
|
goReturn _ Reg.InstrReturn {..} =
|
||||||
|
return $
|
||||||
|
[ goAssignApValue _instrReturnValue,
|
||||||
|
Return
|
||||||
|
]
|
||||||
|
|
||||||
|
goBranch :: Address -> Reg.InstrBranch -> Sem r [Instruction]
|
||||||
|
goBranch addr Reg.InstrBranch {..} = case v of
|
||||||
|
Imm c
|
||||||
|
| c == 0 -> goCode addr _instrBranchTrue
|
||||||
|
| otherwise -> goCode addr _instrBranchFalse
|
||||||
|
Ref r -> do
|
||||||
|
symFalse <- freshSymbol
|
||||||
|
symEnd <- freshSymbol
|
||||||
|
let labFalse = LabelRef symFalse Nothing
|
||||||
|
labEnd = LabelRef symEnd Nothing
|
||||||
|
addr1 = addr + length is + 1
|
||||||
|
codeTrue <- goCode addr1 _instrBranchTrue
|
||||||
|
let addr2 = addr1 + length codeTrue + 1
|
||||||
|
registerLabelAddress symFalse addr2
|
||||||
|
codeFalse <- goCode (addr2 + 1) _instrBranchFalse
|
||||||
|
registerLabelAddress symEnd (addr2 + 1 + length codeFalse)
|
||||||
|
return $
|
||||||
|
is
|
||||||
|
++ [mkJumpIf (Lab labFalse) r]
|
||||||
|
++ codeTrue
|
||||||
|
++ [ mkJump (Val $ Lab labEnd),
|
||||||
|
Label labFalse
|
||||||
|
]
|
||||||
|
++ codeFalse
|
||||||
|
++ [Label labEnd]
|
||||||
|
Lab {} -> impossible
|
||||||
|
where
|
||||||
|
(is, v) = goValue _instrBranchValue
|
||||||
|
|
||||||
|
goCase :: Address -> Reg.InstrCase -> Sem r [Instruction]
|
||||||
|
goCase addr Reg.InstrCase {..} = do
|
||||||
|
syms <- replicateM (length tags) freshSymbol
|
||||||
|
symEnd <- freshSymbol
|
||||||
|
let symMap = HashMap.fromList $ zip tags syms
|
||||||
|
labs = map (flip LabelRef Nothing) syms
|
||||||
|
labEnd = LabelRef symEnd Nothing
|
||||||
|
jmps = map (mkJump . Val . Lab) labs
|
||||||
|
addr1 = addr + length is + 1 + length jmps
|
||||||
|
(addr2, instrs) <- second (concat . reverse) <$> foldM (goCaseBranch symMap labEnd) (addr1, []) _instrCaseBranches
|
||||||
|
(addr3, instrs') <- second reverse <$> foldM (goDefaultLabel symMap) (addr2, []) defaultTags
|
||||||
|
instrs'' <- maybe (return []) (goCode addr3) _instrCaseDefault
|
||||||
|
let addr4 = addr3 + length instrs''
|
||||||
|
registerLabelAddress symEnd addr4
|
||||||
|
return $ is ++ mkJumpRel v : jmps ++ instrs ++ instrs' ++ instrs'' ++ [Label labEnd]
|
||||||
|
where
|
||||||
|
(is, v) = goLoad _instrCaseValue 0
|
||||||
|
tags = Reg.lookupInductiveInfo tab _instrCaseInductive ^. Reg.inductiveConstructors
|
||||||
|
ctrTags = HashSet.fromList $ map (^. Reg.caseBranchTag) _instrCaseBranches
|
||||||
|
defaultTags = filter (not . flip HashSet.member ctrTags) tags
|
||||||
|
|
||||||
|
goCaseBranch :: HashMap Tag Symbol -> LabelRef -> (Address, [[Instruction]]) -> Reg.CaseBranch -> Sem r (Address, [[Instruction]])
|
||||||
|
goCaseBranch symMap labEnd (addr', acc') Reg.CaseBranch {..} = do
|
||||||
|
let sym = fromJust $ HashMap.lookup _caseBranchTag symMap
|
||||||
|
lab = LabelRef sym Nothing
|
||||||
|
registerLabelAddress sym addr'
|
||||||
|
instrs <- goCode (addr' + 1) _caseBranchCode
|
||||||
|
let instrs' = Label lab : instrs ++ [mkJump (Val $ Lab labEnd)]
|
||||||
|
return (addr' + length instrs', instrs' : acc')
|
||||||
|
|
||||||
|
goDefaultLabel :: HashMap Tag Symbol -> (Address, [Instruction]) -> Reg.Tag -> Sem r (Address, [Instruction])
|
||||||
|
goDefaultLabel symMap (addr', acc') tag = do
|
||||||
|
let sym = fromJust $ HashMap.lookup tag symMap
|
||||||
|
lab = LabelRef sym Nothing
|
||||||
|
registerLabelAddress sym addr'
|
||||||
|
return (addr' + 1, Label lab : acc')
|
||||||
|
|
||||||
|
goTrace :: Address -> Reg.InstrTrace -> Sem r [Instruction]
|
||||||
|
goTrace _ Reg.InstrTrace {..} =
|
||||||
|
return [Trace (InstrTrace (goRValue _instrTraceValue))]
|
||||||
|
|
||||||
|
goFail :: Address -> Reg.InstrFailure -> Sem r [Instruction]
|
||||||
|
goFail _ Reg.InstrFailure {..} =
|
||||||
|
return
|
||||||
|
[ Trace (InstrTrace (goRValue _instrFailureValue)),
|
||||||
|
mkJump (Val $ Lab failLab)
|
||||||
|
]
|
||||||
|
|
||||||
|
goBlock :: Address -> Reg.InstrBlock -> Sem r [Instruction]
|
||||||
|
goBlock addr Reg.InstrBlock {..} =
|
||||||
|
goCode addr _instrBlockCode
|
||||||
|
@ -14,13 +14,20 @@ parseText = runParser noFile
|
|||||||
|
|
||||||
runParser :: Path Abs File -> Text -> Either MegaparsecError (LabelInfo, [Instruction])
|
runParser :: Path Abs File -> Text -> Either MegaparsecError (LabelInfo, [Instruction])
|
||||||
runParser fileName input_ =
|
runParser fileName input_ =
|
||||||
case run . runLabelInfoBuilder $ P.runParserT parseToplevel (toFilePath fileName) input_ of
|
case run . runLabelInfoBuilder $ runParser' 0 (toFilePath fileName) input_ of
|
||||||
(_, Left err) -> Left (MegaparsecError err)
|
(_, Left err) -> Left err
|
||||||
(li, Right instrs) -> Right (li, instrs)
|
(li, Right instrs) -> Right (li, instrs)
|
||||||
|
|
||||||
parseToplevel :: (Member LabelInfoBuilder r) => ParsecS r [Instruction]
|
runParser' :: (Member LabelInfoBuilder r) => Address -> FilePath -> Text -> Sem r (Either MegaparsecError [Instruction])
|
||||||
parseToplevel = do
|
runParser' addr fileName input_ = do
|
||||||
instrs <- statements 0
|
e <- P.runParserT (parseToplevel addr) fileName input_
|
||||||
|
return $ case e of
|
||||||
|
Left err -> Left (MegaparsecError err)
|
||||||
|
Right instrs -> Right instrs
|
||||||
|
|
||||||
|
parseToplevel :: (Member LabelInfoBuilder r) => Address -> ParsecS r [Instruction]
|
||||||
|
parseToplevel addr = do
|
||||||
|
instrs <- statements addr
|
||||||
P.eof
|
P.eof
|
||||||
return instrs
|
return instrs
|
||||||
|
|
||||||
@ -160,44 +167,38 @@ parseIncAp = (kw delimSemicolon >> kw kwApPlusPlus >> return True) <|> return Fa
|
|||||||
parseJump :: forall r. (Member LabelInfoBuilder r) => ParsecS r Instruction
|
parseJump :: forall r. (Member LabelInfoBuilder r) => ParsecS r Instruction
|
||||||
parseJump = do
|
parseJump = do
|
||||||
kw kwJmp
|
kw kwJmp
|
||||||
relJmp <|> jmp
|
P.try jmpIf <|> jmp
|
||||||
where
|
where
|
||||||
relJmp :: ParsecS r Instruction
|
jmpIf :: ParsecS r Instruction
|
||||||
relJmp = do
|
jmpIf = do
|
||||||
kw kwRel
|
isRel <- isJust <$> optional (kw kwRel)
|
||||||
tgt <- parseRValue
|
tgt <- parseValue
|
||||||
|
kw kwIf
|
||||||
|
v <- parseMemRef
|
||||||
|
kw kwNotEq
|
||||||
|
symbol "0"
|
||||||
incAp <- parseIncAp
|
incAp <- parseIncAp
|
||||||
return $
|
return $
|
||||||
JumpRel $
|
JumpIf $
|
||||||
InstrJumpRel
|
InstrJumpIf
|
||||||
{ _instrJumpRelTarget = tgt,
|
{ _instrJumpIfTarget = tgt,
|
||||||
_instrJumpRelIncAp = incAp
|
_instrJumpIfValue = v,
|
||||||
|
_instrJumpIfRel = isRel,
|
||||||
|
_instrJumpIfIncAp = incAp
|
||||||
}
|
}
|
||||||
|
|
||||||
jmp :: ParsecS r Instruction
|
jmp :: ParsecS r Instruction
|
||||||
jmp = do
|
jmp = do
|
||||||
tgt <- parseValue
|
isRel <- isJust <$> optional (kw kwRel)
|
||||||
mv <- optional if_
|
tgt <- parseRValue
|
||||||
incAp <- parseIncAp
|
incAp <- parseIncAp
|
||||||
case mv of
|
return $
|
||||||
Nothing ->
|
Jump $
|
||||||
return $ Jump $ InstrJump {_instrJumpTarget = tgt, _instrJumpIncAp = incAp}
|
InstrJump
|
||||||
Just v ->
|
{ _instrJumpTarget = tgt,
|
||||||
return $
|
_instrJumpRel = isRel,
|
||||||
JumpIf $
|
_instrJumpIncAp = incAp
|
||||||
InstrJumpIf
|
}
|
||||||
{ _instrJumpIfTarget = tgt,
|
|
||||||
_instrJumpIfValue = v,
|
|
||||||
_instrJumpIfIncAp = incAp
|
|
||||||
}
|
|
||||||
where
|
|
||||||
if_ :: ParsecS r MemRef
|
|
||||||
if_ = do
|
|
||||||
kw kwIf
|
|
||||||
v <- parseMemRef
|
|
||||||
kw kwNotEq
|
|
||||||
symbol "0"
|
|
||||||
return v
|
|
||||||
|
|
||||||
parseCall :: (Member LabelInfoBuilder r) => ParsecS r Instruction
|
parseCall :: (Member LabelInfoBuilder r) => ParsecS r Instruction
|
||||||
parseCall = do
|
parseCall = do
|
||||||
|
@ -15,7 +15,6 @@ validate labi instrs = mapM_ go instrs
|
|||||||
ExtraBinop x -> goExtraBinop x
|
ExtraBinop x -> goExtraBinop x
|
||||||
Jump x -> goJump x
|
Jump x -> goJump x
|
||||||
JumpIf x -> goJumpIf x
|
JumpIf x -> goJumpIf x
|
||||||
JumpRel x -> goJumpRel x
|
|
||||||
Call x -> goCall x
|
Call x -> goCall x
|
||||||
Return -> return ()
|
Return -> return ()
|
||||||
Alloc x -> goAlloc x
|
Alloc x -> goAlloc x
|
||||||
@ -52,14 +51,11 @@ validate labi instrs = mapM_ go instrs
|
|||||||
goExtraBinop InstrExtraBinop {..} = goValue _instrExtraBinopArg2
|
goExtraBinop InstrExtraBinop {..} = goValue _instrExtraBinopArg2
|
||||||
|
|
||||||
goJump :: InstrJump -> Either CasmError ()
|
goJump :: InstrJump -> Either CasmError ()
|
||||||
goJump InstrJump {..} = goValue _instrJumpTarget
|
goJump InstrJump {..} = goRValue _instrJumpTarget
|
||||||
|
|
||||||
goJumpIf :: InstrJumpIf -> Either CasmError ()
|
goJumpIf :: InstrJumpIf -> Either CasmError ()
|
||||||
goJumpIf InstrJumpIf {..} = goValue _instrJumpIfTarget
|
goJumpIf InstrJumpIf {..} = goValue _instrJumpIfTarget
|
||||||
|
|
||||||
goJumpRel :: InstrJumpRel -> Either CasmError ()
|
|
||||||
goJumpRel InstrJumpRel {..} = goRValue _instrJumpRelTarget
|
|
||||||
|
|
||||||
goCall :: InstrCall -> Either CasmError ()
|
goCall :: InstrCall -> Either CasmError ()
|
||||||
goCall InstrCall {..} = goValue _instrCallTarget
|
goCall InstrCall {..} = goValue _instrCallTarget
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ data TransformationId
|
|||||||
| CheckExec
|
| CheckExec
|
||||||
| CheckVampIR
|
| CheckVampIR
|
||||||
| CheckAnoma
|
| CheckAnoma
|
||||||
|
| CheckCairo
|
||||||
| Normalize
|
| Normalize
|
||||||
| LetFolding
|
| LetFolding
|
||||||
| LambdaFolding
|
| LambdaFolding
|
||||||
@ -99,6 +100,7 @@ instance TransformationId' TransformationId where
|
|||||||
CheckExec -> strCheckExec
|
CheckExec -> strCheckExec
|
||||||
CheckVampIR -> strCheckVampIR
|
CheckVampIR -> strCheckVampIR
|
||||||
CheckAnoma -> strCheckAnoma
|
CheckAnoma -> strCheckAnoma
|
||||||
|
CheckCairo -> strCheckCairo
|
||||||
Normalize -> strNormalize
|
Normalize -> strNormalize
|
||||||
LetFolding -> strLetFolding
|
LetFolding -> strLetFolding
|
||||||
LambdaFolding -> strLambdaFolding
|
LambdaFolding -> strLambdaFolding
|
||||||
|
@ -83,6 +83,9 @@ strCheckVampIR = "check-vampir"
|
|||||||
strCheckAnoma :: Text
|
strCheckAnoma :: Text
|
||||||
strCheckAnoma = "check-anoma"
|
strCheckAnoma = "check-anoma"
|
||||||
|
|
||||||
|
strCheckCairo :: Text
|
||||||
|
strCheckCairo = "check-cairo"
|
||||||
|
|
||||||
strNormalize :: Text
|
strNormalize :: Text
|
||||||
strNormalize = "normalize"
|
strNormalize = "normalize"
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import Juvix.Compiler.Core.Error
|
|||||||
import Juvix.Compiler.Core.Options
|
import Juvix.Compiler.Core.Options
|
||||||
import Juvix.Compiler.Core.Transformation.Base
|
import Juvix.Compiler.Core.Transformation.Base
|
||||||
import Juvix.Compiler.Core.Transformation.Check.Anoma
|
import Juvix.Compiler.Core.Transformation.Check.Anoma
|
||||||
|
import Juvix.Compiler.Core.Transformation.Check.Cairo
|
||||||
import Juvix.Compiler.Core.Transformation.Check.Exec
|
import Juvix.Compiler.Core.Transformation.Check.Exec
|
||||||
import Juvix.Compiler.Core.Transformation.Check.Geb
|
import Juvix.Compiler.Core.Transformation.Check.Geb
|
||||||
import Juvix.Compiler.Core.Transformation.Check.VampIR
|
import Juvix.Compiler.Core.Transformation.Check.VampIR
|
||||||
@ -77,6 +78,7 @@ applyTransformations ts tbl = foldM (flip appTrans) tbl ts
|
|||||||
CheckExec -> mapError (JuvixError @CoreError) . checkExec
|
CheckExec -> mapError (JuvixError @CoreError) . checkExec
|
||||||
CheckVampIR -> mapError (JuvixError @CoreError) . checkVampIR
|
CheckVampIR -> mapError (JuvixError @CoreError) . checkVampIR
|
||||||
CheckAnoma -> mapError (JuvixError @CoreError) . checkAnoma
|
CheckAnoma -> mapError (JuvixError @CoreError) . checkAnoma
|
||||||
|
CheckCairo -> mapError (JuvixError @CoreError) . checkCairo
|
||||||
Normalize -> normalize
|
Normalize -> normalize
|
||||||
LetFolding -> return . letFolding
|
LetFolding -> return . letFolding
|
||||||
LambdaFolding -> return . lambdaFolding
|
LambdaFolding -> return . lambdaFolding
|
||||||
|
13
src/Juvix/Compiler/Core/Transformation/Check/Cairo.hs
Normal file
13
src/Juvix/Compiler/Core/Transformation/Check/Cairo.hs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module Juvix.Compiler.Core.Transformation.Check.Cairo where
|
||||||
|
|
||||||
|
import Juvix.Compiler.Core.Error
|
||||||
|
import Juvix.Compiler.Core.Extra
|
||||||
|
import Juvix.Compiler.Core.Transformation.Base
|
||||||
|
import Juvix.Compiler.Core.Transformation.Check.Base
|
||||||
|
|
||||||
|
checkCairo :: forall r. (Member (Error CoreError) r) => Module -> Sem r Module
|
||||||
|
checkCairo md = do
|
||||||
|
checkMainExists md
|
||||||
|
checkNoAxioms md
|
||||||
|
mapAllNodesM checkNoIO md
|
||||||
|
mapAllNodesM (checkBuiltins' [OpStrConcat, OpStrToInt, OpShow] [PrimString]) md
|
@ -16,6 +16,8 @@ import Juvix.Compiler.Backend qualified as Backend
|
|||||||
import Juvix.Compiler.Backend.C qualified as C
|
import Juvix.Compiler.Backend.C qualified as C
|
||||||
import Juvix.Compiler.Backend.Geb qualified as Geb
|
import Juvix.Compiler.Backend.Geb qualified as Geb
|
||||||
import Juvix.Compiler.Backend.VampIR.Translation qualified as VampIR
|
import Juvix.Compiler.Backend.VampIR.Translation qualified as VampIR
|
||||||
|
import Juvix.Compiler.Casm.Data.Result qualified as Casm
|
||||||
|
import Juvix.Compiler.Casm.Translation.FromReg qualified as Casm
|
||||||
import Juvix.Compiler.Concrete.Data.Highlight.Input
|
import Juvix.Compiler.Concrete.Data.Highlight.Input
|
||||||
import Juvix.Compiler.Concrete.Language
|
import Juvix.Compiler.Concrete.Language
|
||||||
import Juvix.Compiler.Concrete.Translation.FromParsed qualified as Scoper
|
import Juvix.Compiler.Concrete.Translation.FromParsed qualified as Scoper
|
||||||
@ -42,6 +44,7 @@ import Juvix.Compiler.Tree qualified as Tree
|
|||||||
import Juvix.Data.Effect.Git
|
import Juvix.Data.Effect.Git
|
||||||
import Juvix.Data.Effect.Process
|
import Juvix.Data.Effect.Process
|
||||||
import Juvix.Data.Effect.TaggedLock
|
import Juvix.Data.Effect.TaggedLock
|
||||||
|
import Juvix.Data.Field
|
||||||
|
|
||||||
type PipelineAppEffects = '[TaggedLock, EmbedIO, Resource, Final IO]
|
type PipelineAppEffects = '[TaggedLock, EmbedIO, Resource, Final IO]
|
||||||
|
|
||||||
@ -101,6 +104,12 @@ upToAsm ::
|
|||||||
upToAsm =
|
upToAsm =
|
||||||
upToStoredCore >>= \Core.CoreResult {..} -> storedCoreToAsm _coreResultModule
|
upToStoredCore >>= \Core.CoreResult {..} -> storedCoreToAsm _coreResultModule
|
||||||
|
|
||||||
|
upToCasm ::
|
||||||
|
(Members '[HighlightBuilder, Reader Parser.ParserResult, Reader EntryPoint, Reader Store.ModuleTable, Files, NameIdGen, Error JuvixError, GitClone, PathResolver] r) =>
|
||||||
|
Sem r Casm.Result
|
||||||
|
upToCasm =
|
||||||
|
upToStoredCore >>= \Core.CoreResult {..} -> storedCoreToCasm _coreResultModule
|
||||||
|
|
||||||
upToMiniC ::
|
upToMiniC ::
|
||||||
(Members '[HighlightBuilder, Reader Parser.ParserResult, Reader EntryPoint, Reader Store.ModuleTable, Files, NameIdGen, Error JuvixError, GitClone, PathResolver] r) =>
|
(Members '[HighlightBuilder, Reader Parser.ParserResult, Reader EntryPoint, Reader Store.ModuleTable, Files, NameIdGen, Error JuvixError, GitClone, PathResolver] r) =>
|
||||||
Sem r C.MiniCResult
|
Sem r C.MiniCResult
|
||||||
@ -153,6 +162,9 @@ storedCoreToReg = storedCoreToAsm >=> asmToReg
|
|||||||
storedCoreToMiniC :: (Members '[Error JuvixError, Reader EntryPoint] r) => Core.Module -> Sem r C.MiniCResult
|
storedCoreToMiniC :: (Members '[Error JuvixError, Reader EntryPoint] r) => Core.Module -> Sem r C.MiniCResult
|
||||||
storedCoreToMiniC = storedCoreToAsm >=> asmToMiniC
|
storedCoreToMiniC = storedCoreToAsm >=> asmToMiniC
|
||||||
|
|
||||||
|
storedCoreToCasm :: (Members '[Error JuvixError, Reader EntryPoint] r) => Core.Module -> Sem r Casm.Result
|
||||||
|
storedCoreToCasm = local (set entryPointFieldSize cairoFieldSize) . storedCoreToTree Core.CheckCairo >=> treeToCasm
|
||||||
|
|
||||||
storedCoreToGeb :: (Members '[Error JuvixError, Reader EntryPoint] r) => Geb.ResultSpec -> Core.Module -> Sem r Geb.Result
|
storedCoreToGeb :: (Members '[Error JuvixError, Reader EntryPoint] r) => Geb.ResultSpec -> Core.Module -> Sem r Geb.Result
|
||||||
storedCoreToGeb spec = Core.toGeb >=> return . uncurry (Geb.toResult spec) . Geb.fromCore . Core.computeCombinedInfoTable
|
storedCoreToGeb spec = Core.toGeb >=> return . uncurry (Geb.toResult spec) . Geb.fromCore . Core.computeCombinedInfoTable
|
||||||
|
|
||||||
@ -175,6 +187,9 @@ coreToAsm = Core.toStored >=> storedCoreToAsm
|
|||||||
coreToReg :: (Members '[Error JuvixError, Reader EntryPoint] r) => Core.Module -> Sem r Reg.InfoTable
|
coreToReg :: (Members '[Error JuvixError, Reader EntryPoint] r) => Core.Module -> Sem r Reg.InfoTable
|
||||||
coreToReg = Core.toStored >=> storedCoreToReg
|
coreToReg = Core.toStored >=> storedCoreToReg
|
||||||
|
|
||||||
|
coreToCasm :: (Members '[Error JuvixError, Reader EntryPoint] r) => Core.Module -> Sem r Casm.Result
|
||||||
|
coreToCasm = Core.toStored >=> storedCoreToCasm
|
||||||
|
|
||||||
coreToNockma :: (Members '[Error JuvixError, Reader EntryPoint] r) => Core.Module -> Sem r (Nockma.Cell Natural)
|
coreToNockma :: (Members '[Error JuvixError, Reader EntryPoint] r) => Core.Module -> Sem r (Nockma.Cell Natural)
|
||||||
coreToNockma = coreToTree Core.CheckAnoma >=> treeToNockma
|
coreToNockma = coreToTree Core.CheckAnoma >=> treeToNockma
|
||||||
|
|
||||||
@ -200,6 +215,9 @@ coreToVampIR' = Core.toStored' >=> storedCoreToVampIR'
|
|||||||
treeToAsm :: (Member (Error JuvixError) r) => Tree.InfoTable -> Sem r Asm.InfoTable
|
treeToAsm :: (Member (Error JuvixError) r) => Tree.InfoTable -> Sem r Asm.InfoTable
|
||||||
treeToAsm = Tree.toAsm >=> return . Asm.fromTree
|
treeToAsm = Tree.toAsm >=> return . Asm.fromTree
|
||||||
|
|
||||||
|
treeToCairoAsm :: (Member (Error JuvixError) r) => Tree.InfoTable -> Sem r Asm.InfoTable
|
||||||
|
treeToCairoAsm = Tree.toCairoAsm >=> return . Asm.fromTree
|
||||||
|
|
||||||
treeToReg :: (Members '[Error JuvixError, Reader EntryPoint] r) => Tree.InfoTable -> Sem r Reg.InfoTable
|
treeToReg :: (Members '[Error JuvixError, Reader EntryPoint] r) => Tree.InfoTable -> Sem r Reg.InfoTable
|
||||||
treeToReg = treeToAsm >=> asmToReg
|
treeToReg = treeToAsm >=> asmToReg
|
||||||
|
|
||||||
@ -212,9 +230,15 @@ treeToAnoma = Tree.toNockma >=> mapReader NockmaTree.fromEntryPoint . NockmaTree
|
|||||||
treeToMiniC :: (Members '[Error JuvixError, Reader EntryPoint] r) => Tree.InfoTable -> Sem r C.MiniCResult
|
treeToMiniC :: (Members '[Error JuvixError, Reader EntryPoint] r) => Tree.InfoTable -> Sem r C.MiniCResult
|
||||||
treeToMiniC = treeToAsm >=> asmToMiniC
|
treeToMiniC = treeToAsm >=> asmToMiniC
|
||||||
|
|
||||||
|
treeToCasm :: (Members '[Error JuvixError, Reader EntryPoint] r) => Tree.InfoTable -> Sem r Casm.Result
|
||||||
|
treeToCasm = treeToCairoAsm >=> asmToCasm
|
||||||
|
|
||||||
asmToReg :: (Members '[Error JuvixError, Reader EntryPoint] r) => Asm.InfoTable -> Sem r Reg.InfoTable
|
asmToReg :: (Members '[Error JuvixError, Reader EntryPoint] r) => Asm.InfoTable -> Sem r Reg.InfoTable
|
||||||
asmToReg = Asm.toReg >=> return . Reg.fromAsm
|
asmToReg = Asm.toReg >=> return . Reg.fromAsm
|
||||||
|
|
||||||
|
asmToCasm :: (Members '[Error JuvixError, Reader EntryPoint] r) => Asm.InfoTable -> Sem r Casm.Result
|
||||||
|
asmToCasm = asmToReg >=> regToCasm
|
||||||
|
|
||||||
asmToMiniC :: (Members '[Error JuvixError, Reader EntryPoint] r) => Asm.InfoTable -> Sem r C.MiniCResult
|
asmToMiniC :: (Members '[Error JuvixError, Reader EntryPoint] r) => Asm.InfoTable -> Sem r C.MiniCResult
|
||||||
asmToMiniC = asmToReg >=> regToMiniC
|
asmToMiniC = asmToReg >=> regToMiniC
|
||||||
|
|
||||||
@ -224,6 +248,9 @@ regToMiniC tab = do
|
|||||||
e <- ask
|
e <- ask
|
||||||
return $ C.fromReg (Backend.getLimits (e ^. entryPointTarget) (e ^. entryPointDebug)) tab'
|
return $ C.fromReg (Backend.getLimits (e ^. entryPointTarget) (e ^. entryPointDebug)) tab'
|
||||||
|
|
||||||
|
regToCasm :: Reg.InfoTable -> Sem r Casm.Result
|
||||||
|
regToCasm = Reg.toCasm >=> return . Casm.fromReg
|
||||||
|
|
||||||
treeToNockma' :: (Members '[Error JuvixError, Reader NockmaTree.CompilerOptions] r) => Tree.InfoTable -> Sem r (Nockma.Cell Natural)
|
treeToNockma' :: (Members '[Error JuvixError, Reader NockmaTree.CompilerOptions] r) => Tree.InfoTable -> Sem r (Nockma.Cell Natural)
|
||||||
treeToNockma' = Tree.toNockma >=> NockmaTree.fromTreeTable NockmaTree.ProgramCallingConventionJuvix
|
treeToNockma' = Tree.toNockma >=> NockmaTree.fromTreeTable NockmaTree.ProgramCallingConventionJuvix
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ data TransformationId
|
|||||||
deriving stock (Data, Bounded, Enum, Show)
|
deriving stock (Data, Bounded, Enum, Show)
|
||||||
|
|
||||||
data PipelineId
|
data PipelineId
|
||||||
= PipelineCairo
|
= PipelineCasm
|
||||||
| PipelineC
|
| PipelineC
|
||||||
deriving stock (Data, Bounded, Enum)
|
deriving stock (Data, Bounded, Enum)
|
||||||
|
|
||||||
@ -21,8 +21,8 @@ type TransformationLikeId = TransformationLikeId' TransformationId PipelineId
|
|||||||
toCTransformations :: [TransformationId]
|
toCTransformations :: [TransformationId]
|
||||||
toCTransformations = [Cleanup]
|
toCTransformations = [Cleanup]
|
||||||
|
|
||||||
toCairoTransformations :: [TransformationId]
|
toCasmTransformations :: [TransformationId]
|
||||||
toCairoTransformations = [Cleanup, SSA, InitBranchVars]
|
toCasmTransformations = [Cleanup, SSA, InitBranchVars]
|
||||||
|
|
||||||
instance TransformationId' TransformationId where
|
instance TransformationId' TransformationId where
|
||||||
transformationText :: TransformationId -> Text
|
transformationText :: TransformationId -> Text
|
||||||
@ -36,9 +36,9 @@ instance PipelineId' TransformationId PipelineId where
|
|||||||
pipelineText :: PipelineId -> Text
|
pipelineText :: PipelineId -> Text
|
||||||
pipelineText = \case
|
pipelineText = \case
|
||||||
PipelineC -> strCPipeline
|
PipelineC -> strCPipeline
|
||||||
PipelineCairo -> strCairoPipeline
|
PipelineCasm -> strCasmPipeline
|
||||||
|
|
||||||
pipeline :: PipelineId -> [TransformationId]
|
pipeline :: PipelineId -> [TransformationId]
|
||||||
pipeline = \case
|
pipeline = \case
|
||||||
PipelineC -> toCTransformations
|
PipelineC -> toCTransformations
|
||||||
PipelineCairo -> toCairoTransformations
|
PipelineCasm -> toCasmTransformations
|
||||||
|
@ -5,8 +5,8 @@ import Juvix.Prelude
|
|||||||
strCPipeline :: Text
|
strCPipeline :: Text
|
||||||
strCPipeline = "pipeline-c"
|
strCPipeline = "pipeline-c"
|
||||||
|
|
||||||
strCairoPipeline :: Text
|
strCasmPipeline :: Text
|
||||||
strCairoPipeline = "pipeline-cairo"
|
strCasmPipeline = "pipeline-casm"
|
||||||
|
|
||||||
strIdentity :: Text
|
strIdentity :: Text
|
||||||
strIdentity = "identity"
|
strIdentity = "identity"
|
||||||
|
@ -196,8 +196,13 @@ computeLocalVarsNum = maximum . map go
|
|||||||
|
|
||||||
data ExtraInfo = ExtraInfo
|
data ExtraInfo = ExtraInfo
|
||||||
{ _extraInfoTable :: InfoTable,
|
{ _extraInfoTable :: InfoTable,
|
||||||
|
-- | Globally unique IDs for constructor tags
|
||||||
_extraInfoUIDs :: HashMap Tag Int,
|
_extraInfoUIDs :: HashMap Tag Int,
|
||||||
|
-- | Globally unique IDs for function symbols
|
||||||
_extraInfoFUIDs :: HashMap Symbol Int,
|
_extraInfoFUIDs :: HashMap Symbol Int,
|
||||||
|
-- | IDs for constructor tags, consecutive starting from 0 for each
|
||||||
|
-- inductive type separately
|
||||||
|
_extraInfoCIDs :: HashMap Tag Int,
|
||||||
_extraInfoStringMap :: HashMap Text Int,
|
_extraInfoStringMap :: HashMap Text Int,
|
||||||
_extraInfoMaxStackHeight :: HashMap Symbol Int,
|
_extraInfoMaxStackHeight :: HashMap Symbol Int,
|
||||||
_extraInfoLocalVarsNum :: HashMap Symbol Int,
|
_extraInfoLocalVarsNum :: HashMap Symbol Int,
|
||||||
@ -226,12 +231,19 @@ computeFUIDs tab =
|
|||||||
(HashMap.elems (tab ^. infoFunctions))
|
(HashMap.elems (tab ^. infoFunctions))
|
||||||
[0 ..]
|
[0 ..]
|
||||||
|
|
||||||
|
computeCIDs :: InfoTable -> HashMap Tag Int
|
||||||
|
computeCIDs tab = HashMap.fromList $ concatMap go (tab ^. infoInductives)
|
||||||
|
where
|
||||||
|
go :: InductiveInfo -> [(Tag, Int)]
|
||||||
|
go InductiveInfo {..} = zip _inductiveConstructors [0 ..]
|
||||||
|
|
||||||
computeExtraInfo :: Limits -> InfoTable -> ExtraInfo
|
computeExtraInfo :: Limits -> InfoTable -> ExtraInfo
|
||||||
computeExtraInfo lims tab =
|
computeExtraInfo lims tab =
|
||||||
ExtraInfo
|
ExtraInfo
|
||||||
{ _extraInfoTable = tab,
|
{ _extraInfoTable = tab,
|
||||||
_extraInfoUIDs = computeUIDs lims tab,
|
_extraInfoUIDs = computeUIDs lims tab,
|
||||||
_extraInfoFUIDs = computeFUIDs tab,
|
_extraInfoFUIDs = computeFUIDs tab,
|
||||||
|
_extraInfoCIDs = computeCIDs tab,
|
||||||
_extraInfoStringMap =
|
_extraInfoStringMap =
|
||||||
foldr
|
foldr
|
||||||
(\fi mp -> computeStringMap mp (fi ^. functionCode))
|
(\fi mp -> computeStringMap mp (fi ^. functionCode))
|
||||||
|
@ -65,15 +65,6 @@ runFunction hout infoTable args0 info0 = do
|
|||||||
[] ->
|
[] ->
|
||||||
return $ ValVoid
|
return $ ValVoid
|
||||||
|
|
||||||
readConst :: Constant -> Val
|
|
||||||
readConst = \case
|
|
||||||
ConstInt i -> ValInteger i
|
|
||||||
ConstField f -> ValField f
|
|
||||||
ConstBool b -> ValBool b
|
|
||||||
ConstString s -> ValString s
|
|
||||||
ConstUnit -> ValUnit
|
|
||||||
ConstVoid -> ValVoid
|
|
||||||
|
|
||||||
readVarRef :: Args -> Vars s -> VarRef -> ST s Val
|
readVarRef :: Args -> Vars s -> VarRef -> ST s Val
|
||||||
readVarRef args tmps VarRef {..} = case _varRefGroup of
|
readVarRef args tmps VarRef {..} = case _varRefGroup of
|
||||||
VarGroupArgs -> return $ args Vec.! _varRefIndex
|
VarGroupArgs -> return $ args Vec.! _varRefIndex
|
||||||
@ -97,7 +88,7 @@ runFunction hout infoTable args0 info0 = do
|
|||||||
|
|
||||||
readValue :: Args -> Vars s -> Value -> ST s Val
|
readValue :: Args -> Vars s -> Value -> ST s Val
|
||||||
readValue args tmps = \case
|
readValue args tmps = \case
|
||||||
Const c -> return $ readConst c
|
Const c -> return $ constantToValue c
|
||||||
CRef r -> readConstrRef args tmps r
|
CRef r -> readConstrRef args tmps r
|
||||||
VRef r -> readVarRef args tmps r
|
VRef r -> readVarRef args tmps r
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ data ConstrField = ConstrField
|
|||||||
_constrFieldMemRep :: MemRep,
|
_constrFieldMemRep :: MemRep,
|
||||||
-- | Location where the data is stored.
|
-- | Location where the data is stored.
|
||||||
_constrFieldRef :: VarRef,
|
_constrFieldRef :: VarRef,
|
||||||
|
-- | Index of the constructor argument being referenced.
|
||||||
_constrFieldIndex :: Index
|
_constrFieldIndex :: Index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import Juvix.Compiler.Reg.Transformation
|
|||||||
toC :: InfoTable -> Sem r InfoTable
|
toC :: InfoTable -> Sem r InfoTable
|
||||||
toC = applyTransformations toCTransformations
|
toC = applyTransformations toCTransformations
|
||||||
|
|
||||||
-- | Perform transformations on JuvixReg necessary before the translation to Cairo
|
-- | Perform transformations on JuvixReg necessary before the translation to
|
||||||
toCairo :: InfoTable -> Sem r InfoTable
|
-- Cairo assembly
|
||||||
toCairo = applyTransformations toCairoTransformations
|
toCasm :: InfoTable -> Sem r InfoTable
|
||||||
|
toCasm = applyTransformations toCasmTransformations
|
||||||
|
@ -17,6 +17,7 @@ data TransformationId
|
|||||||
data PipelineId
|
data PipelineId
|
||||||
= PipelineNockma
|
= PipelineNockma
|
||||||
| PipelineAsm
|
| PipelineAsm
|
||||||
|
| PipelineCairoAsm
|
||||||
deriving stock (Data, Bounded, Enum)
|
deriving stock (Data, Bounded, Enum)
|
||||||
|
|
||||||
type TransformationLikeId = TransformationLikeId' TransformationId PipelineId
|
type TransformationLikeId = TransformationLikeId' TransformationId PipelineId
|
||||||
@ -27,6 +28,9 @@ toNockmaTransformations = [Validate, Apply, FilterUnreachable, TempHeight]
|
|||||||
toAsmTransformations :: [TransformationId]
|
toAsmTransformations :: [TransformationId]
|
||||||
toAsmTransformations = [Validate]
|
toAsmTransformations = [Validate]
|
||||||
|
|
||||||
|
toCairoAsmTransformations :: [TransformationId]
|
||||||
|
toCairoAsmTransformations = [Validate, Apply, FilterUnreachable]
|
||||||
|
|
||||||
instance TransformationId' TransformationId where
|
instance TransformationId' TransformationId where
|
||||||
transformationText :: TransformationId -> Text
|
transformationText :: TransformationId -> Text
|
||||||
transformationText = \case
|
transformationText = \case
|
||||||
@ -43,8 +47,10 @@ instance PipelineId' TransformationId PipelineId where
|
|||||||
pipelineText = \case
|
pipelineText = \case
|
||||||
PipelineNockma -> strNockmaPipeline
|
PipelineNockma -> strNockmaPipeline
|
||||||
PipelineAsm -> strAsmPipeline
|
PipelineAsm -> strAsmPipeline
|
||||||
|
PipelineCairoAsm -> strCairoAsmPipeline
|
||||||
|
|
||||||
pipeline :: PipelineId -> [TransformationId]
|
pipeline :: PipelineId -> [TransformationId]
|
||||||
pipeline = \case
|
pipeline = \case
|
||||||
PipelineNockma -> toNockmaTransformations
|
PipelineNockma -> toNockmaTransformations
|
||||||
PipelineAsm -> toAsmTransformations
|
PipelineAsm -> toAsmTransformations
|
||||||
|
PipelineCairoAsm -> toCairoAsmTransformations
|
||||||
|
@ -8,6 +8,9 @@ strNockmaPipeline = "pipeline-nockma"
|
|||||||
strAsmPipeline :: Text
|
strAsmPipeline :: Text
|
||||||
strAsmPipeline = "pipeline-asm"
|
strAsmPipeline = "pipeline-asm"
|
||||||
|
|
||||||
|
strCairoAsmPipeline :: Text
|
||||||
|
strCairoAsmPipeline = "pipeline-cairo-asm"
|
||||||
|
|
||||||
strIdentity :: Text
|
strIdentity :: Text
|
||||||
strIdentity = "identity"
|
strIdentity = "identity"
|
||||||
|
|
||||||
|
@ -81,13 +81,7 @@ hEval hout tab = eval' [] mempty
|
|||||||
goTrace v = unsafePerformIO (hPutStrLn hout (printValue tab v) >> return v)
|
goTrace v = unsafePerformIO (hPutStrLn hout (printValue tab v) >> return v)
|
||||||
|
|
||||||
goConstant :: NodeConstant -> Value
|
goConstant :: NodeConstant -> Value
|
||||||
goConstant NodeConstant {..} = case _nodeConstant of
|
goConstant NodeConstant {..} = constantToValue _nodeConstant
|
||||||
ConstInt i -> ValInteger i
|
|
||||||
ConstField f -> ValField f
|
|
||||||
ConstBool b -> ValBool b
|
|
||||||
ConstString s -> ValString s
|
|
||||||
ConstUnit -> ValUnit
|
|
||||||
ConstVoid -> ValVoid
|
|
||||||
|
|
||||||
goMemRef :: NodeMemRef -> Value
|
goMemRef :: NodeMemRef -> Value
|
||||||
goMemRef NodeMemRef {..} = case _nodeMemRef of
|
goMemRef NodeMemRef {..} = case _nodeMemRef of
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
module Juvix.Compiler.Tree.Evaluator.Builtins where
|
module Juvix.Compiler.Tree.Evaluator.Builtins where
|
||||||
|
|
||||||
import Juvix.Compiler.Tree.Data.InfoTable.Base
|
import Juvix.Compiler.Tree.Data.InfoTable.Base
|
||||||
|
import Juvix.Compiler.Tree.Language.Base
|
||||||
import Juvix.Compiler.Tree.Language.Builtins
|
import Juvix.Compiler.Tree.Language.Builtins
|
||||||
import Juvix.Compiler.Tree.Language.Value
|
import Juvix.Compiler.Tree.Language.Value
|
||||||
import Juvix.Compiler.Tree.Pretty.Base
|
import Juvix.Compiler.Tree.Pretty.Base
|
||||||
import Juvix.Data.Field
|
import Juvix.Data.Field
|
||||||
import Juvix.Data.PPOutput
|
import Juvix.Data.PPOutput
|
||||||
import Juvix.Prelude
|
|
||||||
import Text.Read qualified as T
|
import Text.Read qualified as T
|
||||||
|
|
||||||
type ErrorMsg = Text
|
type ErrorMsg = Text
|
||||||
@ -104,3 +104,32 @@ printValue :: InfoTable' t e -> Value -> Text
|
|||||||
printValue tab = \case
|
printValue tab = \case
|
||||||
ValString s -> s
|
ValString s -> s
|
||||||
v -> toPlainText . mkAnsiText . PPOutput . doc (defaultOptions tab) $ v
|
v -> toPlainText . mkAnsiText . PPOutput . doc (defaultOptions tab) $ v
|
||||||
|
|
||||||
|
constantToValue :: Constant -> Value
|
||||||
|
constantToValue = \case
|
||||||
|
ConstInt i -> ValInteger i
|
||||||
|
ConstField f -> ValField f
|
||||||
|
ConstBool b -> ValBool b
|
||||||
|
ConstString s -> ValString s
|
||||||
|
ConstUnit -> ValUnit
|
||||||
|
ConstVoid -> ValVoid
|
||||||
|
|
||||||
|
valueToConstant :: Value -> Constant
|
||||||
|
valueToConstant = \case
|
||||||
|
ValInteger i -> ConstInt i
|
||||||
|
ValField f -> ConstField f
|
||||||
|
ValBool b -> ConstBool b
|
||||||
|
ValString s -> ConstString s
|
||||||
|
ValUnit -> ConstUnit
|
||||||
|
ValVoid -> ConstVoid
|
||||||
|
_ -> impossible
|
||||||
|
|
||||||
|
evalBinop' :: BinaryOp -> Constant -> Constant -> Either ErrorMsg Constant
|
||||||
|
evalBinop' op arg1 arg2 =
|
||||||
|
mapRight valueToConstant $
|
||||||
|
evalBinop op (constantToValue arg1) (constantToValue arg2)
|
||||||
|
|
||||||
|
evalUnop' :: InfoTable' t e -> UnaryOp -> Constant -> Either ErrorMsg Constant
|
||||||
|
evalUnop' tab op v =
|
||||||
|
mapRight valueToConstant $
|
||||||
|
evalUnop tab op (constantToValue v)
|
||||||
|
@ -77,13 +77,7 @@ eval tab = E.runReader emptyEvalCtx . eval'
|
|||||||
goTrace v = E.output v $> v
|
goTrace v = E.output v $> v
|
||||||
|
|
||||||
goConstant :: NodeConstant -> Value
|
goConstant :: NodeConstant -> Value
|
||||||
goConstant NodeConstant {..} = case _nodeConstant of
|
goConstant NodeConstant {..} = constantToValue _nodeConstant
|
||||||
ConstInt i -> ValInteger i
|
|
||||||
ConstField f -> ValField f
|
|
||||||
ConstBool b -> ValBool b
|
|
||||||
ConstString s -> ValString s
|
|
||||||
ConstUnit -> ValUnit
|
|
||||||
ConstVoid -> ValVoid
|
|
||||||
|
|
||||||
askTemp :: Eff r' (BL.BinderList Value)
|
askTemp :: Eff r' (BL.BinderList Value)
|
||||||
askTemp = E.asks (^. evalCtxTemp)
|
askTemp = E.asks (^. evalCtxTemp)
|
||||||
|
@ -75,13 +75,7 @@ eval tab = runReader emptyEvalCtx . eval'
|
|||||||
goTrace v = output v $> v
|
goTrace v = output v $> v
|
||||||
|
|
||||||
goConstant :: NodeConstant -> Value
|
goConstant :: NodeConstant -> Value
|
||||||
goConstant NodeConstant {..} = case _nodeConstant of
|
goConstant NodeConstant {..} = constantToValue _nodeConstant
|
||||||
ConstInt i -> ValInteger i
|
|
||||||
ConstField f -> ValField f
|
|
||||||
ConstBool b -> ValBool b
|
|
||||||
ConstString s -> ValString s
|
|
||||||
ConstUnit -> ValUnit
|
|
||||||
ConstVoid -> ValVoid
|
|
||||||
|
|
||||||
askTemp :: Sem r' (BL.BinderList Value)
|
askTemp :: Sem r' (BL.BinderList Value)
|
||||||
askTemp = asks (^. evalCtxTemp)
|
askTemp = asks (^. evalCtxTemp)
|
||||||
|
@ -12,3 +12,6 @@ toNockma = applyTransformations toNockmaTransformations
|
|||||||
|
|
||||||
toAsm :: (Member (Error JuvixError) r) => InfoTable -> Sem r InfoTable
|
toAsm :: (Member (Error JuvixError) r) => InfoTable -> Sem r InfoTable
|
||||||
toAsm = applyTransformations toAsmTransformations
|
toAsm = applyTransformations toAsmTransformations
|
||||||
|
|
||||||
|
toCairoAsm :: (Member (Error JuvixError) r) => InfoTable -> Sem r InfoTable
|
||||||
|
toCairoAsm = applyTransformations toCairoAsmTransformations
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
module Casm where
|
module Casm where
|
||||||
|
|
||||||
import Base
|
import Base
|
||||||
|
import Casm.Compilation qualified as Compile
|
||||||
|
import Casm.Reg qualified as Reg
|
||||||
import Casm.Run qualified as Run
|
import Casm.Run qualified as Run
|
||||||
|
|
||||||
allTests :: TestTree
|
allTests :: TestTree
|
||||||
allTests = testGroup "CASM tests" [Run.allTests]
|
allTests = testGroup "CASM tests" [Run.allTests, Reg.allTests, Compile.allTests]
|
||||||
|
7
test/Casm/Compilation.hs
Normal file
7
test/Casm/Compilation.hs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module Casm.Compilation where
|
||||||
|
|
||||||
|
import Base
|
||||||
|
import Casm.Compilation.Positive qualified as P
|
||||||
|
|
||||||
|
allTests :: TestTree
|
||||||
|
allTests = testGroup "Juvix to CASM compilation" [P.allTests, P.allTestsNoOptimize]
|
52
test/Casm/Compilation/Base.hs
Normal file
52
test/Casm/Compilation/Base.hs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
module Casm.Compilation.Base where
|
||||||
|
|
||||||
|
import Base
|
||||||
|
import Juvix.Compiler.Casm.Data.Result
|
||||||
|
import Juvix.Compiler.Casm.Interpreter
|
||||||
|
import Juvix.Compiler.Casm.Pretty
|
||||||
|
import Juvix.Compiler.Core qualified as Core
|
||||||
|
import Juvix.Data.Field
|
||||||
|
import Juvix.Data.PPOutput
|
||||||
|
|
||||||
|
compileAssertion ::
|
||||||
|
Path Abs Dir ->
|
||||||
|
Int ->
|
||||||
|
Path Abs File ->
|
||||||
|
Path Abs File ->
|
||||||
|
(String -> IO ()) ->
|
||||||
|
Assertion
|
||||||
|
compileAssertion = compileAssertionEntry (\e -> e {_entryPointFieldSize = cairoFieldSize})
|
||||||
|
|
||||||
|
compileAssertionEntry ::
|
||||||
|
(EntryPoint -> EntryPoint) ->
|
||||||
|
Path Abs Dir ->
|
||||||
|
Int ->
|
||||||
|
Path Abs File ->
|
||||||
|
Path Abs File ->
|
||||||
|
(String -> IO ()) ->
|
||||||
|
Assertion
|
||||||
|
compileAssertionEntry adjustEntry root' optLevel mainFile expectedFile step = do
|
||||||
|
step "Translate to JuvixCore"
|
||||||
|
entryPoint <- adjustEntry <$> testDefaultEntryPointIO root' mainFile
|
||||||
|
PipelineResult {..} <- snd <$> testRunIO entryPoint upToStoredCore
|
||||||
|
step "Translate to CASM"
|
||||||
|
let entryPoint' = entryPoint {_entryPointOptimizationLevel = optLevel}
|
||||||
|
case run $ runError @JuvixError $ runReader entryPoint' $ storedCoreToCasm (_pipelineResult ^. Core.coreResultModule) of
|
||||||
|
Left err -> assertFailure (show (pretty (fromJuvixError @GenericError err)))
|
||||||
|
Right Result {..} -> do
|
||||||
|
withTempDir'
|
||||||
|
( \dirPath -> do
|
||||||
|
let outputFile = dirPath <//> $(mkRelFile "out.out")
|
||||||
|
let tmpFile = dirPath <//> $(mkRelFile "tmp.out")
|
||||||
|
step "Serialize"
|
||||||
|
writeFileEnsureLn tmpFile (toPlainText $ ppProgram _resultCode)
|
||||||
|
hout <- openFile (toFilePath outputFile) WriteMode
|
||||||
|
step "Interpret"
|
||||||
|
let v = hRunCode hout _resultLabelInfo _resultCode
|
||||||
|
hPutStrLn hout (show v)
|
||||||
|
hClose hout
|
||||||
|
actualOutput <- readFile outputFile
|
||||||
|
step "Compare expected and actual program output"
|
||||||
|
expected <- readFile expectedFile
|
||||||
|
assertEqDiffText ("Check: RUN output = " <> toFilePath expectedFile) actualOutput expected
|
||||||
|
)
|
353
test/Casm/Compilation/Positive.hs
Normal file
353
test/Casm/Compilation/Positive.hs
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
module Casm.Compilation.Positive where
|
||||||
|
|
||||||
|
import Base
|
||||||
|
import Casm.Compilation.Base
|
||||||
|
import Data.HashSet qualified as HashSet
|
||||||
|
|
||||||
|
data PosTest = PosTest
|
||||||
|
{ _name :: String,
|
||||||
|
_dir :: Path Abs Dir,
|
||||||
|
_file :: Path Abs File,
|
||||||
|
_expectedFile :: Path Abs File
|
||||||
|
}
|
||||||
|
|
||||||
|
makeLenses ''PosTest
|
||||||
|
|
||||||
|
root :: Path Abs Dir
|
||||||
|
root = relToProject $(mkRelDir "tests/Casm/Compilation/positive/")
|
||||||
|
|
||||||
|
toTestDescr :: Int -> PosTest -> TestDescr
|
||||||
|
toTestDescr optLevel PosTest {..} =
|
||||||
|
let tRoot = _dir
|
||||||
|
file' = _file
|
||||||
|
expected' = _expectedFile
|
||||||
|
in TestDescr
|
||||||
|
{ _testName = _name,
|
||||||
|
_testRoot = tRoot,
|
||||||
|
_testAssertion = Steps $ compileAssertion _dir optLevel file' expected'
|
||||||
|
}
|
||||||
|
|
||||||
|
allTests :: TestTree
|
||||||
|
allTests =
|
||||||
|
testGroup
|
||||||
|
"Juvix to CASM positive tests"
|
||||||
|
(map (mkTest . toTestDescr 3) tests)
|
||||||
|
|
||||||
|
allTestsNoOptimize :: TestTree
|
||||||
|
allTestsNoOptimize =
|
||||||
|
testGroup
|
||||||
|
"Juvix to CASM positive tests (no optimization)"
|
||||||
|
(map (mkTest . toTestDescr 0) tests)
|
||||||
|
|
||||||
|
posTest :: String -> Path Rel Dir -> Path Rel File -> Path Rel File -> PosTest
|
||||||
|
posTest _name rdir rfile routfile =
|
||||||
|
let _dir = root <//> rdir
|
||||||
|
_file = _dir <//> rfile
|
||||||
|
_expectedFile = root <//> routfile
|
||||||
|
in PosTest {..}
|
||||||
|
|
||||||
|
isIgnored :: PosTest -> Bool
|
||||||
|
isIgnored t = HashSet.member (t ^. name) ignored
|
||||||
|
|
||||||
|
ignored :: HashSet String
|
||||||
|
ignored =
|
||||||
|
HashSet.fromList
|
||||||
|
[ -- strings not supported (Partial trait)
|
||||||
|
"Test026: Functional queues"
|
||||||
|
]
|
||||||
|
|
||||||
|
tests :: [PosTest]
|
||||||
|
tests =
|
||||||
|
filter
|
||||||
|
(not . isIgnored)
|
||||||
|
[ posTest
|
||||||
|
"Test001: Arithmetic operators"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test001.juvix")
|
||||||
|
$(mkRelFile "out/test001.out"),
|
||||||
|
posTest
|
||||||
|
"Test002: Arithmetic operators inside lambdas"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test002.juvix")
|
||||||
|
$(mkRelFile "out/test002.out"),
|
||||||
|
posTest
|
||||||
|
"Test003: Integer arithmetic"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test003.juvix")
|
||||||
|
$(mkRelFile "out/test003.out"),
|
||||||
|
posTest
|
||||||
|
"Test005: Higher-order functions"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test005.juvix")
|
||||||
|
$(mkRelFile "out/test005.out"),
|
||||||
|
posTest
|
||||||
|
"Test006: If-then-else and lazy boolean operators"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test006.juvix")
|
||||||
|
$(mkRelFile "out/test006.out"),
|
||||||
|
posTest
|
||||||
|
"Test007: Pattern matching and lambda-case"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test007.juvix")
|
||||||
|
$(mkRelFile "out/test007.out"),
|
||||||
|
posTest
|
||||||
|
"Test008: Recursion"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test008.juvix")
|
||||||
|
$(mkRelFile "out/test008.out"),
|
||||||
|
posTest
|
||||||
|
"Test009: Tail recursion"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test009.juvix")
|
||||||
|
$(mkRelFile "out/test009.out"),
|
||||||
|
posTest
|
||||||
|
"Test010: Let"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test010.juvix")
|
||||||
|
$(mkRelFile "out/test010.out"),
|
||||||
|
posTest
|
||||||
|
"Test013: Functions returning functions with variable capture"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test013.juvix")
|
||||||
|
$(mkRelFile "out/test013.out"),
|
||||||
|
posTest
|
||||||
|
"Test014: Arithmetic"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test014.juvix")
|
||||||
|
$(mkRelFile "out/test014.out"),
|
||||||
|
posTest
|
||||||
|
"Test015: Local functions with free variables"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test015.juvix")
|
||||||
|
$(mkRelFile "out/test015.out"),
|
||||||
|
posTest
|
||||||
|
"Test016: Recursion through higher-order functions"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test016.juvix")
|
||||||
|
$(mkRelFile "out/test016.out"),
|
||||||
|
posTest
|
||||||
|
"Test017: Tail recursion through higher-order functions"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test017.juvix")
|
||||||
|
$(mkRelFile "out/test017.out"),
|
||||||
|
posTest
|
||||||
|
"Test018: Higher-order functions and recursion"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test018.juvix")
|
||||||
|
$(mkRelFile "out/test018.out"),
|
||||||
|
posTest
|
||||||
|
"Test019: Self-application"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test019.juvix")
|
||||||
|
$(mkRelFile "out/test019.out"),
|
||||||
|
posTest
|
||||||
|
"Test020: Recursive functions: McCarthy's 91 function, subtraction by increments"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test020.juvix")
|
||||||
|
$(mkRelFile "out/test020.out"),
|
||||||
|
posTest
|
||||||
|
"Test021: Fast exponentiation"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test021.juvix")
|
||||||
|
$(mkRelFile "out/test021.out"),
|
||||||
|
posTest
|
||||||
|
"Test022: Lists"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test022.juvix")
|
||||||
|
$(mkRelFile "out/test022.out"),
|
||||||
|
posTest
|
||||||
|
"Test023: Mutual recursion"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test023.juvix")
|
||||||
|
$(mkRelFile "out/test023.out"),
|
||||||
|
posTest
|
||||||
|
"Test024: Nested binders with variable capture"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test024.juvix")
|
||||||
|
$(mkRelFile "out/test024.out"),
|
||||||
|
posTest
|
||||||
|
"Test025: Euclid's algorithm"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test025.juvix")
|
||||||
|
$(mkRelFile "out/test025.out"),
|
||||||
|
posTest
|
||||||
|
"Test026: Functional queues"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test026.juvix")
|
||||||
|
$(mkRelFile "out/test026.out"),
|
||||||
|
posTest
|
||||||
|
"Test028: Streams without memoization"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test028.juvix")
|
||||||
|
$(mkRelFile "out/test028.out"),
|
||||||
|
posTest
|
||||||
|
"Test029: Ackermann function"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test029.juvix")
|
||||||
|
$(mkRelFile "out/test029.out"),
|
||||||
|
posTest
|
||||||
|
"Test030: Ackermann function (higher-order definition)"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test030.juvix")
|
||||||
|
$(mkRelFile "out/test030.out"),
|
||||||
|
posTest
|
||||||
|
"Test032: Merge sort"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test032.juvix")
|
||||||
|
$(mkRelFile "out/test032.out"),
|
||||||
|
posTest
|
||||||
|
"Test033: Eta-expansion of builtins and constructors"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test033.juvix")
|
||||||
|
$(mkRelFile "out/test033.out"),
|
||||||
|
posTest
|
||||||
|
"Test034: Recursive let"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test034.juvix")
|
||||||
|
$(mkRelFile "out/test034.out"),
|
||||||
|
posTest
|
||||||
|
"Test035: Pattern matching"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test035.juvix")
|
||||||
|
$(mkRelFile "out/test035.out"),
|
||||||
|
posTest
|
||||||
|
"Test036: Eta-expansion"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test036.juvix")
|
||||||
|
$(mkRelFile "out/test036.out"),
|
||||||
|
posTest
|
||||||
|
"Test037: Applications with lets and cases in function position"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test037.juvix")
|
||||||
|
$(mkRelFile "out/test037.out"),
|
||||||
|
posTest
|
||||||
|
"Test038: Simple case expression"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test038.juvix")
|
||||||
|
$(mkRelFile "out/test038.out"),
|
||||||
|
posTest
|
||||||
|
"Test039: Mutually recursive let expression"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test039.juvix")
|
||||||
|
$(mkRelFile "out/test039.out"),
|
||||||
|
posTest
|
||||||
|
"Test040: Pattern matching nullary constructor"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test040.juvix")
|
||||||
|
$(mkRelFile "out/test040.out"),
|
||||||
|
posTest
|
||||||
|
"Test045: Implicit builtin bool"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test045.juvix")
|
||||||
|
$(mkRelFile "out/test045.out"),
|
||||||
|
posTest
|
||||||
|
"Test046: Polymorphic type arguments"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test046.juvix")
|
||||||
|
$(mkRelFile "out/test046.out"),
|
||||||
|
posTest
|
||||||
|
"Test047: Local Modules"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test047.juvix")
|
||||||
|
$(mkRelFile "out/test047.out"),
|
||||||
|
posTest
|
||||||
|
"Test050: Pattern matching with integers"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test050.juvix")
|
||||||
|
$(mkRelFile "out/test050.out"),
|
||||||
|
posTest
|
||||||
|
"Test053: Inlining"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test053.juvix")
|
||||||
|
$(mkRelFile "out/test053.out"),
|
||||||
|
posTest
|
||||||
|
"Test054: Iterators"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test054.juvix")
|
||||||
|
$(mkRelFile "out/test054.out"),
|
||||||
|
posTest
|
||||||
|
"Test056: Argument specialization"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test056.juvix")
|
||||||
|
$(mkRelFile "out/test056.out"),
|
||||||
|
posTest
|
||||||
|
"Test057: Case folding"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test057.juvix")
|
||||||
|
$(mkRelFile "out/test057.out"),
|
||||||
|
posTest
|
||||||
|
"Test058: Ranges"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test058.juvix")
|
||||||
|
$(mkRelFile "out/test058.out"),
|
||||||
|
posTest
|
||||||
|
"Test059: Builtin list"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test059.juvix")
|
||||||
|
$(mkRelFile "out/test059.out"),
|
||||||
|
posTest
|
||||||
|
"Test060: Record update"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test060.juvix")
|
||||||
|
$(mkRelFile "out/test060.out"),
|
||||||
|
posTest
|
||||||
|
"Test062: Overapplication"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test062.juvix")
|
||||||
|
$(mkRelFile "out/test062.out"),
|
||||||
|
posTest
|
||||||
|
"Test064: Constant folding"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test064.juvix")
|
||||||
|
$(mkRelFile "out/test064.out"),
|
||||||
|
posTest
|
||||||
|
"Test065: Arithmetic simplification"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test065.juvix")
|
||||||
|
$(mkRelFile "out/test065.out"),
|
||||||
|
posTest
|
||||||
|
"Test066: Import function with a function call in default argument"
|
||||||
|
$(mkRelDir "test066")
|
||||||
|
$(mkRelFile "M.juvix")
|
||||||
|
$(mkRelFile "out/test066.out"),
|
||||||
|
posTest
|
||||||
|
"Test067: Dependent default values inserted during translation FromConcrete"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test067.juvix")
|
||||||
|
$(mkRelFile "out/test067.out"),
|
||||||
|
posTest
|
||||||
|
"Test068: Dependent default values inserted in the arity checker"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test068.juvix")
|
||||||
|
$(mkRelFile "out/test068.out"),
|
||||||
|
posTest
|
||||||
|
"Test069: Dependent default values for Ord trait"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test069.juvix")
|
||||||
|
$(mkRelFile "out/test069.out"),
|
||||||
|
posTest
|
||||||
|
"Test070: Nested default values and named arguments"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test070.juvix")
|
||||||
|
$(mkRelFile "out/test070.out"),
|
||||||
|
posTest
|
||||||
|
"Test071: Named application (Ord instance with default cmp)"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test071.juvix")
|
||||||
|
$(mkRelFile "out/test071.out"),
|
||||||
|
posTest
|
||||||
|
"Test072: Monad transformers (ReaderT + StateT + Identity)"
|
||||||
|
$(mkRelDir "test072")
|
||||||
|
$(mkRelFile "ReaderT.juvix")
|
||||||
|
$(mkRelFile "out/test072.out"),
|
||||||
|
posTest
|
||||||
|
"Test073: Import and use a syntax alias"
|
||||||
|
$(mkRelDir "test073")
|
||||||
|
$(mkRelFile "test073.juvix")
|
||||||
|
$(mkRelFile "out/test073.out"),
|
||||||
|
posTest
|
||||||
|
"Test074: Fields"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test074.juvix")
|
||||||
|
$(mkRelFile "out/test074.out")
|
||||||
|
]
|
7
test/Casm/Reg.hs
Normal file
7
test/Casm/Reg.hs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module Casm.Reg where
|
||||||
|
|
||||||
|
import Base
|
||||||
|
import Casm.Reg.Positive qualified as P
|
||||||
|
|
||||||
|
allTests :: TestTree
|
||||||
|
allTests = testGroup "CASM from JuvixReg translation" [P.allTests]
|
20
test/Casm/Reg/Base.hs
Normal file
20
test/Casm/Reg/Base.hs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
module Casm.Reg.Base where
|
||||||
|
|
||||||
|
import Base
|
||||||
|
import Juvix.Compiler.Casm.Data.Result
|
||||||
|
import Juvix.Compiler.Casm.Interpreter
|
||||||
|
import Juvix.Compiler.Reg.Data.InfoTable qualified as Reg
|
||||||
|
import Juvix.Data.PPOutput
|
||||||
|
import Reg.Run.Base qualified as Reg
|
||||||
|
|
||||||
|
compileAssertion' :: Handle -> Symbol -> Reg.InfoTable -> IO ()
|
||||||
|
compileAssertion' hout _ tab = do
|
||||||
|
case run $ runError @JuvixError $ regToCasm tab of
|
||||||
|
Left err -> assertFailure (show (pretty (fromJuvixError @GenericError err)))
|
||||||
|
Right Result {..} -> do
|
||||||
|
let v = hRunCode hout _resultLabelInfo _resultCode
|
||||||
|
hPutStrLn hout (show v)
|
||||||
|
|
||||||
|
regToCasmAssertion :: Path Abs File -> Path Abs File -> (String -> IO ()) -> Assertion
|
||||||
|
regToCasmAssertion mainFile expectedFile step =
|
||||||
|
Reg.regRunAssertionParam compileAssertion' mainFile expectedFile [] (const (return ())) step
|
183
test/Casm/Reg/Positive.hs
Normal file
183
test/Casm/Reg/Positive.hs
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
module Casm.Reg.Positive where
|
||||||
|
|
||||||
|
import Base
|
||||||
|
import Casm.Reg.Base
|
||||||
|
|
||||||
|
data PosTest = PosTest
|
||||||
|
{ _name :: String,
|
||||||
|
_relDir :: Path Rel Dir,
|
||||||
|
_file :: Path Rel File,
|
||||||
|
_expectedFile :: Path Rel File
|
||||||
|
}
|
||||||
|
|
||||||
|
root :: Path Abs Dir
|
||||||
|
root = relToProject $(mkRelDir "tests/Casm/Reg/positive")
|
||||||
|
|
||||||
|
testDescr :: PosTest -> TestDescr
|
||||||
|
testDescr PosTest {..} =
|
||||||
|
let tRoot = root <//> _relDir
|
||||||
|
file' = tRoot <//> _file
|
||||||
|
expected' = tRoot <//> _expectedFile
|
||||||
|
in TestDescr
|
||||||
|
{ _testName = _name,
|
||||||
|
_testRoot = tRoot,
|
||||||
|
_testAssertion = Steps $ regToCasmAssertion file' expected'
|
||||||
|
}
|
||||||
|
|
||||||
|
filterTests :: [String] -> [PosTest] -> [PosTest]
|
||||||
|
filterTests incl = filter (\PosTest {..} -> _name `elem` incl)
|
||||||
|
|
||||||
|
allTests :: TestTree
|
||||||
|
allTests =
|
||||||
|
testGroup
|
||||||
|
"CASM from JuvixReg translation positive tests"
|
||||||
|
(map (mkTest . testDescr) tests)
|
||||||
|
|
||||||
|
tests :: [PosTest]
|
||||||
|
tests =
|
||||||
|
[ PosTest
|
||||||
|
"Test001: Arithmetic opcodes"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test001.jvr")
|
||||||
|
$(mkRelFile "out/test001.out"),
|
||||||
|
PosTest
|
||||||
|
"Test002: Direct call"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test002.jvr")
|
||||||
|
$(mkRelFile "out/test002.out"),
|
||||||
|
PosTest
|
||||||
|
"Test003: Indirect call"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test003.jvr")
|
||||||
|
$(mkRelFile "out/test003.out"),
|
||||||
|
PosTest
|
||||||
|
"Test004: Tail calls"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test004.jvr")
|
||||||
|
$(mkRelFile "out/test004.out"),
|
||||||
|
PosTest
|
||||||
|
"Test008: Branch"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test008.jvr")
|
||||||
|
$(mkRelFile "out/test008.out"),
|
||||||
|
PosTest
|
||||||
|
"Test009: Case"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test009.jvr")
|
||||||
|
$(mkRelFile "out/test009.out"),
|
||||||
|
PosTest
|
||||||
|
"Test010: Recursion"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test010.jvr")
|
||||||
|
$(mkRelFile "out/test010.out"),
|
||||||
|
PosTest
|
||||||
|
"Test011: Tail recursion"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test011.jvr")
|
||||||
|
$(mkRelFile "out/test011.out"),
|
||||||
|
PosTest
|
||||||
|
"Test012: Temporary stack"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test012.jvr")
|
||||||
|
$(mkRelFile "out/test012.out"),
|
||||||
|
PosTest
|
||||||
|
"Test013: Fibonacci numbers in linear time"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test013.jvr")
|
||||||
|
$(mkRelFile "out/test013.out"),
|
||||||
|
PosTest
|
||||||
|
"Test014: Trees"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test014.jvr")
|
||||||
|
$(mkRelFile "out/test014.out"),
|
||||||
|
PosTest
|
||||||
|
"Test015: Functions returning functions"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test015.jvr")
|
||||||
|
$(mkRelFile "out/test015.out"),
|
||||||
|
PosTest
|
||||||
|
"Test016: Arithmetic"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test016.jvr")
|
||||||
|
$(mkRelFile "out/test016.out"),
|
||||||
|
PosTest
|
||||||
|
"Test017: Closures as arguments"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test017.jvr")
|
||||||
|
$(mkRelFile "out/test017.out"),
|
||||||
|
PosTest
|
||||||
|
"Test018: Closure extension"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test018.jvr")
|
||||||
|
$(mkRelFile "out/test018.out"),
|
||||||
|
PosTest
|
||||||
|
"Test019: Recursion through higher-order functions"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test019.jvr")
|
||||||
|
$(mkRelFile "out/test019.out"),
|
||||||
|
PosTest
|
||||||
|
"Test020: Tail recursion through higher-order functions"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test020.jvr")
|
||||||
|
$(mkRelFile "out/test020.out"),
|
||||||
|
PosTest
|
||||||
|
"Test021: Higher-order functions and recursion"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test021.jvr")
|
||||||
|
$(mkRelFile "out/test021.out"),
|
||||||
|
PosTest
|
||||||
|
"Test023: McCarthy's 91 function"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test023.jvr")
|
||||||
|
$(mkRelFile "out/test023.out"),
|
||||||
|
PosTest
|
||||||
|
"Test024: Higher-order recursive functions"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test024.jvr")
|
||||||
|
$(mkRelFile "out/test024.out"),
|
||||||
|
PosTest
|
||||||
|
"Test026: Currying & uncurrying"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test026.jvr")
|
||||||
|
$(mkRelFile "out/test026.out"),
|
||||||
|
PosTest
|
||||||
|
"Test027: Fast exponentiation"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test027.jvr")
|
||||||
|
$(mkRelFile "out/test027.out"),
|
||||||
|
PosTest
|
||||||
|
"Test028: Lists"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test028.jvr")
|
||||||
|
$(mkRelFile "out/test028.out"),
|
||||||
|
PosTest
|
||||||
|
"Test030: Mutual recursion"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test030.jvr")
|
||||||
|
$(mkRelFile "out/test030.out"),
|
||||||
|
PosTest
|
||||||
|
"Test031: Temporary stack with branching"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test031.jvr")
|
||||||
|
$(mkRelFile "out/test031.out"),
|
||||||
|
PosTest
|
||||||
|
"Test033: Ackermann function"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test033.jvr")
|
||||||
|
$(mkRelFile "out/test033.out"),
|
||||||
|
PosTest
|
||||||
|
"Test034: Higher-order function composition"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test034.jvr")
|
||||||
|
$(mkRelFile "out/test034.out"),
|
||||||
|
PosTest
|
||||||
|
"Test036: Streams without memoization"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test036.jvr")
|
||||||
|
$(mkRelFile "out/test036.out"),
|
||||||
|
PosTest
|
||||||
|
"Test038: Apply & argsnum"
|
||||||
|
$(mkRelDir ".")
|
||||||
|
$(mkRelFile "test038.jvr")
|
||||||
|
$(mkRelFile "out/test038.out")
|
||||||
|
]
|
@ -1,7 +1,5 @@
|
|||||||
module Casm.Run where
|
module Casm.Run where
|
||||||
|
|
||||||
-- import Casm.Run.Negative qualified as RunN
|
|
||||||
|
|
||||||
import Base
|
import Base
|
||||||
import Casm.Run.Negative qualified as RunN
|
import Casm.Run.Negative qualified as RunN
|
||||||
import Casm.Run.Positive qualified as RunP
|
import Casm.Run.Positive qualified as RunP
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
11
|
11
|
||||||
9
|
9
|
||||||
10
|
10
|
||||||
|
11
|
||||||
|
@ -40,6 +40,17 @@ function mult(integer, integer) : integer {
|
|||||||
ret;
|
ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function g(integer, integer, integer, integer) : integer {
|
||||||
|
push arg[1];
|
||||||
|
push arg[0];
|
||||||
|
sub;
|
||||||
|
push arg[2];
|
||||||
|
add;
|
||||||
|
push arg[3];
|
||||||
|
mul;
|
||||||
|
ret;
|
||||||
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
calloc plus 0;
|
calloc plus 0;
|
||||||
call f;
|
call f;
|
||||||
@ -53,6 +64,12 @@ function main() {
|
|||||||
call f;
|
call f;
|
||||||
trace; -- 10
|
trace; -- 10
|
||||||
pop;
|
pop;
|
||||||
|
push 2;
|
||||||
|
push 3;
|
||||||
|
calloc g 2;
|
||||||
|
call f;
|
||||||
|
trace; -- 11
|
||||||
|
pop;
|
||||||
push void;
|
push void;
|
||||||
ret;
|
ret;
|
||||||
}
|
}
|
||||||
|
1
tests/Casm/Compilation/positive/out/test001.out
Normal file
1
tests/Casm/Compilation/positive/out/test001.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
11
|
1
tests/Casm/Compilation/positive/out/test002.out
Normal file
1
tests/Casm/Compilation/positive/out/test002.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
11
|
1
tests/Casm/Compilation/positive/out/test003.out
Normal file
1
tests/Casm/Compilation/positive/out/test003.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
11
|
1
tests/Casm/Compilation/positive/out/test005.out
Normal file
1
tests/Casm/Compilation/positive/out/test005.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
6
|
1
tests/Casm/Compilation/positive/out/test006.out
Normal file
1
tests/Casm/Compilation/positive/out/test006.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
3
|
1
tests/Casm/Compilation/positive/out/test007.out
Normal file
1
tests/Casm/Compilation/positive/out/test007.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
6
|
1
tests/Casm/Compilation/positive/out/test008.out
Normal file
1
tests/Casm/Compilation/positive/out/test008.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
50005000
|
1
tests/Casm/Compilation/positive/out/test009.out
Normal file
1
tests/Casm/Compilation/positive/out/test009.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
532635520
|
1
tests/Casm/Compilation/positive/out/test010.out
Normal file
1
tests/Casm/Compilation/positive/out/test010.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
32
|
1
tests/Casm/Compilation/positive/out/test013.out
Normal file
1
tests/Casm/Compilation/positive/out/test013.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
8
|
1
tests/Casm/Compilation/positive/out/test014.out
Normal file
1
tests/Casm/Compilation/positive/out/test014.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
92
|
1
tests/Casm/Compilation/positive/out/test015.out
Normal file
1
tests/Casm/Compilation/positive/out/test015.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
771
|
1
tests/Casm/Compilation/positive/out/test016.out
Normal file
1
tests/Casm/Compilation/positive/out/test016.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
55
|
1
tests/Casm/Compilation/positive/out/test017.out
Normal file
1
tests/Casm/Compilation/positive/out/test017.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
50005000
|
1
tests/Casm/Compilation/positive/out/test018.out
Normal file
1
tests/Casm/Compilation/positive/out/test018.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
11
|
1
tests/Casm/Compilation/positive/out/test019.out
Normal file
1
tests/Casm/Compilation/positive/out/test019.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
7
|
1
tests/Casm/Compilation/positive/out/test020.out
Normal file
1
tests/Casm/Compilation/positive/out/test020.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
4876
|
1
tests/Casm/Compilation/positive/out/test021.out
Normal file
1
tests/Casm/Compilation/positive/out/test021.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
48830320
|
1
tests/Casm/Compilation/positive/out/test022.out
Normal file
1
tests/Casm/Compilation/positive/out/test022.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
100010000
|
1
tests/Casm/Compilation/positive/out/test023.out
Normal file
1
tests/Casm/Compilation/positive/out/test023.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
6386010
|
1
tests/Casm/Compilation/positive/out/test024.out
Normal file
1
tests/Casm/Compilation/positive/out/test024.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
6688
|
1
tests/Casm/Compilation/positive/out/test025.out
Normal file
1
tests/Casm/Compilation/positive/out/test025.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
87
|
1
tests/Casm/Compilation/positive/out/test026.out
Normal file
1
tests/Casm/Compilation/positive/out/test026.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
5050
|
1
tests/Casm/Compilation/positive/out/test028.out
Normal file
1
tests/Casm/Compilation/positive/out/test028.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
2040
|
1
tests/Casm/Compilation/positive/out/test029.out
Normal file
1
tests/Casm/Compilation/positive/out/test029.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
78
|
1
tests/Casm/Compilation/positive/out/test030.out
Normal file
1
tests/Casm/Compilation/positive/out/test030.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
2247
|
1
tests/Casm/Compilation/positive/out/test032.out
Normal file
1
tests/Casm/Compilation/positive/out/test032.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
195
|
1
tests/Casm/Compilation/positive/out/test033.out
Normal file
1
tests/Casm/Compilation/positive/out/test033.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
31
|
1
tests/Casm/Compilation/positive/out/test034.out
Normal file
1
tests/Casm/Compilation/positive/out/test034.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
50006027
|
1
tests/Casm/Compilation/positive/out/test035.out
Normal file
1
tests/Casm/Compilation/positive/out/test035.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
34422
|
1
tests/Casm/Compilation/positive/out/test036.out
Normal file
1
tests/Casm/Compilation/positive/out/test036.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
18
|
1
tests/Casm/Compilation/positive/out/test037.out
Normal file
1
tests/Casm/Compilation/positive/out/test037.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
9
|
1
tests/Casm/Compilation/positive/out/test038.out
Normal file
1
tests/Casm/Compilation/positive/out/test038.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
1
tests/Casm/Compilation/positive/out/test039.out
Normal file
1
tests/Casm/Compilation/positive/out/test039.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
1
tests/Casm/Compilation/positive/out/test040.out
Normal file
1
tests/Casm/Compilation/positive/out/test040.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
1
tests/Casm/Compilation/positive/out/test045.out
Normal file
1
tests/Casm/Compilation/positive/out/test045.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
4
|
1
tests/Casm/Compilation/positive/out/test046.out
Normal file
1
tests/Casm/Compilation/positive/out/test046.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
7
|
1
tests/Casm/Compilation/positive/out/test047.out
Normal file
1
tests/Casm/Compilation/positive/out/test047.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
660
|
1
tests/Casm/Compilation/positive/out/test050.out
Normal file
1
tests/Casm/Compilation/positive/out/test050.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
11
|
1
tests/Casm/Compilation/positive/out/test053.out
Normal file
1
tests/Casm/Compilation/positive/out/test053.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
21
|
1
tests/Casm/Compilation/positive/out/test054.out
Normal file
1
tests/Casm/Compilation/positive/out/test054.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
189
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user