mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
133 lines
3.5 KiB
Rust
133 lines
3.5 KiB
Rust
#![allow(non_snake_case)]
|
|
|
|
use roc_std::{alloca, RocCallResult, RocResult, RocStr};
|
|
use std::alloc::Layout;
|
|
|
|
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_Fx_caller"]
|
|
fn call_Fx(
|
|
flags: &'static u8,
|
|
function_pointer: *const u8,
|
|
closure_data: *const u8,
|
|
output: *mut u8,
|
|
) -> ();
|
|
|
|
#[allow(dead_code)]
|
|
#[link_name = "roc__mainForHost_1_Fx_size"]
|
|
fn size_Fx() -> i64;
|
|
|
|
#[link_name = "roc__mainForHost_1_Fx_result_size"]
|
|
fn size_Fx_result() -> 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_httpGetUtf8(url: RocStr) -> RocResult<RocStr, RocStr> {
|
|
match ureq::get(unsafe { url.as_str() }).call() {
|
|
Ok(resp) => match resp.into_string() {
|
|
Ok(contents) => RocResult::Ok(RocStr::from_slice(contents.as_bytes())), // TODO make roc::Result!
|
|
// TODO turn this error into an enum!
|
|
Err(err) => RocResult::Err(RocStr::from_slice(format!("{:?}", err).as_bytes())),
|
|
},
|
|
// TODO turn this error into an enum!
|
|
Err(err) => RocResult::Err(RocStr::from_slice(format!("{:?}", err).as_bytes())),
|
|
}
|
|
}
|
|
|
|
#[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(line1.as_bytes())
|
|
}
|
|
|
|
unsafe fn call_the_closure(function_pointer: *const u8, closure_data_ptr: *const u8) -> i64 {
|
|
let size = size_Fx_result() 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(
|
|
&0,
|
|
function_pointer,
|
|
closure_data_ptr as *const u8,
|
|
buffer as *mut u8,
|
|
);
|
|
|
|
let output = &*(buffer as *mut RocCallResult<()>);
|
|
|
|
match output.into() {
|
|
Ok(_) => 0,
|
|
Err(e) => panic!("failed with {}", e),
|
|
}
|
|
})
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub fn rust_main() -> isize {
|
|
let size = unsafe { roc_main_size() } as usize;
|
|
let layout = Layout::array::<u8>(size).unwrap();
|
|
|
|
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);
|
|
}
|
|
}
|
|
};
|
|
|
|
// Exit code
|
|
0
|
|
}
|