# Cranefack
[![docs.rs badge](https://docs.rs/cranefack/badge.svg)](https://docs.rs/cranefack/)
[![crates.io badge](https://img.shields.io/crates/v/cranefack.svg)](https://crates.io/crates/cranefack/)
[![Rust](https://github.com/vstroebel/cranefack/actions/workflows/rust.yml/badge.svg)](https://github.com/vstroebel/cranefack/actions/workflows/rust.yml)
A cranelift powered optimizing brainfuck compiler suite.
## Commandline interface
Cranefack provides a command line utility to run, compile and benchmark programs.
```shell
cargo install cranefack-cli
```
### Run
Run a program with interpreter or jit.
Passing the `-v` option prints some statistics and execution time.
```text
USAGE:
cranefack run [FLAGS] [OPTIONS]
FLAGS:
--debug-optimizations Print statistics for optimization passes
-j, --jit Use JIT compiler
-v, --verbose
--wrapping-is-ub Wrapping overflows are undefined behavior during optimization
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
--jit-level Optimization level for JIT [possible values: none, speed, speed_and_size]
-O Optimization mode [default: 2] [possible values: 0, 1, 2, 3, s, wtf]
ARGS:
Brainfuck source file. Use - to read from stdin
```
### Compile
Compile the program.
As of now this will create an assembly like representation by default that is only useful for debugging.
In case you need something to compile into a native binary you can use the `rust` output format to get ugly rust code
that can be compiled with rustc:
```shell
cranefack compile -f=rust some_app.bf > some_app.rs
rustc -O some_app.rs
./some_app
```
```text
USAGE:
cranefack compile [FLAGS] [OPTIONS]
FLAGS:
--debug-optimizations Print statistics for optimization passes
-v, --verbose
--wrapping-is-ub Wrapping overflows are undefined behavior during optimization
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-f, --format Format of compiled code [default: dump] [possible values: dump, clir, rust]
--jit-level Optimization level for JIT [possible values: none, speed, speed_and_size]
-O Optimization mode [default: 2] [possible values: 0, 1, 2, 3, s, wtf]
ARGS:
Brainfuck source file. Use - to read from stdin
```
### Benchmark
Runs a program with different optimization settings and returns a table this the time for each program run.
```text
USAGE:
cranefack benchmark [FLAGS] [OPTIONS]
FLAGS:
-j, --jit Only benchmark jit
-o, --optimized-only Don't benchmark O0
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-i, --iterations Number of benchmarking iterations [default: 2]
-r, --runs Number of runs per optimization in each round [default: 4]
ARGS:
Brainfuck source file. Use - to read from stdin
```
## Use cranefack as a library
To use cranefack as a library add the following to your Cargo.toml dependencies:
```toml
cranefack = "0.4"
```
To run a program with jit compilation:
```rust
use std::error::Error;
use cranefack::{parse, optimize_with_config, OptimizeConfig, CompiledJitModule};
fn main() -> Result<(), Box> {
// Parse program
let mut program = parse("++[<].")?;
// Create optimization config for level 2
let opt_level = OptimizeConfig::o2();
// Optimize with optimization level 2
optimize_with_config(&mut program, &opt_level);
// Compile program into module
let module = CompiledJitModule::new(&program, &opt_level)?;
// Execute compiled module reading from stdin and writing to stdout
module.execute(std::io::stdin(), std::io::stdout());
Ok(())
}
```
## License
This project is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
## Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in cranefack by you, as
defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.