From c04c3e551a19cb34ba909d25cbf420182b18c857 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sat, 12 Dec 2020 22:00:56 +0100 Subject: [PATCH] init! --- examples/tea/Main.roc | 7 + examples/tea/platform/Cargo.lock | 21 +++ examples/tea/platform/Cargo.toml | 13 ++ examples/tea/platform/Cmd.roc | 16 +++ examples/tea/platform/Pkg-Config.roc | 19 +++ examples/tea/platform/host.c | 7 + examples/tea/platform/src/lib.rs | 193 +++++++++++++++++++++++++++ 7 files changed, 276 insertions(+) create mode 100644 examples/tea/Main.roc create mode 100644 examples/tea/platform/Cargo.lock create mode 100644 examples/tea/platform/Cargo.toml create mode 100644 examples/tea/platform/Cmd.roc create mode 100644 examples/tea/platform/Pkg-Config.roc create mode 100644 examples/tea/platform/host.c create mode 100644 examples/tea/platform/src/lib.rs diff --git a/examples/tea/Main.roc b/examples/tea/Main.roc new file mode 100644 index 0000000000..6a02b55825 --- /dev/null +++ b/examples/tea/Main.roc @@ -0,0 +1,7 @@ +app "effect-example" + packages { base: "platform" } + imports [base.Cmd] + provides [ main ] to base + +main : I64 +main = 42 diff --git a/examples/tea/platform/Cargo.lock b/examples/tea/platform/Cargo.lock new file mode 100644 index 0000000000..331efb48b9 --- /dev/null +++ b/examples/tea/platform/Cargo.lock @@ -0,0 +1,21 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "host" +version = "0.1.0" +dependencies = [ + "roc_std", +] + +[[package]] +name = "libc" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" + +[[package]] +name = "roc_std" +version = "0.1.0" +dependencies = [ + "libc", +] diff --git a/examples/tea/platform/Cargo.toml b/examples/tea/platform/Cargo.toml new file mode 100644 index 0000000000..70f3c1f86c --- /dev/null +++ b/examples/tea/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/tea/platform/Cmd.roc b/examples/tea/platform/Cmd.roc new file mode 100644 index 0000000000..07c6158cfc --- /dev/null +++ b/examples/tea/platform/Cmd.roc @@ -0,0 +1,16 @@ +interface Cmd + exposes [ Cmd, none, map, putLine ] + imports [ Effect ] + +Cmd a : Effect.Effect a + +none : Cmd {} +none = Effect.always {} + +# getLine = Effect.after Effect.getLine always + +putLine : Str -> Cmd {} +putLine = \line -> Effect.putLine line + +map : Cmd a, (a -> b) -> Cmd b +map = \cmd, transform -> Effect.map cmd transform diff --git a/examples/tea/platform/Pkg-Config.roc b/examples/tea/platform/Pkg-Config.roc new file mode 100644 index 0000000000..0ccf2493a6 --- /dev/null +++ b/examples/tea/platform/Pkg-Config.roc @@ -0,0 +1,19 @@ +platform folkertdev/foo + requires { main : Effect {} } + exposes [] + packages {} + imports [Cmd] + provides [ mainForHost ] + effects Effect + { + putChar : I64 -> Effect {}, + putLine : Str -> Effect {}, + getLine : Effect Str + } + + +mainForHost : {init : ({} -> I64) as Init } +mainForHost = + { init : \{} -> 42 } + + diff --git a/examples/tea/platform/host.c b/examples/tea/platform/host.c new file mode 100644 index 0000000000..0378c69589 --- /dev/null +++ b/examples/tea/platform/host.c @@ -0,0 +1,7 @@ +#include + +extern int rust_main(); + +int main() { + return rust_main(); +} diff --git a/examples/tea/platform/src/lib.rs b/examples/tea/platform/src/lib.rs new file mode 100644 index 0000000000..5ad83af045 --- /dev/null +++ b/examples/tea/platform/src/lib.rs @@ -0,0 +1,193 @@ +#![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 = "roc__mainForHost_1_exposed"] + fn roc_main(output: *mut u8) -> (); + + #[link_name = "roc__mainForHost_1_size"] + fn roc_main_size() -> i64; + + #[link_name = "roc__mainForHost_1_Init_caller"] + fn call_Init(function_pointer: *const u8, closure_data: *const u8, output: *mut u8) -> (); + + #[link_name = "roc__mainForHost_1_Init_size"] + fn size_Init() -> i64; + + #[link_name = "roc__mainForHost_1_Model_size"] + fn size_Model() -> 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_Init() 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_Init( + function_pointer, + 42 as *const u8, // closure_data_ptr as *const u8, + buffer as *mut u8, + ); + + let output = &*(buffer as *mut RocCallResult); + + match output.into() { + Ok(x) => x, + Err(e) => panic!("failed with {}", e), + } + }) +} + +#[no_mangle] +pub fn rust_main() -> isize { + 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<*const u8>); + + match output.into() { + Ok(_) if size > 16 => { + 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); + + let result = + call_the_closure(function_pointer as *const u8, closure_data_ptr as *const u8); + + std::alloc::dealloc(buffer, layout); + + result + } + Ok(function_pointer) => { + // let closure_data_ptr = buffer.offset(16); + let closure_data_ptr = 0 as *const u8; + + let result = + call_the_closure(function_pointer as *const u8, closure_data_ptr as *const u8); + + std::alloc::dealloc(buffer, layout); + + result + } + 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 closure took {:.4} ms to compute this answer: {:?}", + duration.as_secs_f64() * 1000.0, + // truncate the answer, so stdout is not swamped + answer + ); + + // Exit code + 0 +} + +/* +#[no_mangle] +pub fn old_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); + + let result = + call_the_closure(function_pointer as *const u8, closure_data_ptr as *const u8); + + std::alloc::dealloc(buffer, layout); + + result + } + 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 closure took {:.4} ms to compute this answer: {:?}", + duration.as_secs_f64() * 1000.0, + // truncate the answer, so stdout is not swamped + answer + ); + + // Exit code + 0 +} +*/