mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Generate effectful hosted functions
This commit is contained in:
parent
7af05cc6c9
commit
bc3ab0186a
8 changed files with 59 additions and 56 deletions
|
@ -33,7 +33,7 @@ pub fn build_host_exposed_def(
|
|||
|
||||
let def_body = {
|
||||
match typ.shallow_structural_dealias() {
|
||||
Type::Function(args, _, _, _) => {
|
||||
Type::Function(args, _, _, fx) if **fx == Type::Pure => {
|
||||
for i in 0..args.len() {
|
||||
let name = format!("closure_arg_{ident}_{i}");
|
||||
|
||||
|
@ -109,6 +109,45 @@ pub fn build_host_exposed_def(
|
|||
loc_body: Box::new(Loc::at_zero(body)),
|
||||
})
|
||||
}
|
||||
Type::Function(args, _, _, fx) if **fx == Type::Effectful => {
|
||||
for i in 0..args.len() {
|
||||
let name = format!("{ident}_arg_{i}");
|
||||
|
||||
let arg_symbol = {
|
||||
let ident = name.clone().into();
|
||||
scope.introduce(ident, Region::zero()).unwrap()
|
||||
};
|
||||
|
||||
let arg_var = var_store.fresh();
|
||||
|
||||
arguments.push((
|
||||
arg_var,
|
||||
AnnotatedMark::new(var_store),
|
||||
Loc::at_zero(Pattern::Identifier(arg_symbol)),
|
||||
));
|
||||
|
||||
linked_symbol_arguments.push((arg_var, Expr::Var(arg_symbol, arg_var)));
|
||||
}
|
||||
|
||||
let foreign_symbol_name = format!("roc_fx_{ident}");
|
||||
let foreign_call = Expr::ForeignCall {
|
||||
foreign_symbol: foreign_symbol_name.into(),
|
||||
args: linked_symbol_arguments,
|
||||
ret_var: var_store.fresh(),
|
||||
};
|
||||
|
||||
Expr::Closure(ClosureData {
|
||||
function_type: var_store.fresh(),
|
||||
closure_type: var_store.fresh(),
|
||||
return_type: var_store.fresh(),
|
||||
fx_type: var_store.fresh(),
|
||||
name: symbol,
|
||||
captured_symbols: std::vec::Vec::new(),
|
||||
recursive: Recursive::NotRecursive,
|
||||
arguments,
|
||||
loc_body: Box::new(Loc::at_zero(foreign_call)),
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
// not a function
|
||||
|
|
@ -14,6 +14,7 @@ pub mod copy;
|
|||
pub mod def;
|
||||
mod derive;
|
||||
pub mod desugar;
|
||||
pub mod effect_module;
|
||||
pub mod env;
|
||||
pub mod exhaustive;
|
||||
pub mod expected;
|
||||
|
@ -25,7 +26,6 @@ pub mod procedure;
|
|||
pub mod scope;
|
||||
pub mod string;
|
||||
pub mod suffixed;
|
||||
pub mod task_module;
|
||||
pub mod traverse;
|
||||
|
||||
pub use derive::DERIVED_REGION;
|
||||
|
|
|
@ -533,7 +533,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
aliases: Default::default(),
|
||||
};
|
||||
|
||||
let hosted_def = crate::task_module::build_host_exposed_def(
|
||||
let hosted_def = crate::effect_module::build_host_exposed_def(
|
||||
&mut scope, *symbol, &ident, var_store, annotation,
|
||||
);
|
||||
|
||||
|
@ -586,7 +586,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
aliases: Default::default(),
|
||||
};
|
||||
|
||||
let hosted_def = crate::task_module::build_host_exposed_def(
|
||||
let hosted_def = crate::effect_module::build_host_exposed_def(
|
||||
&mut scope, *symbol, &ident, var_store, annotation,
|
||||
);
|
||||
|
||||
|
|
7
examples/cli/effects-platform/Effect.roc
Normal file
7
examples/cli/effects-platform/Effect.roc
Normal file
|
@ -0,0 +1,7 @@
|
|||
hosted Effect
|
||||
exposes [putLine, getLine]
|
||||
imports []
|
||||
|
||||
putLine : Str => {}
|
||||
|
||||
getLine : {} => Str
|
|
@ -1,7 +0,0 @@
|
|||
hosted PlatformTasks
|
||||
exposes [putLine, getLine]
|
||||
imports []
|
||||
|
||||
putLine : Str -> Task {} *
|
||||
|
||||
getLine : Task Str *
|
|
@ -12,9 +12,6 @@ const Allocator = mem.Allocator;
|
|||
|
||||
extern fn roc__mainForHost_1_exposed_generic([*]u8) void;
|
||||
extern fn roc__mainForHost_1_exposed_size() i64;
|
||||
extern fn roc__mainForHost_0_caller(*const u8, [*]u8, [*]u8) void;
|
||||
extern fn roc__mainForHost_0_size() i64;
|
||||
extern fn roc__mainForHost_0_result_size() i64;
|
||||
|
||||
const Align = 2 * @alignOf(usize);
|
||||
extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque;
|
||||
|
@ -127,8 +124,6 @@ pub export fn main() u8 {
|
|||
|
||||
roc__mainForHost_1_exposed_generic(output);
|
||||
|
||||
call_the_closure(output);
|
||||
|
||||
const nanos = timer.read();
|
||||
const seconds = (@as(f64, @floatFromInt(nanos)) / 1_000_000_000.0);
|
||||
|
||||
|
@ -141,35 +136,6 @@ fn to_seconds(tms: std.os.timespec) f64 {
|
|||
return @as(f64, @floatFromInt(tms.tv_sec)) + (@as(f64, @floatFromInt(tms.tv_nsec)) / 1_000_000_000.0);
|
||||
}
|
||||
|
||||
fn call_the_closure(closure_data_pointer: [*]u8) void {
|
||||
const allocator = std.heap.page_allocator;
|
||||
|
||||
const size = roc__mainForHost_0_result_size();
|
||||
|
||||
if (size == 0) {
|
||||
// the function call returns an empty record
|
||||
// allocating 0 bytes causes issues because the allocator will return a NULL pointer
|
||||
// So it's special-cased
|
||||
const flags: u8 = 0;
|
||||
var result: [1]u8 = .{0};
|
||||
roc__mainForHost_0_caller(&flags, closure_data_pointer, &result);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const raw_output = allocator.alignedAlloc(u8, @alignOf(u64), @as(usize, @intCast(size))) catch unreachable;
|
||||
var output = @as([*]u8, @ptrCast(raw_output));
|
||||
|
||||
defer {
|
||||
allocator.free(raw_output);
|
||||
}
|
||||
|
||||
const flags: u8 = 0;
|
||||
roc__mainForHost_0_caller(&flags, closure_data_pointer, output);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pub export fn roc_fx_getLine() str.RocStr {
|
||||
return roc_fx_getLine_help() catch return str.RocStr.empty();
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
platform "effects"
|
||||
requires {} { main : Task {} [] }
|
||||
requires {} { main : {} => {} }
|
||||
exposes []
|
||||
packages {}
|
||||
imports []
|
||||
provides [mainForHost]
|
||||
|
||||
mainForHost : Task {} []
|
||||
mainForHost = main
|
||||
mainForHost : {} => {}
|
||||
mainForHost = \{} -> main {}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
app [main] { pf: platform "effects-platform/main.roc" }
|
||||
|
||||
import pf.PlatformTasks
|
||||
import pf.Effect
|
||||
|
||||
main : Task {} []
|
||||
main =
|
||||
line = PlatformTasks.getLine!
|
||||
PlatformTasks.putLine! "You entered: $(line)"
|
||||
PlatformTasks.putLine! "It is known"
|
||||
|
||||
Task.ok {}
|
||||
main : {} => {}
|
||||
main = \{} ->
|
||||
line = Effect.getLine {}
|
||||
_ = Effect.putLine "You entered: $(line)"
|
||||
Effect.putLine "It is known"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue