Skip to content

Commit

Permalink
Generate effectful hosted functions
Browse files Browse the repository at this point in the history
  • Loading branch information
agu-z committed Oct 15, 2024
1 parent 3abdae6 commit 5ed7181
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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}");

Expand Down Expand Up @@ -107,6 +107,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

Expand Down
2 changes: 1 addition & 1 deletion crates/compiler/can/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions crates/compiler/can/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,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,
);

Expand Down Expand Up @@ -580,7 +580,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,
);

Expand Down
7 changes: 7 additions & 0 deletions examples/cli/effects-platform/Effect.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
hosted Effect
exposes [putLine, getLine]
imports []

putLine : Str => {}

getLine : {} => Str
7 changes: 0 additions & 7 deletions examples/cli/effects-platform/PlatformTasks.roc

This file was deleted.

34 changes: 0 additions & 34 deletions examples/cli/effects-platform/host.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand All @@ -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();
}
Expand Down
6 changes: 3 additions & 3 deletions examples/cli/effects-platform/main.roc
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
platform "effects"
requires {} { main : Task {} [] }
requires {} { main : {} => {} }
exposes []
packages {}
imports []
provides [mainForHost]

mainForHost : Task {} []
mainForHost = main
mainForHost : {} => {}
mainForHost = \{} -> main {}
14 changes: 6 additions & 8 deletions examples/cli/effects.roc
Original file line number Diff line number Diff line change
@@ -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"

0 comments on commit 5ed7181

Please sign in to comment.