Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RustGlue.roc improvements #5684

Merged
merged 2 commits into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions crates/compiler/builtins/roc/List.roc
Original file line number Diff line number Diff line change
Expand Up @@ -1182,8 +1182,17 @@ mapTry = \list, toResult ->
Result.map (toResult elem) \ok ->
List.append state ok

## This is the same as `iterate` but with [Result] instead of `[Continue, Break]`.
## Using `Result` saves a conditional in `mapTry`.
## Same as [List.walk], except you can stop walking early by returning `Err`.
##
## ## Performance Details
##
## Compared to [List.walk], this can potentially visit fewer elements (which can
## improve performance) at the cost of making each step take longer.
## However, the added cost to each step is extremely small, and can easily
## be outweighed if it results in skipping even a small number of elements.
##
## As such, it is typically better for performance to use this over [List.walk]
## if returning `Break` earlier than the last element is expected to be common.
walkTry : List elem, state, (state, elem -> Result state err) -> Result state err
walkTry = \list, init, func ->
walkTryHelp list init func 0 (List.len list)
Expand Down
110 changes: 72 additions & 38 deletions crates/glue/src/RustGlue.roc
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,11 @@ generateEntryPoint = \buf, types, name, id ->
when Types.shape types id is
Function rocFn ->
arguments =
rocFn.args
|> List.mapWithIndex \argId, i ->
toArgStr rocFn.args types \argId, _shape, index ->
type = typeName types argId
c = Num.toStr i
"arg\(c): \(type)"
|> Str.joinWith ", "
indexStr = Num.toStr index

"arg\(indexStr): \(type)"

ret = typeName types rocFn.ret

Expand All @@ -154,16 +153,13 @@ generateEntryPoint = \buf, types, name, id ->
when Types.shape types id is
Function rocFn ->
arguments =
rocFn.args
|> List.map \argId ->
shape = Types.shape types argId
toArgStr rocFn.args types \argId, shape, _index ->
type = typeName types argId

if canDeriveCopy types shape then
"_: \(type)"
else
"_: &mut core::mem::ManuallyDrop<\(type)>"
|> Str.joinWith ", "

ret = typeName types rocFn.ret
"(_: *mut \(ret), \(arguments))"
Expand All @@ -175,16 +171,13 @@ generateEntryPoint = \buf, types, name, id ->
externArguments =
when Types.shape types id is
Function rocFn ->
rocFn.args
|> List.mapWithIndex \argId, index ->
toArgStr rocFn.args types \_argId, shape, index ->
indexStr = Num.toStr index
shape = Types.shape types argId

if canDeriveCopy types shape then
"arg\(indexStr)"
else
"&mut core::mem::ManuallyDrop::new(arg\(indexStr))"
|> Str.joinWith ", "

_ ->
""
Expand Down Expand Up @@ -215,29 +208,40 @@ generateFunction = \buf, types, rocFn ->
lambdaSet = typeName types rocFn.lambdaSet

publicArguments =
rocFn.args
|> List.mapWithIndex \argId, i ->
toArgStr rocFn.args types \argId, _shape, index ->
type = typeName types argId
c = Num.toStr i
"arg\(c): \(type)"
|> Str.joinWith ", "
indexStr = Num.toStr index

"arg\(indexStr): \(type)"

externDefArguments =
rocFn.args
|> List.mapWithIndex \argId, i ->
type = typeName types argId
c = Num.toStr i
"arg\(c): *const \(type)"
|> Str.joinWith ", "
withoutUnit =
toArgStr rocFn.args types \argId, _shape, index ->
type = typeName types argId
indexStr = Num.toStr index

"arg\(indexStr): *const \(type)"

if Str.isEmpty withoutUnit then
# These always have a first argument that's a pointer, even if it's to nothing.
"arg0: *const ()"
else
withoutUnit

externCallArguments =
rocFn.args
|> List.mapWithIndex \_, i ->
c = Num.toStr i
"&arg\(c)"
|> Str.joinWith ", "
withoutUnit =
toArgStr rocFn.args types \_argId, _shape, index ->
indexStr = Num.toStr index

"&arg\(indexStr)"

externComma = if Str.isEmpty publicArguments then "" else ", "
if Str.isEmpty withoutUnit then
# These always have a first argument that's a pointer, even if it's to nothing.
"&()"
else
withoutUnit

publicComma = if Str.isEmpty publicArguments then "" else ", "

ret = typeName types rocFn.ret

Expand All @@ -251,20 +255,20 @@ generateFunction = \buf, types, rocFn ->
}

impl \(name) {
pub fn force_thunk(mut self, \(publicArguments)) -> \(ret) {
pub fn force_thunk(self\(publicComma)\(publicArguments)) -> \(ret) {
extern "C" {
fn \(externName)(\(externDefArguments)\(externComma) closure_data: *mut u8, output: *mut \(ret));
fn \(externName)(\(externDefArguments), closure_data: *mut u8, output: *mut \(ret));
}

let mut output = core::mem::MaybeUninit::uninit();
let ptr = &mut self.closure_data as *mut _ as *mut u8;
let closure_ptr =
(&mut core::mem::ManuallyDrop::new(self.closure_data)) as *mut _ as *mut u8;

unsafe { \(externName)(\(externCallArguments)\(externComma) ptr, output.as_mut_ptr(), ) };

// ownership of the closure is transferred back to roc
core::mem::forget(self.closure_data);
unsafe {
\(externName)(\(externCallArguments), closure_ptr, output.as_mut_ptr());

unsafe { output.assume_init() }
output.assume_init()
}
}
}
"""
Expand Down Expand Up @@ -2065,3 +2069,33 @@ nextMultipleOf = \lhs, rhs ->
when lhs % rhs is
0 -> lhs
r -> lhs + (rhs - r)


isUnit : Shape -> Bool
isUnit = \shape ->
when shape is
Unit -> Bool.true
_ -> Bool.false

toArgStr : List TypeId, Types, (TypeId, Shape, Nat -> Str) -> Str
toArgStr = \args, types, fmt ->
answer = List.walk args { state: "", index: 0 } \{ state, index }, argId ->
newState =
shape = Types.shape types argId

# Drop `()` args; they aren't FFI-safe, and nothing will get passed anyway.
if isUnit shape then
state
else
argStr = fmt argId shape index

if Str.isEmpty state then
argStr # Don't prepend a comma if this is the first one
else
state
|> Str.concat ", "
|> Str.concat argStr

{ state: newState, index: index + 1 }

answer.state
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub extern "C" fn rust_main() -> i32 {
use std::cmp::Ordering;
use std::collections::hash_set::HashSet;

let tag_union = roc_app::mainForHost(());
let tag_union = roc_app::mainForHost();

// Verify that it has all the expected traits.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub extern "C" fn rust_main() -> i32 {
use std::cmp::Ordering;
use std::collections::hash_set::HashSet;

let tag_union = roc_app::mainForHost(());
let tag_union = roc_app::mainForHost();

// Verify that it has all the expected traits.

Expand Down
2 changes: 1 addition & 1 deletion crates/glue/tests/fixtures/nullable-wrapped/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub extern "C" fn rust_main() -> i32 {
use std::cmp::Ordering;
use std::collections::hash_set::HashSet;

let tag_union = roc_app::mainForHost(());
let tag_union = roc_app::mainForHost();

// Eq
assert!(StrFingerTree::Empty() == StrFingerTree::Empty());
Expand Down
2 changes: 1 addition & 1 deletion crates/glue/tests/fixtures/union-with-padding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub extern "C" fn rust_main() -> i32 {
use std::cmp::Ordering;
use std::collections::hash_set::HashSet;

let tag_union = roc_app::mainForHost(());
let tag_union = roc_app::mainForHost();

// Verify that it has all the expected traits.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub extern "C" fn rust_main() -> i32 {
use std::cmp::Ordering;
use std::collections::hash_set::HashSet;

let tag_union = roc_app::mainForHost(());
let tag_union = roc_app::mainForHost();

// Verify that it has all the expected traits.

Expand Down
Loading