mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Separate hello-world platform switching into its own example
This commit is contained in:
parent
6943e742f5
commit
a9d9acb2b8
38 changed files with 213 additions and 82 deletions
|
@ -293,26 +293,25 @@ 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 {
|
||||||
"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;
|
|
||||||
}
|
|
||||||
"form" => {
|
"form" => {
|
||||||
// test is skipped until we upgrate to zig 0.9 / llvm 13
|
// test is skipped until we upgrate to zig 0.9 / llvm 13
|
||||||
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;
|
||||||
}
|
}
|
||||||
"helloSwift" => {
|
"hello-gui" | "breakout" => {
|
||||||
|
// Since these require opening a window, we do `roc build` on them but don't run them.
|
||||||
|
run_roc_on(&file_name, [CMD_BUILD, OPTIMIZE_FLAG], &[], None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
"rocLovesSwift" => {
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"hello-gui" | "breakout" => {
|
"rocLovesWeb" => {
|
||||||
// Since these require opening a window, we do `roc build` on them but don't run them.
|
// this is a web assembly example, but we don't test with JS at the moment
|
||||||
run_roc_on(&file_name, [CMD_BUILD, OPTIMIZE_FLAG], &[], None);
|
eprintln!("WARNING: skipping testing example {} because the test is broken right now!", example.filename);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -385,50 +384,58 @@ mod cli_run {
|
||||||
examples! {
|
examples! {
|
||||||
helloWorld:"hello-world" => Example {
|
helloWorld:"hello-world" => Example {
|
||||||
filename: "main.roc",
|
filename: "main.roc",
|
||||||
executable_filename: "hello",
|
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,
|
||||||
},
|
},
|
||||||
helloC:"hello-world/c-platform" => Example {
|
platformSwitching:"platform-switching" => Example {
|
||||||
filename: "helloC.roc",
|
filename: "main.roc",
|
||||||
executable_filename: "helloC",
|
executable_filename: "rocLovesPlatforms",
|
||||||
stdin: &[],
|
stdin: &[],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
expected_ending:"Hello, World!\n",
|
expected_ending:"Which platform am I running on now?\n",
|
||||||
use_valgrind: true,
|
use_valgrind: true,
|
||||||
},
|
},
|
||||||
helloZig:"hello-world/zig-platform" => Example {
|
platformSwitchingC:"platform-switching/c-platform" => Example {
|
||||||
filename: "helloZig.roc",
|
filename: "main.roc",
|
||||||
executable_filename: "helloZig",
|
executable_filename: "rocLovesC",
|
||||||
stdin: &[],
|
stdin: &[],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
expected_ending:"Hello, World!\n",
|
expected_ending:"Roc <3 C!\n",
|
||||||
use_valgrind: true,
|
use_valgrind: true,
|
||||||
},
|
},
|
||||||
helloRust:"hello-world/rust-platform" => Example {
|
platformSwitchingRust:"platform-switching/rust-platform" => Example {
|
||||||
filename: "helloRust.roc",
|
filename: "main.roc",
|
||||||
executable_filename: "helloRust",
|
executable_filename: "rocLovesRust",
|
||||||
stdin: &[],
|
stdin: &[],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
expected_ending:"Hello, World!\n",
|
expected_ending:"Roc <3 Rust!\n",
|
||||||
use_valgrind: true,
|
use_valgrind: true,
|
||||||
},
|
},
|
||||||
helloSwift:"hello-world/swift-platform" => Example {
|
platformSwitchingSwift:"platform-switching/swift-platform" => Example {
|
||||||
filename: "helloSwift.roc",
|
filename: "main.roc",
|
||||||
executable_filename: "helloSwift",
|
executable_filename: "rocLovesSwift",
|
||||||
stdin: &[],
|
stdin: &[],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
expected_ending:"Hello, World!\n",
|
expected_ending:"Roc <3 Swift!\n",
|
||||||
use_valgrind: true,
|
use_valgrind: true,
|
||||||
},
|
},
|
||||||
helloWeb:"hello-world/web-platform" => Example {
|
platformSwitchingWeb:"platform-switching/web-platform" => Example {
|
||||||
filename: "helloWeb.roc",
|
filename: "main.roc",
|
||||||
executable_filename: "helloWeb",
|
executable_filename: "rocLovesWeb",
|
||||||
stdin: &[],
|
stdin: &[],
|
||||||
input_file: None,
|
input_file: None,
|
||||||
expected_ending:"Hello, World!\n",
|
expected_ending:"Roc <3 Web!\n",
|
||||||
|
use_valgrind: true,
|
||||||
|
},
|
||||||
|
platformSwitchingZig:"platform-switching/zig-platform" => Example {
|
||||||
|
filename: "main.roc",
|
||||||
|
executable_filename: "rocLovesZig",
|
||||||
|
stdin: &[],
|
||||||
|
input_file: None,
|
||||||
|
expected_ending:"Roc <3 Zig!\n",
|
||||||
use_valgrind: true,
|
use_valgrind: true,
|
||||||
},
|
},
|
||||||
fib:"algorithms" => Example {
|
fib:"algorithms" => Example {
|
||||||
|
@ -804,8 +811,8 @@ mod cli_run {
|
||||||
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?)
|
// TODO: Improve this with a more-dynamic approach. (Read all subdirectories?)
|
||||||
// Some hello-world examples live in nested directories
|
// Some platform-switching examples live in nested directories
|
||||||
if example_dir_name == "hello-world" {
|
if example_dir_name == "platform-switching" {
|
||||||
for sub_dir in [
|
for sub_dir in [
|
||||||
"c-platform",
|
"c-platform",
|
||||||
"rust-platform",
|
"rust-platform",
|
||||||
|
|
6
examples/hello-world/.gitignore
vendored
6
examples/hello-world/.gitignore
vendored
|
@ -1,7 +1 @@
|
||||||
helloC
|
|
||||||
helloRust
|
|
||||||
helloSwift
|
|
||||||
helloWorld
|
|
||||||
helloZig
|
|
||||||
hello
|
hello
|
||||||
*.wasm
|
|
||||||
|
|
|
@ -13,6 +13,5 @@ defaults to running a file named `main.roc`. Other `roc` commands (like `roc bui
|
||||||
|
|
||||||
This uses a very simple platform which does nothing more than printing the string you give it.
|
This uses a very simple platform which does nothing more than printing the string you give it.
|
||||||
|
|
||||||
The line `main = "Hello, World!\n"` sets this string to be `"Hello, World!"` with a newline at the end, and the lines `packages { pf: "c-platform/hello.roc" }` and `provides [main] to pf` specify that the `c-platform/` directory contains this app's platform.
|
The line `main = "Hello, World!\n"` sets this string to be `"Hello, World!"` with a newline at the end, and the lines `packages { pf: "platform/main.roc" }` and `provides [main] to pf` specify that the `platform/` directory contains this app's platform.
|
||||||
|
|
||||||
This platform is called `c-platform` because its low-level code is written in C. There's also a `rust-platform`, `zig-platform`, and so on; if you like, you can try switching `"c-platform/main.roc"` to `"zig-platform/main.roc"` or `"rust-platform/main.roc"` to try one of those platforms instead. They all do the same thing, so the application won't look any different, but if you want to start building your own platforms, this Hello World example gives you some very simple platforms to use as starting points too.
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
app "hello"
|
app "hello"
|
||||||
packages { pf: "c-platform/main.roc" }
|
packages { pf: "platform/main.roc" }
|
||||||
imports []
|
imports []
|
||||||
provides [main] to pf
|
provides [main] to pf
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
platform "hello-world-in-c"
|
platform "hello-world"
|
||||||
requires {} { main : Str }
|
requires {} { main : Str }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
|
@ -1,9 +0,0 @@
|
||||||
platform "hello-world-in-web-assembly"
|
|
||||||
requires {} { main : Str }
|
|
||||||
exposes []
|
|
||||||
packages {}
|
|
||||||
imports []
|
|
||||||
provides [mainForHost]
|
|
||||||
|
|
||||||
mainForHost : Str
|
|
||||||
mainForHost = main
|
|
|
@ -1,6 +0,0 @@
|
||||||
app "helloZig"
|
|
||||||
packages { pf: "main.roc" }
|
|
||||||
imports []
|
|
||||||
provides [main] to pf
|
|
||||||
|
|
||||||
main = "Hello, World!\n"
|
|
7
examples/platform-switching/.gitignore
vendored
Normal file
7
examples/platform-switching/.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
rocLovesC
|
||||||
|
rocLovesPlatforms
|
||||||
|
rocLovesRust
|
||||||
|
rocLovesSwift
|
||||||
|
rocLovesWebAssembly
|
||||||
|
rocLovesZig
|
||||||
|
*.wasm
|
20
examples/platform-switching/README.md
Normal file
20
examples/platform-switching/README.md
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# Platform switching
|
||||||
|
|
||||||
|
To run, `cd` into this directory and run this in your terminal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
roc run
|
||||||
|
```
|
||||||
|
|
||||||
|
This will run `main.roc` because, unless you explicitly give it a filename, `roc run`
|
||||||
|
defaults to running a file named `main.roc`. Other `roc` commands (like `roc build`, `roc test`, and so on) also default to `main.roc` unless you explicitly give them a filename.
|
||||||
|
|
||||||
|
# About this example
|
||||||
|
|
||||||
|
This uses a very simple platform which does nothing more than printing the string you give it.
|
||||||
|
|
||||||
|
The line `main = "Which platform am I running on now?\n"` sets this string to be `"Which platform am I running on now?"` with a newline at the end, and the lines `packages { pf: "c-platform/main.roc" }` and `provides [main] to pf` specify that the `c-platform/` directory contains this app's platform.
|
||||||
|
|
||||||
|
This platform is called `c-platform` because its lower-level code is written in C. There's also a `rust-platform`, `zig-platform`, and so on; if you like, you can try switching `pf: "c-platform/main.roc"` to `pf: "zig-platform/main.roc"` or `pf: "rust-platform/main.roc"` to try one of those platforms instead. They all do similar things, so the application won't look any different.
|
||||||
|
|
||||||
|
If you want to start building your own platforms, these are some very simple example platforms to use as starting points.
|
84
examples/platform-switching/c-platform/host.c
Normal file
84
examples/platform-switching/c-platform/host.c
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void* roc_alloc(size_t size, unsigned int alignment) { return malloc(size); }
|
||||||
|
|
||||||
|
void* roc_realloc(void* ptr, size_t new_size, size_t old_size,
|
||||||
|
unsigned int alignment) {
|
||||||
|
return realloc(ptr, new_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void roc_dealloc(void* ptr, unsigned int alignment) { free(ptr); }
|
||||||
|
|
||||||
|
void roc_panic(void* ptr, unsigned int alignment) {
|
||||||
|
char* msg = (char*)ptr;
|
||||||
|
fprintf(stderr,
|
||||||
|
"Application crashed with message\n\n %s\n\nShutting down\n", msg);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* roc_memcpy(void* dest, const void* src, size_t n) {
|
||||||
|
return memcpy(dest, src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* roc_memset(void* str, int c, size_t n) { return memset(str, c, n); }
|
||||||
|
|
||||||
|
struct RocStr {
|
||||||
|
char* bytes;
|
||||||
|
size_t len;
|
||||||
|
size_t capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool is_small_str(struct RocStr str) { return ((ssize_t)str.capacity) < 0; }
|
||||||
|
|
||||||
|
// Determine the length of the string, taking into
|
||||||
|
// account the small string optimization
|
||||||
|
size_t roc_str_len(struct RocStr str) {
|
||||||
|
char* bytes = (char*)&str;
|
||||||
|
char last_byte = bytes[sizeof(str) - 1];
|
||||||
|
char last_byte_xored = last_byte ^ 0b10000000;
|
||||||
|
size_t small_len = (size_t)(last_byte_xored);
|
||||||
|
size_t big_len = str.len;
|
||||||
|
|
||||||
|
// Avoid branch misprediction costs by always
|
||||||
|
// determining both small_len and big_len,
|
||||||
|
// so this compiles to a cmov instruction.
|
||||||
|
if (is_small_str(str)) {
|
||||||
|
return small_len;
|
||||||
|
} else {
|
||||||
|
return big_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void roc__mainForHost_1_exposed_generic(struct RocStr *string);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
struct RocStr str;
|
||||||
|
roc__mainForHost_1_exposed_generic(&str);
|
||||||
|
|
||||||
|
// Determine str_len and the str_bytes pointer,
|
||||||
|
// taking into account the small string optimization.
|
||||||
|
size_t str_len = roc_str_len(str);
|
||||||
|
char* str_bytes;
|
||||||
|
|
||||||
|
if (is_small_str(str)) {
|
||||||
|
str_bytes = (char*)&str;
|
||||||
|
} else {
|
||||||
|
str_bytes = str.bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to stdout
|
||||||
|
if (write(1, str_bytes, str_len) >= 0) {
|
||||||
|
// Writing succeeded!
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
printf("Error writing to stdout: %s\n", strerror(errno));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
platform "hello-world-in-zig"
|
platform "echo-in-c"
|
||||||
requires {} { main : Str }
|
requires {} { main : Str }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
|
@ -1,6 +1,6 @@
|
||||||
app "helloC"
|
app "rocLovesC"
|
||||||
packages { pf: "main.roc" }
|
packages { pf: "main.roc" }
|
||||||
imports []
|
imports []
|
||||||
provides [main] to pf
|
provides [main] to pf
|
||||||
|
|
||||||
main = "Hello, World!\n"
|
main = "Roc <3 C!\n"
|
11
examples/platform-switching/main.roc
Normal file
11
examples/platform-switching/main.roc
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
app "rocLovesPlatforms"
|
||||||
|
packages { pf: "c-platform/main.roc" }
|
||||||
|
# To switch platforms, comment-out the line above and un-comment one below.
|
||||||
|
# packages { pf: "rust-platform/main.roc" }
|
||||||
|
# packages { pf: "swift-platform/main.roc" }
|
||||||
|
# packages { pf: "web-platform/main.roc" } # See ./web-platform/README.md
|
||||||
|
# packages { pf: "zig-platform/main.roc" }
|
||||||
|
imports []
|
||||||
|
provides [main] to pf
|
||||||
|
|
||||||
|
main = "Which platform am I running on now?\n"
|
|
@ -1,4 +1,4 @@
|
||||||
platform "hello-world-in-rust"
|
platform "echo-in-rust"
|
||||||
requires {} { main : Str }
|
requires {} { main : Str }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
|
@ -1,6 +1,6 @@
|
||||||
app "helloSwift"
|
app "rocLovesRust"
|
||||||
packages { pf: "main.roc" }
|
packages { pf: "main.roc" }
|
||||||
imports []
|
imports []
|
||||||
provides [main] to pf
|
provides [main] to pf
|
||||||
|
|
||||||
main = "Hello, World!\n"
|
main = "Roc <3 Rust!\n"
|
|
@ -1,4 +1,4 @@
|
||||||
platform "hello-world-in-swift"
|
platform "echo-in-swift"
|
||||||
requires {} { main : Str }
|
requires {} { main : Str }
|
||||||
exposes []
|
exposes []
|
||||||
packages {}
|
packages {}
|
|
@ -0,0 +1,6 @@
|
||||||
|
app "rocLovesSwift"
|
||||||
|
packages { pf: "main.roc" }
|
||||||
|
imports []
|
||||||
|
provides [main] to pf
|
||||||
|
|
||||||
|
main = "Roc <3 Swift!\n"
|
|
@ -3,12 +3,12 @@
|
||||||
To run this website, first compile either of these identical apps:
|
To run this website, first compile either of these identical apps:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Option A: Compile helloWeb.roc
|
# Option A: Compile examples/platform-switching/web-assembly-platform/rocLovesWeb.roc
|
||||||
cargo run -- build --target=wasm32 examples/hello-world/web-platform/helloWeb.roc
|
cargo run -- build --target=wasm32 examples/platform-switching/web-assembly-platform/rocLovesWeb.roc
|
||||||
|
|
||||||
# Option B: Compile helloWorld.roc with `pf: "web-platform"` and move the result
|
# Option B: Compile examples/platform-switching/main.roc with `pf: "web-assembly-platform/main.roc"` and move the result
|
||||||
cargo run -- build --target=wasm32 examples/hello-world/main.roc
|
cargo run -- build --target=wasm32 examples/platform-switching/main.roc
|
||||||
(cd examples/hello-world && mv helloWorld.wasm web-platform/helloWeb.wasm)
|
(cd examples/platform-switching && mv rocLovesPlatforms.wasm web-assembly-platform/rocLovesWeb.wasm)
|
||||||
```
|
```
|
||||||
|
|
||||||
Then `cd` into the website directory
|
Then `cd` into the website directory
|
||||||
|
@ -16,7 +16,7 @@ and run any web server that can handle WebAssembly.
|
||||||
For example, with `http-server`:
|
For example, with `http-server`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd examples/hello-world/web-platform
|
cd examples/platform-switching/web-assembly-platform
|
||||||
npm install -g http-server
|
npm install -g http-server
|
||||||
http-server
|
http-server
|
||||||
```
|
```
|
9
examples/platform-switching/web-platform/main.roc
Normal file
9
examples/platform-switching/web-platform/main.roc
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
platform "echo-in-web"
|
||||||
|
requires {} { main : Str }
|
||||||
|
exposes []
|
||||||
|
packages {}
|
||||||
|
imports []
|
||||||
|
provides [mainForHost]
|
||||||
|
|
||||||
|
mainForHost : Str
|
||||||
|
mainForHost = main
|
|
@ -1,6 +1,6 @@
|
||||||
app "helloWeb"
|
app "rocLovesWeb"
|
||||||
packages { pf: "main.roc" }
|
packages { pf: "main.roc" }
|
||||||
imports []
|
imports []
|
||||||
provides [main] to pf
|
provides [main] to pf
|
||||||
|
|
||||||
main = "Hello, World!\n"
|
main = "Roc <3 Web!\n"
|
9
examples/platform-switching/zig-platform/main.roc
Normal file
9
examples/platform-switching/zig-platform/main.roc
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
platform "echo-in-zig"
|
||||||
|
requires {} { main : Str }
|
||||||
|
exposes []
|
||||||
|
packages {}
|
||||||
|
imports []
|
||||||
|
provides [mainForHost]
|
||||||
|
|
||||||
|
mainForHost : Str
|
||||||
|
mainForHost = main
|
|
@ -1,6 +1,6 @@
|
||||||
app "helloRust"
|
app "rocLovesZig"
|
||||||
packages { pf: "main.roc" }
|
packages { pf: "main.roc" }
|
||||||
imports []
|
imports []
|
||||||
provides [main] to pf
|
provides [main] to pf
|
||||||
|
|
||||||
main = "Hello, World!\n"
|
main = "Roc <3 Zig!\n"
|
|
@ -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-world/rust-platform/helloRust.roc
|
./roc examples/platform-switching/rust-platform/rocLovesRust.roc
|
||||||
# Zig
|
# Zig
|
||||||
./roc examples/hello-world/zig-platform/helloZig.roc --linker=legacy
|
./roc examples/platform-switching/zig-platform/rocLovesZig.roc --linker=legacy
|
||||||
# C
|
# C
|
||||||
./roc examples/hello-world/c-platform/helloC.roc --linker=legacy
|
./roc examples/platform-switching/c-platform/rocLovesC.roc --linker=legacy
|
||||||
```
|
```
|
||||||
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-world/rust-platform/helloRust.roc
|
cargo run examples/platform-switching/rust-platform/rocLovesRust.roc
|
||||||
# Zig
|
# Zig
|
||||||
cargo run examples/hello-world/zig-platform/helloZig.roc
|
cargo run examples/platform-switching/zig-platform/rocLovesZig.roc
|
||||||
# C
|
# C
|
||||||
cargo run examples/hello-world/c-platform/helloC.roc
|
cargo run examples/platform-switching/c-platform/rocLovesC.roc
|
||||||
```
|
```
|
||||||
4. See [here](../README.md#examples) for the other examples.
|
4. See [here](../README.md#examples) for the other examples.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue