mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
Merge branch 'trunk' of github.com:rtfeldman/roc into wasm-runtime-error
This commit is contained in:
commit
70804e9bec
102 changed files with 253 additions and 645 deletions
|
@ -124,7 +124,7 @@ build-nightly-release:
|
||||||
RUN printf " on: " >> version.txt
|
RUN printf " on: " >> version.txt
|
||||||
RUN date >> version.txt
|
RUN date >> version.txt
|
||||||
RUN RUSTFLAGS="-C target-cpu=x86-64" cargo build --features with_sound --release
|
RUN RUSTFLAGS="-C target-cpu=x86-64" cargo build --features with_sound --release
|
||||||
RUN cd ./target/release && tar -czvf roc_linux_x86_64.tar.gz ./roc ../../LICENSE ../../LEGAL_DETAILS ../../examples/hello-world ../../examples/hello-rust ../../examples/hello-zig ../../compiler/builtins/bitcode/src/ ../../roc_std
|
RUN cd ./target/release && tar -czvf roc_linux_x86_64.tar.gz ./roc ../../LICENSE ../../LEGAL_DETAILS ../../examples/hello-world ../../compiler/builtins/bitcode/src/ ../../roc_std
|
||||||
SAVE ARTIFACT ./target/release/roc_linux_x86_64.tar.gz AS LOCAL roc_linux_x86_64.tar.gz
|
SAVE ARTIFACT ./target/release/roc_linux_x86_64.tar.gz AS LOCAL roc_linux_x86_64.tar.gz
|
||||||
|
|
||||||
# compile everything needed for benchmarks and output a self-contained dir from which benchmarks can be run.
|
# compile everything needed for benchmarks and output a self-contained dir from which benchmarks can be run.
|
||||||
|
|
|
@ -23,7 +23,7 @@ Many programs can however be compiled correctly. Check out [examples](examples)
|
||||||
|
|
||||||
Run examples as follows:
|
Run examples as follows:
|
||||||
```
|
```
|
||||||
cargo run examples/hello-world/Hello.roc
|
cargo run examples/hello-world/helloWorld.roc
|
||||||
```
|
```
|
||||||
Some examples like `examples/benchmarks/NQueens.roc` require input after running.
|
Some examples like `examples/benchmarks/NQueens.roc` require input after running.
|
||||||
For NQueens, input 10 in the terminal and press enter.
|
For NQueens, input 10 in the terminal and press enter.
|
||||||
|
|
|
@ -234,12 +234,12 @@ mod cli_run {
|
||||||
let file_name = example_file(dir_name, example.filename);
|
let file_name = example_file(dir_name, example.filename);
|
||||||
|
|
||||||
match example.executable_filename {
|
match example.executable_filename {
|
||||||
"hello-web" => {
|
"helloWeb" => {
|
||||||
// this is a web webassembly example, but we don't test with JS at the moment
|
// this is a web webassembly example, but we don't test with JS at the moment
|
||||||
eprintln!("WARNING: skipping testing example {} because the test is broken right now!", example.filename);
|
eprintln!("WARNING: skipping testing example {} because the test is broken right now!", example.filename);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
"hello-swift" => {
|
"helloSwift" => {
|
||||||
if cfg!(not(target_os = "macos")) {
|
if cfg!(not(target_os = "macos")) {
|
||||||
eprintln!("WARNING: skipping testing example {} because it only works on MacOS.", example.filename);
|
eprintln!("WARNING: skipping testing example {} because it only works on MacOS.", example.filename);
|
||||||
return;
|
return;
|
||||||
|
@ -324,49 +324,57 @@ mod cli_run {
|
||||||
// },
|
// },
|
||||||
// ]
|
// ]
|
||||||
examples! {
|
examples! {
|
||||||
hello_world:"hello-world" => Example {
|
helloWorld:"hello-world" => Example {
|
||||||
filename: "Hello.roc",
|
filename: "helloWorld.roc",
|
||||||
executable_filename: "hello-world",
|
executable_filename: "helloWorld",
|
||||||
stdin: &[],
|
stdin: &[],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
expected_ending:"Hello, World!\n",
|
expected_ending:"Hello, World!\n",
|
||||||
use_valgrind: true,
|
use_valgrind: true,
|
||||||
},
|
},
|
||||||
hello_zig:"hello-zig" => Example {
|
helloC:"hello-world/c-platform" => Example {
|
||||||
filename: "Hello.roc",
|
filename: "helloC.roc",
|
||||||
executable_filename: "hello-world",
|
executable_filename: "helloC",
|
||||||
stdin: &[],
|
stdin: &[],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
expected_ending:"Hello, World!\n",
|
expected_ending:"Hello, World!\n",
|
||||||
use_valgrind: true,
|
use_valgrind: true,
|
||||||
},
|
},
|
||||||
hello_rust:"hello-rust" => Example {
|
helloZig:"hello-world/zig-platform" => Example {
|
||||||
filename: "Hello.roc",
|
filename: "helloZig.roc",
|
||||||
executable_filename: "hello-rust",
|
executable_filename: "helloZig",
|
||||||
stdin: &[],
|
stdin: &[],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
expected_ending:"Hello, World!\n",
|
expected_ending:"Hello, World!\n",
|
||||||
use_valgrind: true,
|
use_valgrind: true,
|
||||||
},
|
},
|
||||||
hello_swift:"hello-swift" => Example {
|
helloRust:"hello-world/rust-platform" => Example {
|
||||||
filename: "Hello.roc",
|
filename: "helloRust.roc",
|
||||||
executable_filename: "hello-swift",
|
executable_filename: "helloRust",
|
||||||
stdin: &[],
|
|
||||||
input_file: None,
|
|
||||||
expected_ending:"Hello Swift, meet Roc\n",
|
|
||||||
use_valgrind: true,
|
|
||||||
},
|
|
||||||
hello_web:"hello-web" => Example {
|
|
||||||
filename: "Hello.roc",
|
|
||||||
executable_filename: "hello-web",
|
|
||||||
stdin: &[],
|
stdin: &[],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
expected_ending:"Hello, World!\n",
|
expected_ending:"Hello, World!\n",
|
||||||
use_valgrind: true,
|
use_valgrind: true,
|
||||||
},
|
},
|
||||||
fib:"fib" => Example {
|
helloSwift:"hello-world/swift-platform" => Example {
|
||||||
filename: "Fib.roc",
|
filename: "helloSwift.roc",
|
||||||
executable_filename: "fib",
|
executable_filename: "helloSwift",
|
||||||
|
stdin: &[],
|
||||||
|
input_file: None,
|
||||||
|
expected_ending:"Hello, World!\n",
|
||||||
|
use_valgrind: true,
|
||||||
|
},
|
||||||
|
helloWeb:"hello-world/web-platform" => Example {
|
||||||
|
filename: "helloWeb.roc",
|
||||||
|
executable_filename: "helloWeb",
|
||||||
|
stdin: &[],
|
||||||
|
input_file: None,
|
||||||
|
expected_ending:"Hello, World!\n",
|
||||||
|
use_valgrind: true,
|
||||||
|
},
|
||||||
|
fib:"algorithms" => Example {
|
||||||
|
filename: "fibonacci.roc",
|
||||||
|
executable_filename: "fibonacci",
|
||||||
stdin: &[],
|
stdin: &[],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
expected_ending:"55\n",
|
expected_ending:"55\n",
|
||||||
|
@ -380,8 +388,8 @@ mod cli_run {
|
||||||
expected_ending: "",
|
expected_ending: "",
|
||||||
use_valgrind: false,
|
use_valgrind: false,
|
||||||
},
|
},
|
||||||
quicksort:"quicksort" => Example {
|
quicksort:"algorithms" => Example {
|
||||||
filename: "Quicksort.roc",
|
filename: "quicksort.roc",
|
||||||
executable_filename: "quicksort",
|
executable_filename: "quicksort",
|
||||||
stdin: &[],
|
stdin: &[],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
|
@ -396,9 +404,9 @@ mod cli_run {
|
||||||
// expected_ending: "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n",
|
// expected_ending: "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n",
|
||||||
// use_valgrind: true,
|
// use_valgrind: true,
|
||||||
// },
|
// },
|
||||||
effect:"effect" => Example {
|
effects:"interactive" => Example {
|
||||||
filename: "Main.roc",
|
filename: "effects.roc",
|
||||||
executable_filename: "effect-example",
|
executable_filename: "effects",
|
||||||
stdin: &["hi there!"],
|
stdin: &["hi there!"],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
expected_ending: "hi there!\nIt is known\n",
|
expected_ending: "hi there!\nIt is known\n",
|
||||||
|
@ -412,7 +420,7 @@ mod cli_run {
|
||||||
// expected_ending: "",
|
// expected_ending: "",
|
||||||
// use_valgrind: true,
|
// use_valgrind: true,
|
||||||
// },
|
// },
|
||||||
cli:"cli" => Example {
|
cli:"interactive" => Example {
|
||||||
filename: "form.roc",
|
filename: "form.roc",
|
||||||
executable_filename: "form",
|
executable_filename: "form",
|
||||||
stdin: &["Giovanni\n", "Giorgio\n"],
|
stdin: &["Giovanni\n", "Giorgio\n"],
|
||||||
|
@ -420,8 +428,8 @@ mod cli_run {
|
||||||
expected_ending: "Hi, Giovanni Giorgio! 👋\n",
|
expected_ending: "Hi, Giovanni Giorgio! 👋\n",
|
||||||
use_valgrind: true,
|
use_valgrind: true,
|
||||||
},
|
},
|
||||||
tui:"tui" => Example {
|
tui:"interactive" => Example {
|
||||||
filename: "Main.roc",
|
filename: "tui.roc",
|
||||||
executable_filename: "tui",
|
executable_filename: "tui",
|
||||||
stdin: &["foo\n"], // NOTE: adding more lines leads to memory leaks
|
stdin: &["foo\n"], // NOTE: adding more lines leads to memory leaks
|
||||||
input_file: None,
|
input_file: None,
|
||||||
|
@ -706,6 +714,22 @@ mod cli_run {
|
||||||
if entry.file_type().unwrap().is_dir() {
|
if entry.file_type().unwrap().is_dir() {
|
||||||
let example_dir_name = entry.file_name().into_string().unwrap();
|
let example_dir_name = entry.file_name().into_string().unwrap();
|
||||||
|
|
||||||
|
// TODO: Improve this with a more-dynamic approach. (Read all subdirectories?)
|
||||||
|
// Some hello-world examples live in nested directories
|
||||||
|
if example_dir_name == "hello-world" {
|
||||||
|
for sub_dir in [
|
||||||
|
"c-platform",
|
||||||
|
"rust-platform",
|
||||||
|
"swift-platform",
|
||||||
|
"web-platform",
|
||||||
|
"zig-platform",
|
||||||
|
] {
|
||||||
|
all_examples.remove(format!("{}/{}", example_dir_name, sub_dir).as_str()).unwrap_or_else(|| {
|
||||||
|
panic!("The example directory {}/{}/{} does not have any corresponding tests in cli_run. Please add one, so if it ever stops working, we'll know about it right away!", examples_dir, example_dir_name, sub_dir);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We test benchmarks separately
|
// We test benchmarks separately
|
||||||
if example_dir_name != "benchmarks" {
|
if example_dir_name != "benchmarks" {
|
||||||
all_examples.remove(example_dir_name.as_str()).unwrap_or_else(|| {
|
all_examples.remove(example_dir_name.as_str()).unwrap_or_else(|| {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/multi-module"
|
platform "multi-module"
|
||||||
requires {}{ main : Str }
|
requires {}{ main : Str }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/multi-dep-thunk"
|
platform "multi-dep-thunk"
|
||||||
requires {}{ main : Str }
|
requires {}{ main : Str }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
../../../examples/cli/platform
|
../../../examples/interactive/cli-platform
|
|
@ -794,11 +794,13 @@ pub fn build_exp_literal<'a, 'ctx, 'env>(
|
||||||
_ => panic!("Invalid layout for float literal = {:?}", layout),
|
_ => panic!("Invalid layout for float literal = {:?}", layout),
|
||||||
},
|
},
|
||||||
|
|
||||||
Decimal(int) => env
|
Decimal(int) => {
|
||||||
.context
|
let (upper_bits, lower_bits) = int.as_bits();
|
||||||
.i128_type()
|
env.context
|
||||||
.const_int(int.0 as u64, false)
|
.i128_type()
|
||||||
.into(),
|
.const_int_arbitrary_precision(&[lower_bits, upper_bits as u64])
|
||||||
|
.into()
|
||||||
|
}
|
||||||
Bool(b) => env.context.bool_type().const_int(*b as u64, false).into(),
|
Bool(b) => env.context.bool_type().const_int(*b as u64, false).into(),
|
||||||
Byte(b) => env.context.i8_type().const_int(*b as u64, false).into(),
|
Byte(b) => env.context.i8_type().const_int(*b as u64, false).into(),
|
||||||
Str(str_literal) => {
|
Str(str_literal) => {
|
||||||
|
|
|
@ -637,9 +637,8 @@ impl<'a> WasmBackend<'a> {
|
||||||
|
|
||||||
match lit {
|
match lit {
|
||||||
Literal::Decimal(decimal) => {
|
Literal::Decimal(decimal) => {
|
||||||
let lower_bits = (decimal.0 & 0xffff_ffff_ffff_ffff) as i64;
|
let (upper_bits, lower_bits) = decimal.as_bits();
|
||||||
let upper_bits = (decimal.0 >> 64) as i64;
|
write128(lower_bits as i64, upper_bits);
|
||||||
write128(lower_bits, upper_bits);
|
|
||||||
}
|
}
|
||||||
Literal::Int(x) => {
|
Literal::Int(x) => {
|
||||||
let lower_bits = (*x & 0xffff_ffff_ffff_ffff) as i64;
|
let lower_bits = (*x & 0xffff_ffff_ffff_ffff) as i64;
|
||||||
|
|
|
@ -647,7 +647,7 @@ mod test_load {
|
||||||
"platform/Package-Config.roc",
|
"platform/Package-Config.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
platform "examples/hello-world"
|
platform "hello-c"
|
||||||
requires {} { main : Str }
|
requires {} { main : Str }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
||||||
|
@ -691,7 +691,7 @@ mod test_load {
|
||||||
"platform/Package-Config.roc",
|
"platform/Package-Config.roc",
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
platform "examples/hello-world"
|
platform "hello-world"
|
||||||
requires {} { main : { content: Str, other: Str } }
|
requires {} { main : { content: Str, other: Str } }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
||||||
|
|
|
@ -135,7 +135,7 @@ impl<'a> Hash for Test<'a> {
|
||||||
IsDecimal(v) => {
|
IsDecimal(v) => {
|
||||||
// TODO: Is this okay?
|
// TODO: Is this okay?
|
||||||
state.write_u8(6);
|
state.write_u8(6);
|
||||||
v.0.hash(state);
|
v.hash(state);
|
||||||
}
|
}
|
||||||
IsU128(v) => {
|
IsU128(v) => {
|
||||||
state.write_u8(7);
|
state.write_u8(7);
|
||||||
|
@ -906,7 +906,7 @@ fn to_relevant_branch_help<'a>(
|
||||||
},
|
},
|
||||||
|
|
||||||
DecimalLiteral(dec) => match test {
|
DecimalLiteral(dec) => match test {
|
||||||
IsDecimal(test_dec) if dec.0 == test_dec.0 => {
|
IsDecimal(test_dec) if dec.eq(test_dec) => {
|
||||||
start.extend(end);
|
start.extend(end);
|
||||||
Some(Branch {
|
Some(Branch {
|
||||||
goal: branch.goal,
|
goal: branch.goal,
|
||||||
|
@ -1396,7 +1396,7 @@ fn test_to_equality<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
Test::IsDecimal(test_dec) => {
|
Test::IsDecimal(test_dec) => {
|
||||||
let lhs = Expr::Literal(Literal::Int(test_dec.0));
|
let lhs = Expr::Literal(Literal::Decimal(test_dec));
|
||||||
let lhs_symbol = env.unique_symbol();
|
let lhs_symbol = env.unique_symbol();
|
||||||
stores.push((lhs_symbol, *cond_layout, lhs));
|
stores.push((lhs_symbol, *cond_layout, lhs));
|
||||||
|
|
||||||
|
|
|
@ -1536,8 +1536,7 @@ impl<'a> Literal<'a> {
|
||||||
Int(lit) => alloc.text(format!("{}i64", lit)),
|
Int(lit) => alloc.text(format!("{}i64", lit)),
|
||||||
U128(lit) => alloc.text(format!("{}u128", lit)),
|
U128(lit) => alloc.text(format!("{}u128", lit)),
|
||||||
Float(lit) => alloc.text(format!("{}f64", lit)),
|
Float(lit) => alloc.text(format!("{}f64", lit)),
|
||||||
// TODO: Add proper Dec.to_str
|
Decimal(lit) => alloc.text(format!("{}dec", lit)),
|
||||||
Decimal(lit) => alloc.text(format!("{}Dec", lit.0)),
|
|
||||||
Bool(lit) => alloc.text(format!("{}", lit)),
|
Bool(lit) => alloc.text(format!("{}", lit)),
|
||||||
Byte(lit) => alloc.text(format!("{}u8", lit)),
|
Byte(lit) => alloc.text(format!("{}u8", lit)),
|
||||||
Str(lit) => alloc.text(format!("{:?}", lit)),
|
Str(lit) => alloc.text(format!("{:?}", lit)),
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
Platform {
|
Platform {
|
||||||
header: PlatformHeader {
|
header: PlatformHeader {
|
||||||
name: @9-23 PackageName(
|
name: @9-14 PackageName(
|
||||||
"examples/cli",
|
"cli",
|
||||||
),
|
),
|
||||||
requires: PlatformRequires {
|
requires: PlatformRequires {
|
||||||
rigids: [],
|
rigids: [],
|
||||||
signature: @41-58 TypedIdent {
|
signature: @32-49 TypedIdent {
|
||||||
ident: @41-45 "main",
|
ident: @32-36 "main",
|
||||||
spaces_before_colon: [],
|
spaces_before_colon: [],
|
||||||
ann: @48-58 Apply(
|
ann: @39-49 Apply(
|
||||||
"",
|
"",
|
||||||
"Task",
|
"Task",
|
||||||
[
|
[
|
||||||
@53-55 Record {
|
@44-46 Record {
|
||||||
fields: [],
|
fields: [],
|
||||||
ext: None,
|
ext: None,
|
||||||
},
|
},
|
||||||
@56-58 TagUnion {
|
@47-49 TagUnion {
|
||||||
ext: None,
|
ext: None,
|
||||||
tags: [],
|
tags: [],
|
||||||
},
|
},
|
||||||
|
@ -27,19 +27,19 @@ Platform {
|
||||||
exposes: [],
|
exposes: [],
|
||||||
packages: [],
|
packages: [],
|
||||||
imports: [
|
imports: [
|
||||||
@119-132 Module(
|
@110-123 Module(
|
||||||
ModuleName(
|
ModuleName(
|
||||||
"Task",
|
"Task",
|
||||||
),
|
),
|
||||||
[
|
[
|
||||||
@126-130 ExposedName(
|
@117-121 ExposedName(
|
||||||
"Task",
|
"Task",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
provides: [
|
provides: [
|
||||||
@150-161 ExposedName(
|
@141-152 ExposedName(
|
||||||
"mainForHost",
|
"mainForHost",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/cli"
|
platform "cli"
|
||||||
requires {}{ main : Task {} [] } # TODO FIXME
|
requires {}{ main : Task {} [] } # TODO FIXME
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
||||||
|
|
|
@ -517,7 +517,7 @@ fn read_main_roc_file(project_dir_path_opt: Option<&Path>) -> (PathStr, String)
|
||||||
|
|
||||||
// returns path and content of app file
|
// returns path and content of app file
|
||||||
fn init_new_roc_project(project_dir_path_str: &str) -> (PathStr, String) {
|
fn init_new_roc_project(project_dir_path_str: &str) -> (PathStr, String) {
|
||||||
let orig_platform_path = Path::new("./examples/hello-world/platform");
|
let orig_platform_path = Path::new("./examples/hello-c/platform");
|
||||||
|
|
||||||
let project_dir_path = Path::new(project_dir_path_str);
|
let project_dir_path = Path::new(project_dir_path_str);
|
||||||
|
|
||||||
|
|
6
examples/.gitignore
vendored
6
examples/.gitignore
vendored
|
@ -1,10 +1,6 @@
|
||||||
app
|
|
||||||
*.o
|
|
||||||
*.dSYM
|
*.dSYM
|
||||||
libhost.a
|
libhost.a
|
||||||
roc_app.ll
|
libapp.so
|
||||||
roc_app.bc
|
|
||||||
dynhost
|
dynhost
|
||||||
preprocessedhost
|
preprocessedhost
|
||||||
metadata
|
metadata
|
||||||
libapp.so
|
|
|
@ -1,13 +1,20 @@
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
|
|
||||||
Took a look around in the `examples` folder, `examples/benchmarks` contains some larger examples.
|
Took a look around in this folder; `examples/benchmarks/` contains some larger examples.
|
||||||
|
|
||||||
Run examples as follows:
|
Run examples as follows:
|
||||||
1. Navigate to `/examples`
|
|
||||||
2. Run with:
|
1. Navigate to the examples directory
|
||||||
```
|
|
||||||
cargo run hello-world/Hello.roc
|
```bash
|
||||||
```
|
cd examples
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Run "Hello, World!" example
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo run hello-world/helloWorld.roc
|
||||||
|
```
|
||||||
|
|
||||||
Some examples like `examples/benchmarks/NQueens.roc` require input after running.
|
Some examples like `examples/benchmarks/NQueens.roc` require input after running.
|
||||||
For NQueens, input 10 in the terminal and press enter.
|
For NQueens, input 10 in the terminal and press enter.
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
fibonacci
|
||||||
quicksort
|
quicksort
|
15
examples/algorithms/README.md
Normal file
15
examples/algorithms/README.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# Algorithm examples
|
||||||
|
|
||||||
|
To run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo run fibonacci.roc
|
||||||
|
cargo run quicksort.roc
|
||||||
|
```
|
||||||
|
|
||||||
|
To run in release mode instead, do:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo run --release fibonacci.roc
|
||||||
|
cargo run --release quicksort.roc
|
||||||
|
```
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/add"
|
platform "fibonacci"
|
||||||
requires {} { main : I64 -> I64 }
|
requires {} { main : I64 -> I64 }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
|
@ -1,5 +1,5 @@
|
||||||
app "fib"
|
app "fibonacci"
|
||||||
packages { pf: "platform" }
|
packages { pf: "fibonacci-platform" }
|
||||||
imports []
|
imports []
|
||||||
provides [ main ] to pf
|
provides [ main ] to pf
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/quicksort"
|
platform "quicksort"
|
||||||
requires {} { quicksort : List I64 -> List I64 }
|
requires {} { quicksort : List I64 -> List I64 }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
|
@ -1,5 +1,5 @@
|
||||||
app "quicksort"
|
app "quicksort"
|
||||||
packages { pf: "platform" }
|
packages { pf: "quicksort-platform" }
|
||||||
imports []
|
imports []
|
||||||
provides [ quicksort ] to pf
|
provides [ quicksort ] to pf
|
||||||
|
|
20
examples/benchmarks/.gitignore
vendored
20
examples/benchmarks/.gitignore
vendored
|
@ -1,19 +1,11 @@
|
||||||
app
|
|
||||||
*.o
|
|
||||||
*.dSYM
|
|
||||||
*.ll
|
|
||||||
*.bc
|
|
||||||
libhost.a
|
|
||||||
roc_app.ll
|
|
||||||
roc_app.bc
|
|
||||||
nqueens
|
|
||||||
deriv
|
|
||||||
closure
|
|
||||||
cfold
|
cfold
|
||||||
rbtree-insert
|
closure
|
||||||
rbtree-del
|
deriv
|
||||||
issue2279
|
issue2279
|
||||||
|
nqueens
|
||||||
|
quicksortapp
|
||||||
rbtree-ck
|
rbtree-ck
|
||||||
|
rbtree-del
|
||||||
|
rbtree-insert
|
||||||
test-astar
|
test-astar
|
||||||
test-base64
|
test-base64
|
||||||
quicksortapp
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
platform "folkertdev/foo"
|
platform "benchmarks"
|
||||||
requires {} { main : Effect {} }
|
requires {} { main : Effect {} }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
# Command Line Interface (CLI) Example
|
|
||||||
|
|
||||||
This is an example of how to make an extremely basic CLI in Roc.
|
|
||||||
|
|
||||||
There's not currently much documentation for the CLI platform (which also doesn't support many operations at this point!)
|
|
||||||
but you can look at [the modules it includes](platform) - for example,
|
|
||||||
multiple other modules use the [`Task`](platform/Task.roc) module, including the
|
|
||||||
[`Stdin`](platform/Stdin.roc) and [`Stdout`](platform/Stdout.roc) modules.
|
|
1
examples/effect/.gitignore
vendored
1
examples/effect/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
effect-example
|
|
|
@ -1,33 +0,0 @@
|
||||||
interface ConsList exposes [ ConsList, empty, isEmpty, map, len ] imports []
|
|
||||||
|
|
||||||
ConsList a : [ Cons a (ConsList a), Nil ]
|
|
||||||
|
|
||||||
empty : ConsList a
|
|
||||||
empty = Nil
|
|
||||||
|
|
||||||
len : ConsList a -> Int *
|
|
||||||
len = \list ->
|
|
||||||
when list is
|
|
||||||
Cons _ rest ->
|
|
||||||
1 + len rest
|
|
||||||
|
|
||||||
Nil ->
|
|
||||||
0
|
|
||||||
|
|
||||||
map : ConsList a, (a -> b) -> ConsList b
|
|
||||||
map = \list, f ->
|
|
||||||
when list is
|
|
||||||
Cons x xs ->
|
|
||||||
Cons (f x) (map xs f)
|
|
||||||
|
|
||||||
Nil ->
|
|
||||||
Nil
|
|
||||||
|
|
||||||
isEmpty : ConsList a -> Bool
|
|
||||||
isEmpty = \list ->
|
|
||||||
when list is
|
|
||||||
Cons _ _ ->
|
|
||||||
False
|
|
||||||
|
|
||||||
Nil ->
|
|
||||||
True
|
|
|
@ -1,341 +0,0 @@
|
||||||
interface RBTree exposes [ Dict, empty, size, singleton, isEmpty, insert, remove, update, fromList, toList, balance ] imports []
|
|
||||||
|
|
||||||
# The color of a node. Leaves are considered Black.
|
|
||||||
NodeColor : [ Red, Black ]
|
|
||||||
|
|
||||||
Dict k v : [ Node NodeColor k v (Dict k v) (Dict k v), Empty ]
|
|
||||||
|
|
||||||
Key k : Num k
|
|
||||||
|
|
||||||
Maybe a : [ Just a, Nothing ]
|
|
||||||
|
|
||||||
# Create an empty dictionary.
|
|
||||||
empty : Dict k v
|
|
||||||
empty =
|
|
||||||
Empty
|
|
||||||
|
|
||||||
# Create a dictionary with one key-value pair.
|
|
||||||
singleton : Key k, v -> Dict (Key k) v
|
|
||||||
singleton = \key, value ->
|
|
||||||
# Root node is always Black
|
|
||||||
Node Black key value Empty Empty
|
|
||||||
|
|
||||||
# {-| Determine the number of key-value pairs in the dictionary. -}
|
|
||||||
size : Dict k v -> Int *
|
|
||||||
size = \dict ->
|
|
||||||
sizeHelp 0 dict
|
|
||||||
|
|
||||||
sizeHelp : Int *, Dict k v -> Int *
|
|
||||||
sizeHelp = \n, dict ->
|
|
||||||
when dict is
|
|
||||||
Empty ->
|
|
||||||
n
|
|
||||||
|
|
||||||
Node _ _ _ left right ->
|
|
||||||
sizeHelp (sizeHelp (n + 1) right) left
|
|
||||||
|
|
||||||
isEmpty : Dict k v -> Bool
|
|
||||||
isEmpty = \dict ->
|
|
||||||
when dict is
|
|
||||||
Empty ->
|
|
||||||
True
|
|
||||||
|
|
||||||
Node _ _ _ _ _ ->
|
|
||||||
False
|
|
||||||
|
|
||||||
insert : Key k, v, Dict (Key k) v -> Dict (Key k) v
|
|
||||||
insert = \key, value, dict ->
|
|
||||||
when insertHelp key value dict is
|
|
||||||
Node Red k v l r ->
|
|
||||||
Node Black k v l r
|
|
||||||
|
|
||||||
x ->
|
|
||||||
x
|
|
||||||
|
|
||||||
insertHelp : Key k, v, Dict (Key k) v -> Dict (Key k) v
|
|
||||||
insertHelp = \key, value, dict ->
|
|
||||||
when dict is
|
|
||||||
Empty ->
|
|
||||||
# New nodes are always red. If it violates the rules, it will be fixed
|
|
||||||
# when balancing.
|
|
||||||
Node Red key value Empty Empty
|
|
||||||
|
|
||||||
Node nColor nKey nValue nLeft nRight ->
|
|
||||||
when Num.compare key nKey is
|
|
||||||
LT ->
|
|
||||||
balance nColor nKey nValue (insertHelp key value nLeft) nRight
|
|
||||||
|
|
||||||
EQ ->
|
|
||||||
Node nColor nKey value nLeft nRight
|
|
||||||
|
|
||||||
GT ->
|
|
||||||
balance nColor nKey nValue nLeft (insertHelp key value nRight)
|
|
||||||
|
|
||||||
balance : NodeColor, k, v, Dict k v, Dict k v -> Dict k v
|
|
||||||
balance = \color, key, value, left, right ->
|
|
||||||
when right is
|
|
||||||
Node Red rK rV rLeft rRight ->
|
|
||||||
when left is
|
|
||||||
Node Red lK lV lLeft lRight ->
|
|
||||||
Node
|
|
||||||
Red
|
|
||||||
key
|
|
||||||
value
|
|
||||||
(Node Black lK lV lLeft lRight)
|
|
||||||
(Node Black rK rV rLeft rRight)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
Node color rK rV (Node Red key value left rLeft) rRight
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
when left is
|
|
||||||
Node Red lK lV (Node Red llK llV llLeft llRight) lRight ->
|
|
||||||
Node
|
|
||||||
Red
|
|
||||||
lK
|
|
||||||
lV
|
|
||||||
(Node Black llK llV llLeft llRight)
|
|
||||||
(Node Black key value lRight right)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
Node color key value left right
|
|
||||||
|
|
||||||
remove : Key k, Dict (Key k) v -> Dict (Key k) v
|
|
||||||
remove = \key, dict ->
|
|
||||||
# Root node is always Black
|
|
||||||
when removeHelp key dict is
|
|
||||||
Node Red k v l r ->
|
|
||||||
Node Black k v l r
|
|
||||||
|
|
||||||
x ->
|
|
||||||
x
|
|
||||||
|
|
||||||
# The easiest thing to remove from the tree, is a red node. However, when searching for the
|
|
||||||
# node to remove, we have no way of knowing if it will be red or not. This remove implementation
|
|
||||||
# makes sure that the bottom node is red by moving red colors down the tree through rotation
|
|
||||||
# and color flips. Any violations this will cause, can easily be fixed by balancing on the way
|
|
||||||
# up again.
|
|
||||||
removeHelp : Key k, Dict (Key k) v -> Dict (Key k) v
|
|
||||||
removeHelp = \targetKey, dict ->
|
|
||||||
when dict is
|
|
||||||
Empty ->
|
|
||||||
Empty
|
|
||||||
|
|
||||||
Node color key value left right ->
|
|
||||||
if targetKey < key then
|
|
||||||
when left is
|
|
||||||
Node Black _ _ lLeft _ ->
|
|
||||||
when lLeft is
|
|
||||||
Node Red _ _ _ _ ->
|
|
||||||
Node color key value (removeHelp targetKey left) right
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
when moveRedLeft dict is
|
|
||||||
Node nColor nKey nValue nLeft nRight ->
|
|
||||||
balance nColor nKey nValue (removeHelp targetKey nLeft) nRight
|
|
||||||
|
|
||||||
Empty ->
|
|
||||||
Empty
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
Node color key value (removeHelp targetKey left) right
|
|
||||||
else
|
|
||||||
removeHelpEQGT targetKey (removeHelpPrepEQGT targetKey dict color key value left right)
|
|
||||||
|
|
||||||
removeHelpPrepEQGT : Key k, Dict (Key k) v, NodeColor, Key k, v, Dict (Key k) v, Dict (Key k) v -> Dict (Key k) v
|
|
||||||
removeHelpPrepEQGT = \_, dict, color, key, value, left, right ->
|
|
||||||
when left is
|
|
||||||
Node Red lK lV lLeft lRight ->
|
|
||||||
Node
|
|
||||||
color
|
|
||||||
lK
|
|
||||||
lV
|
|
||||||
lLeft
|
|
||||||
(Node Red key value lRight right)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
when right is
|
|
||||||
Node Black _ _ (Node Black _ _ _ _) _ ->
|
|
||||||
moveRedRight dict
|
|
||||||
|
|
||||||
Node Black _ _ Empty _ ->
|
|
||||||
moveRedRight dict
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
dict
|
|
||||||
|
|
||||||
# When we find the node we are looking for, we can remove by replacing the key-value
|
|
||||||
# pair with the key-value pair of the left-most node on the right side (the closest pair).
|
|
||||||
removeHelpEQGT : Key k, Dict (Key k) v -> Dict (Key k) v
|
|
||||||
removeHelpEQGT = \targetKey, dict ->
|
|
||||||
when dict is
|
|
||||||
Node color key value left right ->
|
|
||||||
if targetKey == key then
|
|
||||||
when getMin right is
|
|
||||||
Node _ minKey minValue _ _ ->
|
|
||||||
balance color minKey minValue left (removeMin right)
|
|
||||||
|
|
||||||
Empty ->
|
|
||||||
Empty
|
|
||||||
else
|
|
||||||
balance color key value left (removeHelp targetKey right)
|
|
||||||
|
|
||||||
Empty ->
|
|
||||||
Empty
|
|
||||||
|
|
||||||
getMin : Dict k v -> Dict k v
|
|
||||||
getMin = \dict ->
|
|
||||||
when dict is
|
|
||||||
# Node _ _ _ ((Node _ _ _ _ _) as left) _ ->
|
|
||||||
Node _ _ _ left _ ->
|
|
||||||
when left is
|
|
||||||
Node _ _ _ _ _ ->
|
|
||||||
getMin left
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
dict
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
dict
|
|
||||||
|
|
||||||
moveRedLeft : Dict k v -> Dict k v
|
|
||||||
moveRedLeft = \dict ->
|
|
||||||
when dict is
|
|
||||||
# Node clr k v (Node lClr lK lV lLeft lRight) (Node rClr rK rV ((Node Red rlK rlV rlL rlR) as rLeft) rRight) ->
|
|
||||||
# Node clr k v (Node lClr lK lV lLeft lRight) (Node rClr rK rV rLeft rRight) ->
|
|
||||||
Node clr k v (Node _ lK lV lLeft lRight) (Node _ rK rV rLeft rRight) ->
|
|
||||||
when rLeft is
|
|
||||||
Node Red rlK rlV rlL rlR ->
|
|
||||||
Node
|
|
||||||
Red
|
|
||||||
rlK
|
|
||||||
rlV
|
|
||||||
(Node Black k v (Node Red lK lV lLeft lRight) rlL)
|
|
||||||
(Node Black rK rV rlR rRight)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
when clr is
|
|
||||||
Black ->
|
|
||||||
Node
|
|
||||||
Black
|
|
||||||
k
|
|
||||||
v
|
|
||||||
(Node Red lK lV lLeft lRight)
|
|
||||||
(Node Red rK rV rLeft rRight)
|
|
||||||
|
|
||||||
Red ->
|
|
||||||
Node
|
|
||||||
Black
|
|
||||||
k
|
|
||||||
v
|
|
||||||
(Node Red lK lV lLeft lRight)
|
|
||||||
(Node Red rK rV rLeft rRight)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
dict
|
|
||||||
|
|
||||||
moveRedRight : Dict k v -> Dict k v
|
|
||||||
moveRedRight = \dict ->
|
|
||||||
when dict is
|
|
||||||
Node _ k v (Node _ lK lV (Node Red llK llV llLeft llRight) lRight) (Node _ rK rV rLeft rRight) ->
|
|
||||||
Node
|
|
||||||
Red
|
|
||||||
lK
|
|
||||||
lV
|
|
||||||
(Node Black llK llV llLeft llRight)
|
|
||||||
(Node Black k v lRight (Node Red rK rV rLeft rRight))
|
|
||||||
|
|
||||||
Node clr k v (Node _ lK lV lLeft lRight) (Node _ rK rV rLeft rRight) ->
|
|
||||||
when clr is
|
|
||||||
Black ->
|
|
||||||
Node
|
|
||||||
Black
|
|
||||||
k
|
|
||||||
v
|
|
||||||
(Node Red lK lV lLeft lRight)
|
|
||||||
(Node Red rK rV rLeft rRight)
|
|
||||||
|
|
||||||
Red ->
|
|
||||||
Node
|
|
||||||
Black
|
|
||||||
k
|
|
||||||
v
|
|
||||||
(Node Red lK lV lLeft lRight)
|
|
||||||
(Node Red rK rV rLeft rRight)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
dict
|
|
||||||
|
|
||||||
removeMin : Dict k v -> Dict k v
|
|
||||||
removeMin = \dict ->
|
|
||||||
when dict is
|
|
||||||
Node color key value left right ->
|
|
||||||
when left is
|
|
||||||
Node lColor _ _ lLeft _ ->
|
|
||||||
when lColor is
|
|
||||||
Black ->
|
|
||||||
when lLeft is
|
|
||||||
Node Red _ _ _ _ ->
|
|
||||||
Node color key value (removeMin left) right
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
when moveRedLeft dict is
|
|
||||||
Node nColor nKey nValue nLeft nRight ->
|
|
||||||
balance nColor nKey nValue (removeMin nLeft) nRight
|
|
||||||
|
|
||||||
Empty ->
|
|
||||||
Empty
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
Node color key value (removeMin left) right
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
Empty
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
Empty
|
|
||||||
|
|
||||||
# Update the value of a dictionary for a specific key with a given function.
|
|
||||||
update : Key k, (Maybe v -> Maybe v), Dict (Key k) v -> Dict (Key k) v
|
|
||||||
update = \targetKey, alter, dictionary ->
|
|
||||||
when alter (get targetKey dictionary) is
|
|
||||||
Just value ->
|
|
||||||
insert targetKey value dictionary
|
|
||||||
|
|
||||||
Nothing ->
|
|
||||||
remove targetKey dictionary
|
|
||||||
|
|
||||||
get : Key k, Dict (Key k) v -> Maybe v
|
|
||||||
get = \targetKey, dict ->
|
|
||||||
when dict is
|
|
||||||
Empty ->
|
|
||||||
Nothing
|
|
||||||
|
|
||||||
Node _ key value left right ->
|
|
||||||
when Num.compare targetKey key is
|
|
||||||
LT ->
|
|
||||||
get targetKey left
|
|
||||||
|
|
||||||
EQ ->
|
|
||||||
Just value
|
|
||||||
|
|
||||||
GT ->
|
|
||||||
get targetKey right
|
|
||||||
|
|
||||||
fromList : List { key : Num k, value : v } -> Dict (Num k) v
|
|
||||||
fromList = \xs ->
|
|
||||||
List.walkRight xs (\{ key, value }, dict -> insert key value dict) empty
|
|
||||||
|
|
||||||
foldr : (k, v, b -> b), b, Dict k v -> b
|
|
||||||
foldr = \func, acc, t ->
|
|
||||||
when t is
|
|
||||||
Empty ->
|
|
||||||
acc
|
|
||||||
|
|
||||||
Node _ key value left right ->
|
|
||||||
foldr func (func key value (foldr func acc right)) left
|
|
||||||
|
|
||||||
# Convert a dictionary into an association list of key-value pairs, sorted by keys.
|
|
||||||
toList : Dict k v -> List { key : k, value : v }
|
|
||||||
toList = \dict ->
|
|
||||||
foldr (\key, value, list -> List.append list { key, value }) [] dict
|
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/cli"
|
platform "false-interpreter"
|
||||||
requires {} { main : Str -> Task {} [] }
|
requires {} { main : Str -> Task {} [] }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
||||||
|
|
2
examples/fib/.gitignore
vendored
2
examples/fib/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
add
|
|
||||||
fib
|
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/hello-world"
|
platform "gui"
|
||||||
requires {} { render : Elem }
|
requires {} { render : Elem }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
||||||
|
|
1
examples/hello-rust/.gitignore
vendored
1
examples/hello-rust/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
hello-rust
|
|
|
@ -1,12 +0,0 @@
|
||||||
app "hello-rust"
|
|
||||||
packages { pf: "platform" }
|
|
||||||
imports []
|
|
||||||
provides [ main ] to pf
|
|
||||||
|
|
||||||
greeting =
|
|
||||||
hi = "Hello"
|
|
||||||
name = "World"
|
|
||||||
|
|
||||||
"\(hi), \(name)!\n"
|
|
||||||
|
|
||||||
main = greeting
|
|
1
examples/hello-swift/.gitignore
vendored
1
examples/hello-swift/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
hello-swift
|
|
|
@ -1,10 +0,0 @@
|
||||||
app "hello-swift"
|
|
||||||
packages { pf: "platform" }
|
|
||||||
imports []
|
|
||||||
provides [ main ] to pf
|
|
||||||
|
|
||||||
main =
|
|
||||||
host = "Swift"
|
|
||||||
app = "Roc"
|
|
||||||
|
|
||||||
"Hello \(host), meet \(app)"
|
|
2
examples/hello-web/.gitignore
vendored
2
examples/hello-web/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
hello-web.wasm
|
|
||||||
*.wat
|
|
|
@ -1,12 +0,0 @@
|
||||||
app "hello-web"
|
|
||||||
packages { pf: "platform" }
|
|
||||||
imports []
|
|
||||||
provides [ main ] to pf
|
|
||||||
|
|
||||||
greeting =
|
|
||||||
hi = "Hello"
|
|
||||||
name = "World"
|
|
||||||
|
|
||||||
"\(hi), \(name)!"
|
|
||||||
|
|
||||||
main = greeting
|
|
8
examples/hello-world/.gitignore
vendored
8
examples/hello-world/.gitignore
vendored
|
@ -1 +1,7 @@
|
||||||
hello-world
|
helloC
|
||||||
|
helloRust
|
||||||
|
helloSwift
|
||||||
|
helloWeb.wasm
|
||||||
|
helloWorld
|
||||||
|
helloWorld.wasm
|
||||||
|
helloZig
|
||||||
|
|
|
@ -3,19 +3,19 @@
|
||||||
To run, `cd` into this directory and run:
|
To run, `cd` into this directory and run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cargo run Hello.roc
|
cargo run helloWorld.roc
|
||||||
```
|
```
|
||||||
|
|
||||||
To run in release mode instead, do:
|
To run in release mode instead, do:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cargo run --release Hello.roc
|
cargo run --release helloWorld.roc
|
||||||
```
|
```
|
||||||
|
|
||||||
## Design Notes
|
## Design Notes
|
||||||
|
|
||||||
This demonstrates the basic design of hosts: Roc code gets compiled into a pure
|
This demonstrates the basic design of hosts: Roc code gets compiled into a pure
|
||||||
function (in this case, a thunk that always returns `"Hello, World!"`) and
|
function (in this case, a thunk that always returns `"Hello, World!\n"`) and
|
||||||
then the host calls that function. Fundamentally, that's the whole idea! The host
|
then the host calls that function. Fundamentally, that's the whole idea! The host
|
||||||
might not even have a `main` - it could be a library, a plugin, anything.
|
might not even have a `main` - it could be a library, a plugin, anything.
|
||||||
Everything else is built on this basic "hosts calling linked pure functions" design.
|
Everything else is built on this basic "hosts calling linked pure functions" design.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/hello-swift"
|
platform "hello-world-in-c"
|
||||||
requires {} { main : Str }
|
requires {} { main : Str }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
|
@ -1,5 +1,5 @@
|
||||||
app "hello-world"
|
app "helloC"
|
||||||
packages { pf: "platform" }
|
packages { pf: "." }
|
||||||
imports []
|
imports []
|
||||||
provides [ main ] to pf
|
provides [ main ] to pf
|
||||||
|
|
11
examples/hello-world/helloWorld.roc
Normal file
11
examples/hello-world/helloWorld.roc
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
app "helloWorld"
|
||||||
|
packages { pf: "c-platform" }
|
||||||
|
# To switch platforms, comment-out the line above and un-comment one below.
|
||||||
|
# packages { pf: "rust-platform" }
|
||||||
|
# packages { pf: "swift-platform" }
|
||||||
|
# packages { pf: "web-platform" } # See ./web-platform/README.md
|
||||||
|
# packages { pf: "zig-platform" }
|
||||||
|
imports []
|
||||||
|
provides [ main ] to pf
|
||||||
|
|
||||||
|
main = "Hello, World!\n"
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/hello-world"
|
platform "hello-world-in-rust"
|
||||||
requires {} { main : Str }
|
requires {} { main : Str }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
6
examples/hello-world/rust-platform/helloRust.roc
Normal file
6
examples/hello-world/rust-platform/helloRust.roc
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
app "helloRust"
|
||||||
|
packages { pf: "." }
|
||||||
|
imports []
|
||||||
|
provides [ main ] to pf
|
||||||
|
|
||||||
|
main = "Hello, World!\n"
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/hello-world"
|
platform "hello-world-in-swift"
|
||||||
requires {} { main : Str }
|
requires {} { main : Str }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
6
examples/hello-world/swift-platform/helloSwift.roc
Normal file
6
examples/hello-world/swift-platform/helloSwift.roc
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
app "helloSwift"
|
||||||
|
packages { pf: "." }
|
||||||
|
imports []
|
||||||
|
provides [ main ] to pf
|
||||||
|
|
||||||
|
main = "Hello, World!\n"
|
|
@ -53,6 +53,6 @@ extension RocStr {
|
||||||
|
|
||||||
@_cdecl("main")
|
@_cdecl("main")
|
||||||
func main() -> UInt8 {
|
func main() -> UInt8 {
|
||||||
print(roc__mainForHost_1_exposed().string)
|
print(roc__mainForHost_1_exposed().string, terminator: "")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
9
examples/hello-world/web-platform/Package-Config.roc
Normal file
9
examples/hello-world/web-platform/Package-Config.roc
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
platform "hello-world-in-web-assembly"
|
||||||
|
requires {} { main : Str }
|
||||||
|
exposes []
|
||||||
|
packages {}
|
||||||
|
imports []
|
||||||
|
provides [ mainForHost ]
|
||||||
|
|
||||||
|
mainForHost : Str
|
||||||
|
mainForHost = main
|
|
@ -1,16 +1,22 @@
|
||||||
# Hello, World!
|
# Hello, World!
|
||||||
|
|
||||||
To run, go to the project home directory and run:
|
To run this website, first compile either of these identical apps:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cargo run -- build --target=wasm32 examples/hello-web/Hello.roc
|
# Option A: Compile helloWeb.roc
|
||||||
|
cargo run -- build --target=wasm32 examples/hello-world/web-platform/helloWeb.roc
|
||||||
|
|
||||||
|
# Option B: Compile helloWorld.roc with `pf: "web-platform"` and move the result
|
||||||
|
cargo run -- build --target=wasm32 examples/hello-world/helloWorld.roc
|
||||||
|
(cd examples/hello-world && mv helloWorld.wasm web-platform/helloWeb.wasm)
|
||||||
```
|
```
|
||||||
|
|
||||||
Then `cd` into the example directory and run any web server that can handle WebAssembly.
|
Then `cd` into the website directory
|
||||||
For example with `http-server`:
|
and run any web server that can handle WebAssembly.
|
||||||
|
For example, with `http-server`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd examples/hello-web
|
cd examples/hello-world/web-platform
|
||||||
npm install -g http-server
|
npm install -g http-server
|
||||||
http-server
|
http-server
|
||||||
```
|
```
|
||||||
|
@ -20,7 +26,7 @@ Now open your browser at http://localhost:8080
|
||||||
## Design Notes
|
## Design Notes
|
||||||
|
|
||||||
This demonstrates the basic design of hosts: Roc code gets compiled into a pure
|
This demonstrates the basic design of hosts: Roc code gets compiled into a pure
|
||||||
function (in this case, a thunk that always returns `"Hello, World!"`) and
|
function (in this case, a thunk that always returns `"Hello, World!\n"`) and
|
||||||
then the host calls that function. Fundamentally, that's the whole idea! The host
|
then the host calls that function. Fundamentally, that's the whole idea! The host
|
||||||
might not even have a `main` - it could be a library, a plugin, anything.
|
might not even have a `main` - it could be a library, a plugin, anything.
|
||||||
Everything else is built on this basic "hosts calling linked pure functions" design.
|
Everything else is built on this basic "hosts calling linked pure functions" design.
|
6
examples/hello-world/web-platform/helloWeb.roc
Normal file
6
examples/hello-world/web-platform/helloWeb.roc
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
app "helloWeb"
|
||||||
|
packages { pf: "." }
|
||||||
|
imports []
|
||||||
|
provides [ main ] to pf
|
||||||
|
|
||||||
|
main = "Hello, World!\n"
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Node.js test file for hello-web example
|
* Node.js test file for helloWeb example
|
||||||
* We are not running this in CI currently, and Node.js is not a Roc dependency.
|
* We are not running this in CI currently, and Node.js is not a Roc dependency.
|
||||||
* But if you happen to have it, you can run this.
|
* But if you happen to have it, you can run this.
|
||||||
*/
|
*/
|
||||||
|
@ -13,10 +13,10 @@ global.fetch = (filename) =>
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const { roc_web_platform_run } = require("./platform/host");
|
const { roc_web_platform_run } = require("./host");
|
||||||
|
|
||||||
roc_web_platform_run("./hello-world.wasm", (string_from_roc) => {
|
roc_web_platform_run("../helloWeb.wasm", (string_from_roc) => {
|
||||||
const expected = "Hello, World!";
|
const expected = "Hello, World!\n";
|
||||||
if (string_from_roc !== expected) {
|
if (string_from_roc !== expected) {
|
||||||
console.error(`Expected "${expected}", but got "${string_from_roc}"`);
|
console.error(`Expected "${expected}", but got "${string_from_roc}"`);
|
||||||
process.exit(1);
|
process.exit(1);
|
|
@ -1,10 +1,10 @@
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<div id="output"></div>
|
<div id="output"></div>
|
||||||
<script src="platform/host.js"></script>
|
<script src="./host.js"></script>
|
||||||
<script>
|
<script>
|
||||||
const elem = document.getElementById("output");
|
const elem = document.getElementById("output");
|
||||||
roc_web_platform_run("./hello-web.wasm", (string_from_roc) => {
|
roc_web_platform_run("./helloWeb.wasm", (string_from_roc) => {
|
||||||
elem.textContent = string_from_roc;
|
elem.textContent = string_from_roc;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/hello-world"
|
platform "hello-world-in-zig"
|
||||||
requires {} { main : Str }
|
requires {} { main : Str }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
6
examples/hello-world/zig-platform/helloZig.roc
Normal file
6
examples/hello-world/zig-platform/helloZig.roc
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
app "helloZig"
|
||||||
|
packages { pf: "." }
|
||||||
|
imports []
|
||||||
|
provides [ main ] to pf
|
||||||
|
|
||||||
|
main = "Hello, World!\n"
|
|
@ -97,7 +97,7 @@ pub fn main() u8 {
|
||||||
std.os.clock_gettime(std.os.CLOCK_REALTIME, &ts2) catch unreachable;
|
std.os.clock_gettime(std.os.CLOCK_REALTIME, &ts2) catch unreachable;
|
||||||
|
|
||||||
// stdout the result
|
// stdout the result
|
||||||
stdout.print("{s}\n", .{callresult.asSlice()}) catch unreachable;
|
stdout.print("{s}", .{callresult.asSlice()}) catch unreachable;
|
||||||
|
|
||||||
callresult.deinit();
|
callresult.deinit();
|
||||||
|
|
1
examples/hello-zig/.gitignore
vendored
1
examples/hello-zig/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
hello-world
|
|
|
@ -1,12 +0,0 @@
|
||||||
app "hello-world"
|
|
||||||
packages { pf: "platform" }
|
|
||||||
imports []
|
|
||||||
provides [ main ] to pf
|
|
||||||
|
|
||||||
greeting =
|
|
||||||
hi = "Hello"
|
|
||||||
name = "World"
|
|
||||||
|
|
||||||
"\(hi), \(name)!"
|
|
||||||
|
|
||||||
main = greeting
|
|
|
@ -1,44 +0,0 @@
|
||||||
# Hello, World!
|
|
||||||
|
|
||||||
To run, `cd` into this directory and run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ cargo run Hello.roc
|
|
||||||
```
|
|
||||||
|
|
||||||
To run in release mode instead, do:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ cargo run --release Hello.roc
|
|
||||||
```
|
|
||||||
|
|
||||||
## Design Notes
|
|
||||||
|
|
||||||
This demonstrates the basic design of hosts: Roc code gets compiled into a pure
|
|
||||||
function (in this case, a thunk that always returns `"Hello, World!"`) and
|
|
||||||
then the host calls that function. Fundamentally, that's the whole idea! The host
|
|
||||||
might not even have a `main` - it could be a library, a plugin, anything.
|
|
||||||
Everything else is built on this basic "hosts calling linked pure functions" design.
|
|
||||||
|
|
||||||
For example, things get more interesting when the compiled Roc function returns
|
|
||||||
a `Task` - that is, a tagged union data structure containing function pointers
|
|
||||||
to callback closures. This lets the Roc pure function describe arbitrary
|
|
||||||
chainable effects, which the host can interpret to perform I/O as requested by
|
|
||||||
the Roc program. (The tagged union `Task` would have a variant for each supported
|
|
||||||
I/O operation.)
|
|
||||||
|
|
||||||
In this trivial example, it's very easy to line up the API between the host and
|
|
||||||
the Roc program. In a more involved host, this would be much trickier - especially
|
|
||||||
if the API were changing frequently during development.
|
|
||||||
|
|
||||||
The idea there is to have a first-class concept of "glue code" which host authors
|
|
||||||
can write (it would be plain Roc code, but with some extra keywords that aren't
|
|
||||||
available in normal modules - kinda like `port module` in Elm), and which
|
|
||||||
describe both the Roc-host/C boundary as well as the Roc-host/Roc-app boundary.
|
|
||||||
Roc application authors only care about the Roc-host/Roc-app portion, and the
|
|
||||||
host author only cares about the Roc-host/C boundary when implementing the host.
|
|
||||||
|
|
||||||
Using this glue code, the Roc compiler can generate C header files describing the
|
|
||||||
boundary. This not only gets us host compatibility with C compilers, but also
|
|
||||||
Rust FFI for free, because [`rust-bindgen`](https://github.com/rust-lang/rust-bindgen)
|
|
||||||
generates correct Rust FFI bindings from C headers.
|
|
|
@ -1,9 +0,0 @@
|
||||||
platform "examples/hello-world"
|
|
||||||
requires {} { main : Str }
|
|
||||||
exposes []
|
|
||||||
packages {}
|
|
||||||
imports []
|
|
||||||
provides [ mainForHost ]
|
|
||||||
|
|
||||||
mainForHost : Str
|
|
||||||
mainForHost = main
|
|
|
@ -1,3 +1,5 @@
|
||||||
countdown
|
countdown
|
||||||
echo
|
echo
|
||||||
|
effects
|
||||||
form
|
form
|
||||||
|
tui
|
9
examples/interactive/README.md
Normal file
9
examples/interactive/README.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Interactive examples
|
||||||
|
|
||||||
|
These are examples of how to make extremely basic
|
||||||
|
CLI (command-line interface) and TUI (terminal user interface) apps in Roc.
|
||||||
|
|
||||||
|
There's not currently much documentation for the CLI platform (which also doesn't support many operations at this point!)
|
||||||
|
but you can look at [the modules it includes](cli-platform) - for example,
|
||||||
|
multiple other modules use the [`Task`](cli-platform/Task.roc) module, including the
|
||||||
|
[`Stdin`](cli-platform/Stdin.roc) and [`Stdout`](cli-platform/Stdout.roc) modules.
|
|
@ -1,4 +1,4 @@
|
||||||
platform "examples/cli"
|
platform "cli"
|
||||||
requires {} { main : Task {} [] }
|
requires {} { main : Task {} [] }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
|
@ -1,5 +1,5 @@
|
||||||
app "countdown"
|
app "countdown"
|
||||||
packages { pf: "platform" }
|
packages { pf: "cli-platform" }
|
||||||
imports [ pf.Stdin, pf.Stdout, pf.Task.{ await, loop, succeed } ]
|
imports [ pf.Stdin, pf.Stdout, pf.Task.{ await, loop, succeed } ]
|
||||||
provides [ main ] to pf
|
provides [ main ] to pf
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
app "echo"
|
app "echo"
|
||||||
packages { pf: "platform" }
|
packages { pf: "cli-platform" }
|
||||||
imports [ pf.Stdin, pf.Stdout, pf.Task ]
|
imports [ pf.Stdin, pf.Stdout, pf.Task ]
|
||||||
provides [ main ] to pf
|
provides [ main ] to pf
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
platform "roc-examples/cli"
|
platform "effects"
|
||||||
requires {} { main : Effect {} }
|
requires {} { main : Effect {} }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
|
@ -1,5 +1,5 @@
|
||||||
app "effect-example"
|
app "effects"
|
||||||
packages { pf: "thing/platform-dir" }
|
packages { pf: "effects-platform" }
|
||||||
imports [ pf.Effect ]
|
imports [ pf.Effect ]
|
||||||
provides [ main ] to pf
|
provides [ main ] to pf
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
app "form"
|
app "form"
|
||||||
packages { pf: "platform" }
|
packages { pf: "cli-platform" }
|
||||||
imports [ pf.Stdin, pf.Stdout, pf.Task.{ await, Task } ]
|
imports [ pf.Stdin, pf.Stdout, pf.Task.{ await, Task } ]
|
||||||
provides [ main ] to pf
|
provides [ main ] to pf
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
platform "folkertdev/foo"
|
platform "tui"
|
||||||
requires { Model } { main : Effect {} }
|
requires { Model } { main : Effect {} }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
|
@ -1,5 +1,5 @@
|
||||||
app "tui"
|
app "tui"
|
||||||
packages { pf: "platform" }
|
packages { pf: "tui-platform" }
|
||||||
imports [ pf.Program.{ Program } ]
|
imports [ pf.Program.{ Program } ]
|
||||||
provides [ main ] { Model } to pf
|
provides [ main ] { Model } to pf
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
# Quicksort
|
|
||||||
|
|
||||||
To run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ cargo run Quicksort.roc
|
|
||||||
```
|
|
||||||
|
|
||||||
To run in release mode instead, do:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ cargo run --release Quicksort.roc
|
|
||||||
```
|
|
1
examples/tui/.gitignore
vendored
1
examples/tui/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
tui
|
|
|
@ -22,11 +22,11 @@
|
||||||
0. Run examples with:
|
0. Run examples with:
|
||||||
```
|
```
|
||||||
# Rust. If you installed rust in this terminal you'll need to open a new one first!
|
# Rust. If you installed rust in this terminal you'll need to open a new one first!
|
||||||
./roc examples/hello-rust/Hello.roc
|
./roc examples/hello-world/rust-platform/helloRust.roc
|
||||||
# Zig
|
# Zig
|
||||||
./roc examples/hello-zig/Hello.roc
|
./roc examples/hello-world/zig-platform/helloZig.roc
|
||||||
# C
|
# C
|
||||||
./roc examples/hello-world/Hello.roc
|
./roc examples/hello-world/c-platform/helloC.roc
|
||||||
```
|
```
|
||||||
0. See [here](../README.md#examples) for the other examples.
|
0. See [here](../README.md#examples) for the other examples.
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
3. Run examples with:
|
3. Run examples with:
|
||||||
```
|
```
|
||||||
# Rust
|
# Rust
|
||||||
cargo run examples/hello-rust/Hello.roc
|
cargo run examples/hello-world/rust-platform/helloRust.roc
|
||||||
# Zig
|
# Zig
|
||||||
cargo run examples/hello-zig/Hello.roc
|
cargo run examples/hello-world/zig-platform/helloZig.roc
|
||||||
# C
|
# C
|
||||||
cargo run examples/hello-world/Hello.roc
|
cargo run examples/hello-world/c-platform/helloC.roc
|
||||||
```
|
```
|
||||||
4. See [here](../README.md#examples) for the other examples.
|
4. See [here](../README.md#examples) for the other examples.
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub trait ReplAppMemory {
|
||||||
|
|
||||||
fn deref_dec(&self, addr: usize) -> RocDec {
|
fn deref_dec(&self, addr: usize) -> RocDec {
|
||||||
let bits = self.deref_i128(addr);
|
let bits = self.deref_i128(addr);
|
||||||
RocDec(bits)
|
RocDec::new(bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deref_str(&self, addr: usize) -> &str;
|
fn deref_str(&self, addr: usize) -> &str;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue