diff --git a/examples/balance/Main.roc b/examples/balance/Main.roc new file mode 100644 index 0000000000..bb87fb29b2 --- /dev/null +++ b/examples/balance/Main.roc @@ -0,0 +1,7 @@ +app Main provides [ rocMain ] imports [ Effect ] + +rocMain : Effect.Effect {} as Fx +rocMain = + when List.len (Str.split "hello" "JJJJ there") is + _ -> Effect.putLine "Yay" + diff --git a/examples/balance/platform/Cargo.lock b/examples/balance/platform/Cargo.lock new file mode 100644 index 0000000000..c386bb6c4a --- /dev/null +++ b/examples/balance/platform/Cargo.lock @@ -0,0 +1,23 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "host" +version = "0.1.0" +dependencies = [ + "roc_std 0.1.0", +] + +[[package]] +name = "libc" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "roc_std" +version = "0.1.0" +dependencies = [ + "libc 0.2.79 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum libc 0.2.79 (registry+https://github.com/rust-lang/crates.io-index)" = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743" diff --git a/examples/balance/platform/Cargo.toml b/examples/balance/platform/Cargo.toml new file mode 100644 index 0000000000..70f3c1f86c --- /dev/null +++ b/examples/balance/platform/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "host" +version = "0.1.0" +authors = ["Richard Feldman "] +edition = "2018" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +roc_std = { path = "../../../roc_std" } + +[workspace] diff --git a/examples/balance/platform/Pkg-Config.roc b/examples/balance/platform/Pkg-Config.roc new file mode 100644 index 0000000000..a463e3bbb9 --- /dev/null +++ b/examples/balance/platform/Pkg-Config.roc @@ -0,0 +1,13 @@ +platform folkertdev/foo + provides [ mainForHost ] + requires { main : Effect {} } + imports [] + effects Effect + { + putChar : Int -> Effect {}, + putLine : Str -> Effect {}, + getLine : Effect Str + } + +mainForHost : Effect {} as Fx +mainForHost = main diff --git a/examples/balance/platform/host.c b/examples/balance/platform/host.c new file mode 100644 index 0000000000..0378c69589 --- /dev/null +++ b/examples/balance/platform/host.c @@ -0,0 +1,7 @@ +#include + +extern int rust_main(); + +int main() { + return rust_main(); +} diff --git a/examples/balance/platform/src/lib.rs b/examples/balance/platform/src/lib.rs new file mode 100644 index 0000000000..61957ea485 --- /dev/null +++ b/examples/balance/platform/src/lib.rs @@ -0,0 +1,118 @@ +#![allow(non_snake_case)] + +use roc_std::alloca; +use roc_std::RocCallResult; +use roc_std::RocStr; +use std::alloc::Layout; +use std::time::SystemTime; + +extern "C" { + #[link_name = "Main_rocMain_1_exposed"] + fn roc_main(output: *mut u8) -> (); + + #[link_name = "Main_rocMain_1_size"] + fn roc_main_size() -> i64; + + #[link_name = "Main_rocMain_1_Fx_caller"] + fn call_Fx(function_pointer: *const u8, closure_data: *const u8, output: *mut u8) -> (); + + #[link_name = "Main_rocMain_1_Fx_size"] + fn size_Fx() -> i64; +} + +#[no_mangle] +pub fn roc_fx_putChar(foo: i64) -> () { + let character = foo as u8 as char; + print!("{}", character); + + () +} + +#[no_mangle] +pub fn roc_fx_putLine(line: RocStr) -> () { + let bytes = line.as_slice(); + let string = unsafe { std::str::from_utf8_unchecked(bytes) }; + println!("{}", string); + + () +} + +#[no_mangle] +pub fn roc_fx_getLine() -> RocStr { + use std::io::{self, BufRead}; + + let stdin = io::stdin(); + let line1 = stdin.lock().lines().next().unwrap().unwrap(); + + RocStr::from_slice_with_capacity(line1.as_bytes(), line1.len()) +} + +unsafe fn call_the_closure(function_pointer: *const u8, closure_data_ptr: *const u8) -> i64 { + let size = size_Fx() as usize; + + alloca::with_stack_bytes(size, |buffer| { + let buffer: *mut std::ffi::c_void = buffer; + let buffer: *mut u8 = buffer as *mut u8; + + call_Fx( + function_pointer, + closure_data_ptr as *const u8, + buffer as *mut u8, + ); + + let output = &*(buffer as *mut RocCallResult); + + // match output.into() { + // Ok(v) => v, + // Err(e) => panic!("failed with {}", e), + // } + 32 + }) +} + +#[no_mangle] +pub fn rust_main() -> isize { + println!("Running Roc closure"); + let start_time = SystemTime::now(); + + let size = unsafe { roc_main_size() } as usize; + let layout = Layout::array::(size).unwrap(); + let answer = unsafe { + let buffer = std::alloc::alloc(layout); + + roc_main(buffer); + + let output = &*(buffer as *mut RocCallResult<()>); + + match output.into() { + Ok(()) => { + let function_pointer = { + // this is a pointer to the location where the function pointer is stored + // we pass just the function pointer + let temp = buffer.offset(8) as *const i64; + + (*temp) as *const u8 + }; + + let closure_data_ptr = buffer.offset(16); + + call_the_closure(function_pointer as *const u8, closure_data_ptr as *const u8) + } + Err(msg) => { + std::alloc::dealloc(buffer, layout); + + panic!("Roc failed with message: {}", msg); + } + } + }; + let end_time = SystemTime::now(); + let duration = end_time.duration_since(start_time).unwrap(); + + println!( + "Roc execution took {:.4} ms", + duration.as_secs_f64() * 1000.0, + ); + + // Exit code + 0 +}