1
1
mirror of https://github.com/anoma/juvix.git synced 2024-12-15 01:52:11 +03:00
juvix/test/BackendC/Base.hs
Paul Cadman 40287efabb
Support partial application and closure passing in C backend (#190)
* Add support for parital application eval/apply

* include string.h in libc runtime

* Add wasm SimpleFungibleTokenImplicit to tests

* Update VP example to new syntax

* propagate types from all reachable modules

* Change prelude import ordering to workaround minic issue

* Pre-declare inductive typedefs in C backend

This generates the typedefs corresponding to each inductive type.

e.g

```
inductive Bool { .. }
```

is translated to:

```
typedef struct Bool_3_s Bool_3_t;
```

This means that C code can reference these typedefs before they have
been fully defined. (all references to inductive types go through these typedefs
names).

This fixes an issue with the ordering of delcarations when modules are included.

* Use common Lib for MiniC tests

* libc runtime: flush stdout after writing to it

* Adds MiniTicTacToe example using common example lib

In MonoJuvixToMiniC we emit the inductive type typedefs before anything
else to support includes ordering

* Adds tests for mutually recrusive functions

* Add golden tests for milestone examples

* Example: Remove commented out code

* Test error handling behaviour in MiniTicTacToe

* Fail clang compilation on warnings

* Add test for Nested list types

* Add PrettyCode instances for NonEmpty and ConcreteType

* Ignore IsImplicit field in Eq and Hashable of TypeApplication

This is to workaround a crash in Micro->Mono translation when looking up
a concrete type

* Fix formatting

* hlint fixes

* Formatting fixes not reported by local pre-commit

* Refactor MonoJuvixToMiniC

* Fix shelltest

NB: We cannot check the order of the 'Writing' lines because this
depends on the order of files returned by the FS which is
non-deterministic between systems

* Refactor Base to CBuilder

* Refactor using applyOnFunStatement

Co-authored-by: Jan Mas Rovira <janmasrovira@gmail.com>
2022-06-28 10:25:43 +02:00

96 lines
2.9 KiB
Haskell

module BackendC.Base where
import Base
import Data.FileEmbed
import Data.Text.IO qualified as TIO
import MiniJuvix.Pipeline
import MiniJuvix.Translation.MonoJuvixToMiniC as MiniC
import System.IO.Extra (withTempDir)
import System.Process qualified as P
clangCompile ::
(FilePath -> FilePath -> [String]) ->
MiniC.MiniCResult ->
Text ->
(String -> IO ()) ->
IO Text
clangCompile mkClangArgs cResult stdinText step =
withTempDir
( \dirPath -> do
let cOutputFile = dirPath </> "out.c"
wasmOutputFile = dirPath </> "out.wasm"
TIO.writeFile cOutputFile (cResult ^. MiniC.resultCCode)
step "WASM generation"
P.callProcess
"clang"
(mkClangArgs wasmOutputFile cOutputFile)
step "WASM execution"
pack <$> P.readProcess "wasmer" [wasmOutputFile] (unpack stdinText)
)
clangAssertion :: FilePath -> FilePath -> Text -> ((String -> IO ()) -> Assertion)
clangAssertion mainFile expectedFile stdinText step = do
step "Check clang and wasmer are on path"
assertCmdExists "clang"
assertCmdExists "wasmer"
step "Lookup WASI_SYSROOT_PATH"
sysrootPath <-
assertEnvVar
"Env var WASI_SYSROOT_PATH missing. Set to the location of the wasi-clib sysroot"
"WASI_SYSROOT_PATH"
step "C Generation"
let entryPoint = defaultEntryPoint mainFile
p :: MiniC.MiniCResult <- runIO (upToMiniC entryPoint)
expected <- TIO.readFile expectedFile
step "Compile C with standalone runtime"
actualStandalone <- clangCompile (standaloneArgs sysrootPath) p stdinText step
step "Compare expected and actual program output"
assertEqDiff ("check: WASM output = " <> expectedFile) actualStandalone expected
step "Compile C with libc runtime"
actualLibc <- clangCompile (libcArgs sysrootPath) p stdinText step
step "Compare expected and actual program output"
assertEqDiff ("check: WASM output = " <> expectedFile) actualLibc expected
standaloneArgs :: FilePath -> FilePath -> FilePath -> [String]
standaloneArgs sysrootPath wasmOutputFile cOutputFile =
[ "-nodefaultlibs",
"-I",
takeDirectory minicRuntime,
"-Werror",
"--target=wasm32-wasi",
"--sysroot",
sysrootPath,
"-o",
wasmOutputFile,
wallocPath,
cOutputFile
]
where
minicRuntime :: FilePath
minicRuntime = $(makeRelativeToProject "minic-runtime/standalone/minic-runtime.h" >>= strToExp)
wallocPath :: FilePath
wallocPath = $(makeRelativeToProject "minic-runtime/standalone/walloc.c" >>= strToExp)
libcArgs :: FilePath -> FilePath -> FilePath -> [String]
libcArgs sysrootPath wasmOutputFile cOutputFile =
[ "-nodefaultlibs",
"-I",
takeDirectory minicRuntime,
"-Werror",
"-lc",
"--target=wasm32-wasi",
"--sysroot",
sysrootPath,
"-o",
wasmOutputFile,
cOutputFile
]
where
minicRuntime :: FilePath
minicRuntime = $(makeRelativeToProject "minic-runtime/libc/minic-runtime.h" >>= strToExp)