mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-13 09:49:11 +03:00
commit
5fe620f9b7
@ -223,13 +223,13 @@ mod cli_run {
|
||||
// expected_ending: "",
|
||||
// use_valgrind: true,
|
||||
// },
|
||||
// cli:"cli" => Example {
|
||||
// filename: "Echo.roc",
|
||||
// executable_filename: "echo",
|
||||
// stdin: &["Giovanni\n", "Giorgio\n"],
|
||||
// expected_ending: "Giovanni Giorgio!\n",
|
||||
// use_valgrind: true,
|
||||
// },
|
||||
cli:"cli" => Example {
|
||||
filename: "Echo.roc",
|
||||
executable_filename: "echo",
|
||||
stdin: &["Giovanni\n", "Giorgio\n"],
|
||||
expected_ending: "Hi, Giovanni Giorgio!\n",
|
||||
use_valgrind: true,
|
||||
},
|
||||
// custom_malloc:"custom-malloc" => Example {
|
||||
// filename: "Main.roc",
|
||||
// executable_filename: "custom-malloc-example",
|
||||
|
1
examples/.gitignore
vendored
1
examples/.gitignore
vendored
@ -4,4 +4,3 @@ app
|
||||
libhost.a
|
||||
roc_app.ll
|
||||
roc_app.bc
|
||||
effect-example
|
||||
|
1
examples/cli/.gitignore
vendored
Normal file
1
examples/cli/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
echo
|
18
examples/cli/Echo.roc
Normal file
18
examples/cli/Echo.roc
Normal file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env roc
|
||||
|
||||
app "echo"
|
||||
packages { base: "platform" }
|
||||
imports [ base.Task.{ Task, await }, base.Stdout, base.Stdin ]
|
||||
provides [ main ] to base
|
||||
|
||||
main : Task {} *
|
||||
main =
|
||||
{} <- await (Stdout.line "What's your first name?")
|
||||
|
||||
firstName <- await Stdin.line
|
||||
|
||||
{} <- await (Stdout.line "What's your last name?")
|
||||
|
||||
lastName <- await Stdin.line
|
||||
|
||||
Stdout.line "Hi, \(firstName) \(lastName)!"
|
BIN
examples/cli/cli-example
Executable file
BIN
examples/cli/cli-example
Executable file
Binary file not shown.
BIN
examples/cli/hello-world
Executable file
BIN
examples/cli/hello-world
Executable file
Binary file not shown.
21
examples/cli/platform/Cargo.lock
generated
Normal file
21
examples/cli/platform/Cargo.lock
generated
Normal file
@ -0,0 +1,21 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "host"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"roc_std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5"
|
||||
|
||||
[[package]]
|
||||
name = "roc_std"
|
||||
version = "0.1.0"
|
15
examples/cli/platform/Cargo.toml
Normal file
15
examples/cli/platform/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "host"
|
||||
version = "0.1.0"
|
||||
authors = ["The Roc Contributors"]
|
||||
license = "UPL-1.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
roc_std = { path = "../../../roc_std" }
|
||||
libc = "0.2"
|
||||
|
||||
[workspace]
|
14
examples/cli/platform/Package-Config.roc
Normal file
14
examples/cli/platform/Package-Config.roc
Normal file
@ -0,0 +1,14 @@
|
||||
platform examples/cli
|
||||
requires {}{ main : Task {} [] } # TODO FIXME
|
||||
exposes []
|
||||
packages {}
|
||||
imports [ Task.{ Task } ]
|
||||
provides [ mainForHost ]
|
||||
effects fx.Effect
|
||||
{
|
||||
putLine : Str -> Effect {},
|
||||
getLine : Effect Str
|
||||
}
|
||||
|
||||
mainForHost : Task {} [] as Fx
|
||||
mainForHost = main
|
6
examples/cli/platform/Stdin.roc
Normal file
6
examples/cli/platform/Stdin.roc
Normal file
@ -0,0 +1,6 @@
|
||||
interface Stdin
|
||||
exposes [ line ]
|
||||
imports [ fx.Effect, Task ]
|
||||
|
||||
line : Task.Task Str *
|
||||
line = Effect.after Effect.getLine Task.succeed # TODO FIXME Effect.getLine should suffice
|
9
examples/cli/platform/Stdout.roc
Normal file
9
examples/cli/platform/Stdout.roc
Normal file
@ -0,0 +1,9 @@
|
||||
interface Stdout
|
||||
exposes [ line ]
|
||||
imports [ fx.Effect, Task.{ Task } ]
|
||||
|
||||
# line : Str -> Task.Task {} *
|
||||
# line = \line -> Effect.map (Effect.putLine line) (\_ -> Ok {})
|
||||
|
||||
line : Str -> Task {} *
|
||||
line = \str -> Effect.map (Effect.putLine str) (\_ -> Ok {})
|
44
examples/cli/platform/Task.roc
Normal file
44
examples/cli/platform/Task.roc
Normal file
@ -0,0 +1,44 @@
|
||||
interface Task
|
||||
exposes [ Task, succeed, fail, await, map, onFail, attempt ]
|
||||
imports [ fx.Effect ]
|
||||
|
||||
|
||||
Task ok err : Effect.Effect (Result ok err)
|
||||
|
||||
|
||||
succeed : val -> Task val *
|
||||
succeed = \val ->
|
||||
Effect.always (Ok val)
|
||||
|
||||
|
||||
fail : err -> Task * err
|
||||
fail = \val ->
|
||||
Effect.always (Err val)
|
||||
|
||||
attempt : Task a b, (Result a b -> Task c d) -> Task c d
|
||||
attempt = \effect, transform ->
|
||||
Effect.after effect \result ->
|
||||
when result is
|
||||
Ok ok -> transform (Ok ok)
|
||||
Err err -> transform (Err err)
|
||||
|
||||
await : Task a err, (a -> Task b err) -> Task b err
|
||||
await = \effect, transform ->
|
||||
Effect.after effect \result ->
|
||||
when result is
|
||||
Ok a -> transform a
|
||||
Err err -> Task.fail err
|
||||
|
||||
onFail : Task ok a, (a -> Task ok b) -> Task ok b
|
||||
onFail = \effect, transform ->
|
||||
Effect.after effect \result ->
|
||||
when result is
|
||||
Ok a -> Task.succeed a
|
||||
Err err -> transform err
|
||||
|
||||
map : Task a err, (a -> b) -> Task b err
|
||||
map = \effect, transform ->
|
||||
Effect.after effect \result ->
|
||||
when result is
|
||||
Ok a -> Task.succeed (transform a)
|
||||
Err err -> Task.fail err
|
7
examples/cli/platform/host.c
Normal file
7
examples/cli/platform/host.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
extern int rust_main();
|
||||
|
||||
int main() {
|
||||
return rust_main();
|
||||
}
|
139
examples/cli/platform/src/lib.rs
Normal file
139
examples/cli/platform/src/lib.rs
Normal file
@ -0,0 +1,139 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use core::alloc::Layout;
|
||||
use core::ffi::c_void;
|
||||
use core::mem::MaybeUninit;
|
||||
use libc;
|
||||
use roc_std::{RocCallResult, RocStr};
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "roc__mainForHost_1_exposed"]
|
||||
fn roc_main(output: *mut u8) -> ();
|
||||
|
||||
#[link_name = "roc__mainForHost_size"]
|
||||
fn roc_main_size() -> i64;
|
||||
|
||||
#[link_name = "roc__mainForHost_1_Fx_caller"]
|
||||
fn call_Fx(flags: *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 unsafe fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void {
|
||||
libc::malloc(size)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_realloc(
|
||||
c_ptr: *mut c_void,
|
||||
new_size: usize,
|
||||
_old_size: usize,
|
||||
_alignment: u32,
|
||||
) -> *mut c_void {
|
||||
libc::realloc(c_ptr, new_size)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_dealloc(c_ptr: *mut c_void, _alignment: u32) {
|
||||
libc::free(c_ptr)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_panic(c_ptr: *mut c_void, tag_id: u32) {
|
||||
match tag_id {
|
||||
0 => {
|
||||
let slice = CStr::from_ptr(c_ptr as *const c_char);
|
||||
let string = slice.to_str().unwrap();
|
||||
eprintln!("Roc hit a panic: {}", string);
|
||||
std::process::exit(1);
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn rust_main() -> isize {
|
||||
let size = unsafe { roc_main_size() } as usize;
|
||||
let layout = Layout::array::<u8>(size).unwrap();
|
||||
|
||||
unsafe {
|
||||
// TODO allocate on the stack if it's under a certain size
|
||||
let buffer = std::alloc::alloc(layout);
|
||||
|
||||
roc_main(buffer);
|
||||
|
||||
let output = buffer as *mut RocCallResult<()>;
|
||||
|
||||
match (&*output).into() {
|
||||
Ok(()) => {
|
||||
let closure_data_ptr = buffer.offset(8);
|
||||
let result = call_the_closure(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
|
||||
}
|
||||
|
||||
unsafe fn call_the_closure(closure_data_ptr: *const u8) -> i64 {
|
||||
let size = size_Fx_result() as usize;
|
||||
let layout = Layout::array::<u8>(size).unwrap();
|
||||
let buffer = std::alloc::alloc(layout) as *mut u8;
|
||||
|
||||
call_Fx(
|
||||
// This flags pointer will never get dereferenced
|
||||
MaybeUninit::uninit().as_ptr(),
|
||||
closure_data_ptr as *const u8,
|
||||
buffer as *mut u8,
|
||||
);
|
||||
|
||||
let output = &*(buffer as *mut RocCallResult<()>);
|
||||
|
||||
match output.into() {
|
||||
Ok(_) => {
|
||||
std::alloc::dealloc(buffer, layout);
|
||||
0
|
||||
}
|
||||
Err(e) => panic!("failed with {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
#[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())
|
||||
}
|
||||
|
||||
#[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);
|
||||
|
||||
// don't mess with the refcount!
|
||||
core::mem::forget(line);
|
||||
|
||||
()
|
||||
}
|
@ -584,6 +584,10 @@ impl RocStr {
|
||||
|
||||
let raw_ptr = Self::get_element_ptr(raw_ptr as *mut u8);
|
||||
|
||||
// write the refcount
|
||||
let refcount_ptr = raw_ptr as *mut isize;
|
||||
*(refcount_ptr.offset(-1)) = isize::MIN;
|
||||
|
||||
{
|
||||
// NOTE: using a memcpy here causes weird issues
|
||||
let target_ptr = raw_ptr as *mut u8;
|
||||
|
Loading…
Reference in New Issue
Block a user