Skip to content

Commit

Permalink
Merge branch 'roc-lang:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
dadhi authored Oct 22, 2024
2 parents 0d683ca + ff83fd6 commit 8bc83a8
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 15 deletions.
41 changes: 33 additions & 8 deletions crates/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,15 @@ pub fn build(
// ManuallyDrop will leak the bytes because we don't drop manually
let bytes = &ManuallyDrop::new(std::fs::read(&binary_path).unwrap());

roc_run(&arena, opt_level, target, args, bytes, expect_metadata)
roc_run(
&arena,
path,
opt_level,
target,
args,
bytes,
expect_metadata,
)
}
BuildAndRunIfNoErrors => {
if problems.fatally_errored {
Expand Down Expand Up @@ -1021,7 +1029,15 @@ pub fn build(
// ManuallyDrop will leak the bytes because we don't drop manually
let bytes = &ManuallyDrop::new(std::fs::read(&binary_path).unwrap());

roc_run(&arena, opt_level, target, args, bytes, expect_metadata)
roc_run(
&arena,
path,
opt_level,
target,
args,
bytes,
expect_metadata,
)
}
}
}
Expand All @@ -1034,6 +1050,7 @@ pub fn build(

fn roc_run<'a, I: IntoIterator<Item = &'a OsStr>>(
arena: &Bump,
script_path: &Path,
opt_level: OptLevel,
target: Target,
args: I,
Expand Down Expand Up @@ -1073,7 +1090,14 @@ fn roc_run<'a, I: IntoIterator<Item = &'a OsStr>>(

Ok(0)
}
_ => roc_run_native(arena, opt_level, args, binary_bytes, expect_metadata),
_ => roc_run_native(
arena,
script_path,
opt_level,
args,
binary_bytes,
expect_metadata,
),
}
}

Expand All @@ -1090,16 +1114,15 @@ fn os_str_as_utf8_bytes(os_str: &OsStr) -> &[u8] {

fn make_argv_envp<'a, I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
arena: &'a Bump,
executable: &ExecutableFile,
script_path: &Path,
args: I,
) -> (
bumpalo::collections::Vec<'a, CString>,
bumpalo::collections::Vec<'a, CString>,
) {
use bumpalo::collections::CollectIn;

let path = executable.as_path();
let path_cstring = CString::new(os_str_as_utf8_bytes(path.as_os_str())).unwrap();
let path_cstring = CString::new(os_str_as_utf8_bytes(script_path.as_os_str())).unwrap();

// argv is an array of pointers to strings passed to the new program
// as its command-line arguments. By convention, the first of these
Expand Down Expand Up @@ -1137,6 +1160,7 @@ fn make_argv_envp<'a, I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
#[cfg(target_family = "unix")]
fn roc_run_native<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
arena: &Bump,
script_path: &Path,
opt_level: OptLevel,
args: I,
binary_bytes: &[u8],
Expand All @@ -1145,7 +1169,7 @@ fn roc_run_native<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
use bumpalo::collections::CollectIn;

let executable = roc_run_executable_file_path(binary_bytes)?;
let (argv_cstrings, envp_cstrings) = make_argv_envp(arena, &executable, args);
let (argv_cstrings, envp_cstrings) = make_argv_envp(arena, script_path, args);

let argv: bumpalo::collections::Vec<*const c_char> = argv_cstrings
.iter()
Expand Down Expand Up @@ -1400,6 +1424,7 @@ fn roc_run_executable_file_path(binary_bytes: &[u8]) -> std::io::Result<Executab
#[cfg(not(target_family = "unix"))]
fn roc_run_native<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
arena: &Bump, // This should be passed an owned value, not a reference, so we can usefully mem::forget it!
script_path: &Path,
opt_level: OptLevel,
args: I,
binary_bytes: &[u8],
Expand All @@ -1411,7 +1436,7 @@ fn roc_run_native<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
let executable = roc_run_executable_file_path(binary_bytes)?;

// TODO forward the arguments
let (argv_cstrings, envp_cstrings) = make_argv_envp(&arena, &executable, args);
let (argv_cstrings, envp_cstrings) = make_argv_envp(&arena, script_path, args);

let argv: bumpalo::collections::Vec<*const c_char> = argv_cstrings
.iter()
Expand Down
12 changes: 12 additions & 0 deletions crates/cli/tests/cli/argv0.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
app [main] {
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br",
}

import pf.Stdout
import pf.Arg

main =
args = Arg.list! {}
when List.first args is
Ok argv0 -> Stdout.line argv0
Err ListWasEmpty -> Stdout.line "Failed: argv was empty"
31 changes: 24 additions & 7 deletions crates/cli/tests/cli_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ mod cli_run {
}
};

let self_path = file.display().to_string();
let self_path = file.parent().unwrap().display().to_string();

let actual_cmd_stdout = ignore_test_timings(&strip_colors(&cmd_output.stdout))
.replace(&self_path, "<ignored for tests>");
Expand Down Expand Up @@ -573,12 +573,12 @@ mod cli_run {
words : List Str
words = ["this", "will", "for", "sure", "be", "a", "large", "string", "so", "when", "we", "split", "it", "it", "will", "use", "seamless", "slices", "which", "affect", "printing"]
[<ignored for tests>:31] x = 42
[<ignored for tests>:33] "Fjoer en ferdjer frieten oan dyn geve lea" = "Fjoer en ferdjer frieten oan dyn geve lea"
[<ignored for tests>:35] "this is line 24" = "this is line 24"
[<ignored for tests>:21] x = "abc"
[<ignored for tests>:21] x = 10
[<ignored for tests>:21] x = (A (B C))
[<ignored for tests>/expects.roc:31] x = 42
[<ignored for tests>/expects.roc:33] "Fjoer en ferdjer frieten oan dyn geve lea" = "Fjoer en ferdjer frieten oan dyn geve lea"
[<ignored for tests>/expects.roc:35] "this is line 24" = "this is line 24"
[<ignored for tests>/expects.roc:21] x = "abc"
[<ignored for tests>/expects.roc:21] x = 10
[<ignored for tests>/expects.roc:21] x = (A (B C))
Program finished!
"#
),
Expand Down Expand Up @@ -1203,6 +1203,23 @@ mod cli_run {
)
}

#[test]
#[serial(cli_platform)]
#[cfg_attr(windows, ignore)]
#[ignore = "broken because of a bug in basic-cli: https://github.com/roc-lang/basic-cli/issues/82"]
fn argv0() {
test_roc_app(
"crates/cli/tests/cli",
"argv0.roc",
&[],
&[],
&[],
"<ignored for tests>/argv0.roc\n",
UseValgrind::No,
TestCliCommands::Run,
)
}

#[test]
#[serial(cli_platform)]
#[cfg_attr(windows, ignore)]
Expand Down
33 changes: 33 additions & 0 deletions crates/glue/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Glue

Glue is a bit of tooling built into Roc to help with platform development. Roc platforms are written in a different language than Roc, and some it requires some finesse to let other languages to read and write Roc types like records and unions in a way compatible with how Roc uses those types.

The `roc glue` command generates code in other languages for interacting with the Roc types used by your platform. It takes three arguments:

1. A 'glue spec', this is a Roc file specifying how to output type helpers fora particular language. You can find some examples in the src/ subdirectory:

- **RustGlue.roc:** Generates Roc bindings for rust platforms.
- **ZigGlue.roc:** Generates Roc bindings for zig platforms (out of date).
- **DescribeGlue.roc:** Does not generate Roc bindings, but outputs some information about the types that assist writing compatible types in other languages by hand.

2. A 'glue dir', specifying where glue should place generated files. Pass any directory you want here.

3. A .roc file exposing some types that glue should generate code for. You can extend the template below.


```roc
platform "glue-types"
requires {} { main : _ }
exposes []
packages {}
imports []
provides [mainForHost]
GlueTypes : {
a : SomeType,
b : AnotherType,
}
mainForHost : GlueTypes
mainForHost = main
```
13 changes: 13 additions & 0 deletions crates/glue/src/DescribeGlue.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
app [makeGlue] { pf: platform "../platform/main.roc" }

import pf.Types exposing [Types]
import pf.File exposing [File]

makeGlue : List Types -> Result (List File) Str
makeGlue = \types ->
Ok [
{
name: "types.txt",
content: List.map types Inspect.toStr |> Str.joinWith "\n",
},
]

0 comments on commit 8bc83a8

Please sign in to comment.