mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
make the example loop a couple of times
This commit is contained in:
parent
f00bd9ba01
commit
a67a750fdc
5 changed files with 168 additions and 35 deletions
|
@ -478,7 +478,6 @@ pub fn build_exp_literal<'a, 'ctx, 'env>(
|
||||||
let ctx = env.context;
|
let ctx = env.context;
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
let number_of_chars = str_literal.len() as u64;
|
let number_of_chars = str_literal.len() as u64;
|
||||||
let elem_bytes = CHAR_LAYOUT.stack_size(env.ptr_bytes) as u64;
|
|
||||||
let ptr_bytes = env.ptr_bytes;
|
let ptr_bytes = env.ptr_bytes;
|
||||||
|
|
||||||
let populate_str = |ptr| {
|
let populate_str = |ptr| {
|
||||||
|
|
|
@ -3,7 +3,6 @@ use bumpalo::Bump;
|
||||||
use inkwell::context::Context;
|
use inkwell::context::Context;
|
||||||
use inkwell::types::BasicTypeEnum::{self, *};
|
use inkwell::types::BasicTypeEnum::{self, *};
|
||||||
use inkwell::types::{ArrayType, BasicType, FunctionType, IntType, PointerType, StructType};
|
use inkwell::types::{ArrayType, BasicType, FunctionType, IntType, PointerType, StructType};
|
||||||
use inkwell::values::IntValue;
|
|
||||||
use inkwell::AddressSpace;
|
use inkwell::AddressSpace;
|
||||||
use roc_mono::layout::Layout;
|
use roc_mono::layout::Layout;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
interface Cmd
|
interface Cmd
|
||||||
exposes [ Cmd, none, map, putLine ]
|
exposes [ Cmd, none, map, putLine, getLine, always, after ]
|
||||||
imports [ Effect ]
|
imports [ Effect ]
|
||||||
|
|
||||||
Cmd a : Effect.Effect a
|
Cmd a : Effect.Effect a
|
||||||
|
@ -7,10 +7,18 @@ Cmd a : Effect.Effect a
|
||||||
none : Cmd {}
|
none : Cmd {}
|
||||||
none = Effect.always {}
|
none = Effect.always {}
|
||||||
|
|
||||||
# getLine = Effect.after Effect.getLine always
|
always : {} -> Cmd {}
|
||||||
|
always = \x -> Effect.always x
|
||||||
|
|
||||||
|
getLine : (Str -> msg) -> Cmd msg
|
||||||
|
getLine = \toMsg ->
|
||||||
|
Effect.map Effect.getLine toMsg
|
||||||
|
|
||||||
putLine : Str -> Cmd {}
|
putLine : Str -> Cmd {}
|
||||||
putLine = \line -> Effect.putLine line
|
putLine = \line -> Effect.putLine line
|
||||||
|
|
||||||
map : Cmd a, (a -> b) -> Cmd b
|
map : Cmd a, (a -> b) -> Cmd b
|
||||||
map = \cmd, transform -> Effect.map cmd transform
|
map = \cmd, transform -> Effect.map cmd transform
|
||||||
|
|
||||||
|
after : Cmd a, (a -> Cmd b) -> Cmd b
|
||||||
|
after = \cmd, transform -> Effect.after cmd transform
|
||||||
|
|
|
@ -12,8 +12,30 @@ platform folkertdev/foo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mainForHost : {init : ({} -> I64) as Init }
|
mainForHost :
|
||||||
|
{
|
||||||
|
init : ({} -> { model: I64, cmd : (Cmd.Cmd [ Line Str ]) as Fx }) as Init,
|
||||||
|
update : ([ Line Str ], I64 -> { model: I64, cmd : Cmd.Cmd [ Line Str ] } ) as Update
|
||||||
|
}
|
||||||
mainForHost =
|
mainForHost =
|
||||||
{ init : \{} -> 42 }
|
{
|
||||||
|
init : \{} ->
|
||||||
|
{
|
||||||
|
model: 42,
|
||||||
|
cmd:
|
||||||
|
Cmd.after (Cmd.putLine "Type a thing, and I'll say it back") \{} ->
|
||||||
|
Cmd.getLine (\l -> Line l)
|
||||||
|
},
|
||||||
|
update : \msg, model ->
|
||||||
|
when msg is
|
||||||
|
Line line ->
|
||||||
|
cmd =
|
||||||
|
Cmd.after (Cmd.putLine "You said:") \{} ->
|
||||||
|
Cmd.after (Cmd.putLine line) \{} ->
|
||||||
|
Cmd.after (Cmd.putLine "Type another thing, and I'll say it back") \{} ->
|
||||||
|
Cmd.getLine (\l -> Line l)
|
||||||
|
|
||||||
|
{ model: model + 1, cmd }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,9 @@ use roc_std::RocStr;
|
||||||
use std::alloc::Layout;
|
use std::alloc::Layout;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
type Msg = RocStr;
|
||||||
|
type Model = i64;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "roc__mainForHost_1_exposed"]
|
#[link_name = "roc__mainForHost_1_exposed"]
|
||||||
fn roc_main(output: *mut u8) -> ();
|
fn roc_main(output: *mut u8) -> ();
|
||||||
|
@ -19,6 +22,33 @@ extern "C" {
|
||||||
#[link_name = "roc__mainForHost_1_Init_size"]
|
#[link_name = "roc__mainForHost_1_Init_size"]
|
||||||
fn size_Init() -> i64;
|
fn size_Init() -> i64;
|
||||||
|
|
||||||
|
#[link_name = "roc__mainForHost_1_Init_result_size"]
|
||||||
|
fn size_Init_result() -> i64;
|
||||||
|
|
||||||
|
#[link_name = "roc__mainForHost_1_Update_caller"]
|
||||||
|
fn call_Update(
|
||||||
|
msg: Msg,
|
||||||
|
model: Model,
|
||||||
|
function_pointer: *const u8,
|
||||||
|
closure_data: *const u8,
|
||||||
|
output: *mut u8,
|
||||||
|
) -> ();
|
||||||
|
|
||||||
|
#[link_name = "roc__mainForHost_1_Update_size"]
|
||||||
|
fn size_Update() -> i64;
|
||||||
|
|
||||||
|
#[link_name = "roc__mainForHost_1_Update_result_size"]
|
||||||
|
fn size_Update_result() -> i64;
|
||||||
|
|
||||||
|
#[link_name = "roc__mainForHost_1_Fx_caller"]
|
||||||
|
fn call_Fx(function_pointer: *const u8, closure_data: *const u8, output: *mut u8) -> ();
|
||||||
|
|
||||||
|
#[link_name = "roc__mainForHost_1_Fx_size"]
|
||||||
|
fn size_Fx() -> i64;
|
||||||
|
|
||||||
|
#[link_name = "roc__mainForHost_1_Fx_result_size"]
|
||||||
|
fn size_Fx_result() -> i64;
|
||||||
|
|
||||||
#[link_name = "roc__mainForHost_1_Model_size"]
|
#[link_name = "roc__mainForHost_1_Model_size"]
|
||||||
fn size_Model() -> i64;
|
fn size_Model() -> i64;
|
||||||
}
|
}
|
||||||
|
@ -50,23 +80,104 @@ pub fn roc_fx_getLine() -> RocStr {
|
||||||
RocStr::from_slice_with_capacity(line1.as_bytes(), line1.len())
|
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 {
|
unsafe fn run_fx(function_pointer: *const u8, closure_data_ptr: *const u8) -> Msg {
|
||||||
let size = size_Init() as usize;
|
let size = size_Fx_result() as usize;
|
||||||
|
|
||||||
alloca::with_stack_bytes(size, |buffer| {
|
alloca::with_stack_bytes(size, |buffer| {
|
||||||
let buffer: *mut std::ffi::c_void = buffer;
|
let buffer: *mut std::ffi::c_void = buffer;
|
||||||
let buffer: *mut u8 = buffer as *mut u8;
|
let buffer: *mut u8 = buffer as *mut u8;
|
||||||
|
|
||||||
call_Init(
|
call_Fx(
|
||||||
function_pointer,
|
function_pointer,
|
||||||
42 as *const u8, // closure_data_ptr as *const u8,
|
closure_data_ptr as *const u8,
|
||||||
buffer as *mut u8,
|
buffer as *mut u8,
|
||||||
);
|
);
|
||||||
|
|
||||||
let output = &*(buffer as *mut RocCallResult<i64>);
|
let output = &*(buffer as *mut RocCallResult<()>);
|
||||||
|
|
||||||
match output.into() {
|
match output.into() {
|
||||||
Ok(x) => x,
|
Ok(()) => {
|
||||||
|
let mut bytes = *(buffer.add(8) as *const (u64, u64));
|
||||||
|
let msg = std::mem::transmute::<(u64, u64), RocStr>(bytes);
|
||||||
|
|
||||||
|
msg
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(e) => panic!("failed with {}", e),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn run_init(function_pointer: *const u8, closure_data_ptr: *const u8) -> (Model, Msg) {
|
||||||
|
let size = size_Init_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_Init(function_pointer, 0 as *const u8, buffer as *mut u8);
|
||||||
|
|
||||||
|
// cmd < model, so the command comes first
|
||||||
|
let output = &*(buffer as *mut RocCallResult<()>);
|
||||||
|
|
||||||
|
match output.into() {
|
||||||
|
Ok(_) => {
|
||||||
|
let offset = 8 + size_Fx();
|
||||||
|
let model_ptr = buffer.add(offset as usize);
|
||||||
|
let model: i64 = *(model_ptr as *const i64);
|
||||||
|
|
||||||
|
let cmd_fn_ptr_ptr = buffer.add(8) as *const i64;
|
||||||
|
let cmd_fn_ptr = (*cmd_fn_ptr_ptr) as *const u8;
|
||||||
|
let cmd_closure_data_ptr = buffer.add(16);
|
||||||
|
|
||||||
|
let msg = run_fx(cmd_fn_ptr, cmd_closure_data_ptr);
|
||||||
|
|
||||||
|
(model, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(e) => panic!("failed with {}", e),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn run_update(
|
||||||
|
msg: RocStr,
|
||||||
|
model: Model,
|
||||||
|
function_pointer: *const u8,
|
||||||
|
closure_data_ptr: *const u8,
|
||||||
|
) -> (Model, Msg) {
|
||||||
|
let size = size_Update_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_Update(
|
||||||
|
msg,
|
||||||
|
model,
|
||||||
|
function_pointer,
|
||||||
|
closure_data_ptr,
|
||||||
|
buffer as *mut u8,
|
||||||
|
);
|
||||||
|
|
||||||
|
// cmd < model, so the command comes first
|
||||||
|
let output = &*(buffer as *mut RocCallResult<()>);
|
||||||
|
|
||||||
|
match output.into() {
|
||||||
|
Ok(_) => {
|
||||||
|
let offset = 8 + size_Fx();
|
||||||
|
let model_ptr = buffer.add(offset as usize);
|
||||||
|
let model: i64 = *(model_ptr as *const i64);
|
||||||
|
|
||||||
|
let cmd_fn_ptr_ptr = buffer.add(8) as *const i64;
|
||||||
|
let cmd_fn_ptr = (*cmd_fn_ptr_ptr) as *const u8;
|
||||||
|
let cmd_closure_data_ptr = buffer.add(16);
|
||||||
|
|
||||||
|
let msg = run_fx(cmd_fn_ptr, cmd_closure_data_ptr);
|
||||||
|
|
||||||
|
(model, msg)
|
||||||
|
}
|
||||||
|
|
||||||
Err(e) => panic!("failed with {}", e),
|
Err(e) => panic!("failed with {}", e),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -83,37 +194,31 @@ pub fn rust_main() -> isize {
|
||||||
|
|
||||||
roc_main(buffer);
|
roc_main(buffer);
|
||||||
|
|
||||||
let output = &*(buffer as *mut RocCallResult<*const u8>);
|
let output = &*(buffer as *mut RocCallResult<(*const u8, *const u8)>);
|
||||||
|
|
||||||
match output.into() {
|
match output.into() {
|
||||||
Ok(_) if size > 16 => {
|
Ok((init_fn_ptr, update_fn_ptr)) => {
|
||||||
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 = buffer.offset(16);
|
||||||
let closure_data_ptr = 0 as *const u8;
|
let closure_data_ptr = 0 as *const u8;
|
||||||
|
|
||||||
let result =
|
let (mut model, mut msg) =
|
||||||
call_the_closure(function_pointer as *const u8, closure_data_ptr as *const u8);
|
run_init(init_fn_ptr as *const u8, closure_data_ptr as *const u8);
|
||||||
|
|
||||||
|
for _ in 0..5 {
|
||||||
|
let result = run_update(
|
||||||
|
msg,
|
||||||
|
model,
|
||||||
|
update_fn_ptr as *const u8,
|
||||||
|
closure_data_ptr as *const u8,
|
||||||
|
);
|
||||||
|
|
||||||
|
model = result.0;
|
||||||
|
msg = result.1;
|
||||||
|
}
|
||||||
|
|
||||||
std::alloc::dealloc(buffer, layout);
|
std::alloc::dealloc(buffer, layout);
|
||||||
|
|
||||||
result
|
model
|
||||||
}
|
}
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
std::alloc::dealloc(buffer, layout);
|
std::alloc::dealloc(buffer, layout);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue