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 date >> version.txt
|
||||
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
|
||||
|
||||
# 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:
|
||||
```
|
||||
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.
|
||||
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);
|
||||
|
||||
match example.executable_filename {
|
||||
"hello-web" => {
|
||||
"helloWeb" => {
|
||||
// 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);
|
||||
return;
|
||||
}
|
||||
"hello-swift" => {
|
||||
"helloSwift" => {
|
||||
if cfg!(not(target_os = "macos")) {
|
||||
eprintln!("WARNING: skipping testing example {} because it only works on MacOS.", example.filename);
|
||||
return;
|
||||
|
@ -324,49 +324,57 @@ mod cli_run {
|
|||
// },
|
||||
// ]
|
||||
examples! {
|
||||
hello_world:"hello-world" => Example {
|
||||
filename: "Hello.roc",
|
||||
executable_filename: "hello-world",
|
||||
helloWorld:"hello-world" => Example {
|
||||
filename: "helloWorld.roc",
|
||||
executable_filename: "helloWorld",
|
||||
stdin: &[],
|
||||
input_file: None,
|
||||
expected_ending:"Hello, World!\n",
|
||||
use_valgrind: true,
|
||||
},
|
||||
hello_zig:"hello-zig" => Example {
|
||||
filename: "Hello.roc",
|
||||
executable_filename: "hello-world",
|
||||
helloC:"hello-world/c-platform" => Example {
|
||||
filename: "helloC.roc",
|
||||
executable_filename: "helloC",
|
||||
stdin: &[],
|
||||
input_file: None,
|
||||
expected_ending:"Hello, World!\n",
|
||||
use_valgrind: true,
|
||||
},
|
||||
hello_rust:"hello-rust" => Example {
|
||||
filename: "Hello.roc",
|
||||
executable_filename: "hello-rust",
|
||||
helloZig:"hello-world/zig-platform" => Example {
|
||||
filename: "helloZig.roc",
|
||||
executable_filename: "helloZig",
|
||||
stdin: &[],
|
||||
input_file: None,
|
||||
expected_ending:"Hello, World!\n",
|
||||
use_valgrind: true,
|
||||
},
|
||||
hello_swift:"hello-swift" => Example {
|
||||
filename: "Hello.roc",
|
||||
executable_filename: "hello-swift",
|
||||
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",
|
||||
helloRust:"hello-world/rust-platform" => Example {
|
||||
filename: "helloRust.roc",
|
||||
executable_filename: "helloRust",
|
||||
stdin: &[],
|
||||
input_file: None,
|
||||
expected_ending:"Hello, World!\n",
|
||||
use_valgrind: true,
|
||||
},
|
||||
fib:"fib" => Example {
|
||||
filename: "Fib.roc",
|
||||
executable_filename: "fib",
|
||||
helloSwift:"hello-world/swift-platform" => Example {
|
||||
filename: "helloSwift.roc",
|
||||
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: &[],
|
||||
input_file: None,
|
||||
expected_ending:"55\n",
|
||||
|
@ -380,8 +388,8 @@ mod cli_run {
|
|||
expected_ending: "",
|
||||
use_valgrind: false,
|
||||
},
|
||||
quicksort:"quicksort" => Example {
|
||||
filename: "Quicksort.roc",
|
||||
quicksort:"algorithms" => Example {
|
||||
filename: "quicksort.roc",
|
||||
executable_filename: "quicksort",
|
||||
stdin: &[],
|
||||
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",
|
||||
// use_valgrind: true,
|
||||
// },
|
||||
effect:"effect" => Example {
|
||||
filename: "Main.roc",
|
||||
executable_filename: "effect-example",
|
||||
effects:"interactive" => Example {
|
||||
filename: "effects.roc",
|
||||
executable_filename: "effects",
|
||||
stdin: &["hi there!"],
|
||||
input_file: None,
|
||||
expected_ending: "hi there!\nIt is known\n",
|
||||
|
@ -412,7 +420,7 @@ mod cli_run {
|
|||
// expected_ending: "",
|
||||
// use_valgrind: true,
|
||||
// },
|
||||
cli:"cli" => Example {
|
||||
cli:"interactive" => Example {
|
||||
filename: "form.roc",
|
||||
executable_filename: "form",
|
||||
stdin: &["Giovanni\n", "Giorgio\n"],
|
||||
|
@ -420,8 +428,8 @@ mod cli_run {
|
|||
expected_ending: "Hi, Giovanni Giorgio! 👋\n",
|
||||
use_valgrind: true,
|
||||
},
|
||||
tui:"tui" => Example {
|
||||
filename: "Main.roc",
|
||||
tui:"interactive" => Example {
|
||||
filename: "tui.roc",
|
||||
executable_filename: "tui",
|
||||
stdin: &["foo\n"], // NOTE: adding more lines leads to memory leaks
|
||||
input_file: None,
|
||||
|
@ -706,6 +714,22 @@ mod cli_run {
|
|||
if entry.file_type().unwrap().is_dir() {
|
||||
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
|
||||
if example_dir_name != "benchmarks" {
|
||||
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 }
|
||||
exposes []
|
||||
packages {}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
platform "examples/multi-dep-thunk"
|
||||
platform "multi-dep-thunk"
|
||||
requires {}{ main : Str }
|
||||
exposes []
|
||||
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),
|
||||
},
|
||||
|
||||
Decimal(int) => env
|
||||
.context
|
||||
Decimal(int) => {
|
||||
let (upper_bits, lower_bits) = int.as_bits();
|
||||
env.context
|
||||
.i128_type()
|
||||
.const_int(int.0 as u64, false)
|
||||
.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(),
|
||||
Byte(b) => env.context.i8_type().const_int(*b as u64, false).into(),
|
||||
Str(str_literal) => {
|
||||
|
|
|
@ -637,9 +637,8 @@ impl<'a> WasmBackend<'a> {
|
|||
|
||||
match lit {
|
||||
Literal::Decimal(decimal) => {
|
||||
let lower_bits = (decimal.0 & 0xffff_ffff_ffff_ffff) as i64;
|
||||
let upper_bits = (decimal.0 >> 64) as i64;
|
||||
write128(lower_bits, upper_bits);
|
||||
let (upper_bits, lower_bits) = decimal.as_bits();
|
||||
write128(lower_bits as i64, upper_bits);
|
||||
}
|
||||
Literal::Int(x) => {
|
||||
let lower_bits = (*x & 0xffff_ffff_ffff_ffff) as i64;
|
||||
|
|
|
@ -647,7 +647,7 @@ mod test_load {
|
|||
"platform/Package-Config.roc",
|
||||
indoc!(
|
||||
r#"
|
||||
platform "examples/hello-world"
|
||||
platform "hello-c"
|
||||
requires {} { main : Str }
|
||||
exposes []
|
||||
packages {}
|
||||
|
@ -691,7 +691,7 @@ mod test_load {
|
|||
"platform/Package-Config.roc",
|
||||
indoc!(
|
||||
r#"
|
||||
platform "examples/hello-world"
|
||||
platform "hello-world"
|
||||
requires {} { main : { content: Str, other: Str } }
|
||||
exposes []
|
||||
packages {}
|
||||
|
|
|
@ -135,7 +135,7 @@ impl<'a> Hash for Test<'a> {
|
|||
IsDecimal(v) => {
|
||||
// TODO: Is this okay?
|
||||
state.write_u8(6);
|
||||
v.0.hash(state);
|
||||
v.hash(state);
|
||||
}
|
||||
IsU128(v) => {
|
||||
state.write_u8(7);
|
||||
|
@ -906,7 +906,7 @@ fn to_relevant_branch_help<'a>(
|
|||
},
|
||||
|
||||
DecimalLiteral(dec) => match test {
|
||||
IsDecimal(test_dec) if dec.0 == test_dec.0 => {
|
||||
IsDecimal(test_dec) if dec.eq(test_dec) => {
|
||||
start.extend(end);
|
||||
Some(Branch {
|
||||
goal: branch.goal,
|
||||
|
@ -1396,7 +1396,7 @@ fn test_to_equality<'a>(
|
|||
}
|
||||
|
||||
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();
|
||||
stores.push((lhs_symbol, *cond_layout, lhs));
|
||||
|
||||
|
|
|
@ -1536,8 +1536,7 @@ impl<'a> Literal<'a> {
|
|||
Int(lit) => alloc.text(format!("{}i64", lit)),
|
||||
U128(lit) => alloc.text(format!("{}u128", lit)),
|
||||
Float(lit) => alloc.text(format!("{}f64", lit)),
|
||||
// TODO: Add proper Dec.to_str
|
||||
Decimal(lit) => alloc.text(format!("{}Dec", lit.0)),
|
||||
Decimal(lit) => alloc.text(format!("{}dec", lit)),
|
||||
Bool(lit) => alloc.text(format!("{}", lit)),
|
||||
Byte(lit) => alloc.text(format!("{}u8", lit)),
|
||||
Str(lit) => alloc.text(format!("{:?}", lit)),
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
Platform {
|
||||
header: PlatformHeader {
|
||||
name: @9-23 PackageName(
|
||||
"examples/cli",
|
||||
name: @9-14 PackageName(
|
||||
"cli",
|
||||
),
|
||||
requires: PlatformRequires {
|
||||
rigids: [],
|
||||
signature: @41-58 TypedIdent {
|
||||
ident: @41-45 "main",
|
||||
signature: @32-49 TypedIdent {
|
||||
ident: @32-36 "main",
|
||||
spaces_before_colon: [],
|
||||
ann: @48-58 Apply(
|
||||
ann: @39-49 Apply(
|
||||
"",
|
||||
"Task",
|
||||
[
|
||||
@53-55 Record {
|
||||
@44-46 Record {
|
||||
fields: [],
|
||||
ext: None,
|
||||
},
|
||||
@56-58 TagUnion {
|
||||
@47-49 TagUnion {
|
||||
ext: None,
|
||||
tags: [],
|
||||
},
|
||||
|
@ -27,19 +27,19 @@ Platform {
|
|||
exposes: [],
|
||||
packages: [],
|
||||
imports: [
|
||||
@119-132 Module(
|
||||
@110-123 Module(
|
||||
ModuleName(
|
||||
"Task",
|
||||
),
|
||||
[
|
||||
@126-130 ExposedName(
|
||||
@117-121 ExposedName(
|
||||
"Task",
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
provides: [
|
||||
@150-161 ExposedName(
|
||||
@141-152 ExposedName(
|
||||
"mainForHost",
|
||||
),
|
||||
],
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
platform "examples/cli"
|
||||
platform "cli"
|
||||
requires {}{ main : Task {} [] } # TODO FIXME
|
||||
exposes []
|
||||
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
|
||||
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);
|
||||
|
||||
|
|
6
examples/.gitignore
vendored
6
examples/.gitignore
vendored
|
@ -1,10 +1,6 @@
|
|||
app
|
||||
*.o
|
||||
*.dSYM
|
||||
libhost.a
|
||||
roc_app.ll
|
||||
roc_app.bc
|
||||
libapp.so
|
||||
dynhost
|
||||
preprocessedhost
|
||||
metadata
|
||||
libapp.so
|
|
@ -1,13 +1,20 @@
|
|||
|
||||
# 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:
|
||||
1. Navigate to `/examples`
|
||||
2. Run with:
|
||||
```
|
||||
cargo run hello-world/Hello.roc
|
||||
```
|
||||
|
||||
1. Navigate to the examples directory
|
||||
|
||||
```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.
|
||||
For NQueens, input 10 in the terminal and press enter.
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
fibonacci
|
||||
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 }
|
||||
exposes []
|
||||
packages {}
|
|
@ -1,5 +1,5 @@
|
|||
app "fib"
|
||||
packages { pf: "platform" }
|
||||
app "fibonacci"
|
||||
packages { pf: "fibonacci-platform" }
|
||||
imports []
|
||||
provides [ main ] to pf
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
platform "examples/quicksort"
|
||||
platform "quicksort"
|
||||
requires {} { quicksort : List I64 -> List I64 }
|
||||
exposes []
|
||||
packages {}
|
|
@ -1,5 +1,5 @@
|
|||
app "quicksort"
|
||||
packages { pf: "platform" }
|
||||
packages { pf: "quicksort-platform" }
|
||||
imports []
|
||||
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
|
||||
rbtree-insert
|
||||
rbtree-del
|
||||
closure
|
||||
deriv
|
||||
issue2279
|
||||
nqueens
|
||||
quicksortapp
|
||||
rbtree-ck
|
||||
rbtree-del
|
||||
rbtree-insert
|
||||
test-astar
|
||||
test-base64
|
||||
quicksortapp
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
platform "folkertdev/foo"
|
||||
platform "benchmarks"
|
||||
requires {} { main : Effect {} }
|
||||
exposes []
|
||||
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 {} [] }
|
||||
exposes []
|
||||
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 }
|
||||
exposes []
|
||||
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:
|
||||
|
||||
```bash
|
||||
$ cargo run Hello.roc
|
||||
cargo run helloWorld.roc
|
||||
```
|
||||
|
||||
To run in release mode instead, do:
|
||||
|
||||
```bash
|
||||
$ cargo run --release Hello.roc
|
||||
cargo run --release helloWorld.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
|
||||
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
|
||||
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.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
platform "examples/hello-swift"
|
||||
platform "hello-world-in-c"
|
||||
requires {} { main : Str }
|
||||
exposes []
|
||||
packages {}
|
|
@ -1,5 +1,5 @@
|
|||
app "hello-world"
|
||||
packages { pf: "platform" }
|
||||
app "helloC"
|
||||
packages { pf: "." }
|
||||
imports []
|
||||
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 }
|
||||
exposes []
|
||||
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 }
|
||||
exposes []
|
||||
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")
|
||||
func main() -> UInt8 {
|
||||
print(roc__mainForHost_1_exposed().string)
|
||||
print(roc__mainForHost_1_exposed().string, terminator: "")
|
||||
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!
|
||||
|
||||
To run, go to the project home directory and run:
|
||||
To run this website, first compile either of these identical apps:
|
||||
|
||||
```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.
|
||||
For example with `http-server`:
|
||||
Then `cd` into the website directory
|
||||
and run any web server that can handle WebAssembly.
|
||||
For example, with `http-server`:
|
||||
|
||||
```bash
|
||||
cd examples/hello-web
|
||||
cd examples/hello-world/web-platform
|
||||
npm install -g http-server
|
||||
http-server
|
||||
```
|
||||
|
@ -20,7 +26,7 @@ Now open your browser at http://localhost:8080
|
|||
## 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
|
||||
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
|
||||
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.
|
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.
|
||||
* 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) => {
|
||||
const expected = "Hello, World!";
|
||||
roc_web_platform_run("../helloWeb.wasm", (string_from_roc) => {
|
||||
const expected = "Hello, World!\n";
|
||||
if (string_from_roc !== expected) {
|
||||
console.error(`Expected "${expected}", but got "${string_from_roc}"`);
|
||||
process.exit(1);
|
|
@ -1,10 +1,10 @@
|
|||
<html>
|
||||
<body>
|
||||
<div id="output"></div>
|
||||
<script src="platform/host.js"></script>
|
||||
<script src="./host.js"></script>
|
||||
<script>
|
||||
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;
|
||||
});
|
||||
</script>
|
|
@ -1,4 +1,4 @@
|
|||
platform "examples/hello-world"
|
||||
platform "hello-world-in-zig"
|
||||
requires {} { main : Str }
|
||||
exposes []
|
||||
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;
|
||||
|
||||
// stdout the result
|
||||
stdout.print("{s}\n", .{callresult.asSlice()}) catch unreachable;
|
||||
stdout.print("{s}", .{callresult.asSlice()}) catch unreachable;
|
||||
|
||||
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
|
||||
echo
|
||||
effects
|
||||
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 {} [] }
|
||||
exposes []
|
||||
packages {}
|
|
@ -1,5 +1,5 @@
|
|||
app "countdown"
|
||||
packages { pf: "platform" }
|
||||
packages { pf: "cli-platform" }
|
||||
imports [ pf.Stdin, pf.Stdout, pf.Task.{ await, loop, succeed } ]
|
||||
provides [ main ] to pf
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
app "echo"
|
||||
packages { pf: "platform" }
|
||||
packages { pf: "cli-platform" }
|
||||
imports [ pf.Stdin, pf.Stdout, pf.Task ]
|
||||
provides [ main ] to pf
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
platform "roc-examples/cli"
|
||||
platform "effects"
|
||||
requires {} { main : Effect {} }
|
||||
exposes []
|
||||
packages {}
|
|
@ -1,5 +1,5 @@
|
|||
app "effect-example"
|
||||
packages { pf: "thing/platform-dir" }
|
||||
app "effects"
|
||||
packages { pf: "effects-platform" }
|
||||
imports [ pf.Effect ]
|
||||
provides [ main ] to pf
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
app "form"
|
||||
packages { pf: "platform" }
|
||||
packages { pf: "cli-platform" }
|
||||
imports [ pf.Stdin, pf.Stdout, pf.Task.{ await, Task } ]
|
||||
provides [ main ] to pf
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
platform "folkertdev/foo"
|
||||
platform "tui"
|
||||
requires { Model } { main : Effect {} }
|
||||
exposes []
|
||||
packages {}
|
|
@ -1,5 +1,5 @@
|
|||
app "tui"
|
||||
packages { pf: "platform" }
|
||||
packages { pf: "tui-platform" }
|
||||
imports [ pf.Program.{ Program } ]
|
||||
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:
|
||||
```
|
||||
# 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
|
||||
./roc examples/hello-zig/Hello.roc
|
||||
./roc examples/hello-world/zig-platform/helloZig.roc
|
||||
# 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.
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
3. Run examples with:
|
||||
```
|
||||
# Rust
|
||||
cargo run examples/hello-rust/Hello.roc
|
||||
cargo run examples/hello-world/rust-platform/helloRust.roc
|
||||
# Zig
|
||||
cargo run examples/hello-zig/Hello.roc
|
||||
cargo run examples/hello-world/zig-platform/helloZig.roc
|
||||
# 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.
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ pub trait ReplAppMemory {
|
|||
|
||||
fn deref_dec(&self, addr: usize) -> RocDec {
|
||||
let bits = self.deref_i128(addr);
|
||||
RocDec(bits)
|
||||
RocDec::new(bits)
|
||||
}
|
||||
|
||||
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