mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
WIP List.map + RC'd closure troubles
This commit is contained in:
parent
2b72f9e733
commit
8dddf952a8
5 changed files with 121 additions and 18 deletions
|
@ -175,18 +175,34 @@ pub fn listReverse(list: RocList, alignment: usize, element_width: usize) callco
|
|||
}
|
||||
}
|
||||
|
||||
pub fn listMap(list: RocList, transform: Opaque, caller: Caller1, alignment: usize, old_element_width: usize, new_element_width: usize) callconv(.C) RocList {
|
||||
pub const RocFunctionCall1 = extern struct {
|
||||
caller: Caller1,
|
||||
data: Opaque,
|
||||
inc_n_data: IncN,
|
||||
data_is_owned: bool,
|
||||
};
|
||||
|
||||
pub fn listMap(
|
||||
list: RocList,
|
||||
call: RocFunctionCall1,
|
||||
alignment: usize,
|
||||
old_element_width: usize,
|
||||
new_element_width: usize,
|
||||
) callconv(.C) RocList {
|
||||
if (list.bytes) |source_ptr| {
|
||||
const size = list.len();
|
||||
var i: usize = 0;
|
||||
const output = RocList.allocate(std.heap.c_allocator, alignment, size, new_element_width);
|
||||
const target_ptr = output.bytes orelse unreachable;
|
||||
|
||||
while (i < size) : (i += 1) {
|
||||
caller(transform, source_ptr + (i * old_element_width), target_ptr + (i * new_element_width));
|
||||
}
|
||||
// if (call.data_is_owned) {
|
||||
// }
|
||||
|
||||
// utils.decref(std.heap.c_allocator, alignment, list.bytes, size * old_element_width);
|
||||
call.inc_n_data(call.data, size);
|
||||
|
||||
while (i < size) : (i += 1) {
|
||||
call.caller(call.data, source_ptr + (i * old_element_width), target_ptr + (i * new_element_width));
|
||||
}
|
||||
|
||||
return output;
|
||||
} else {
|
||||
|
|
|
@ -3669,10 +3669,12 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
||||
Layout::Builtin(Builtin::List(_, element_layout)) => list_map(
|
||||
env,
|
||||
layout_ids,
|
||||
function,
|
||||
function_layout,
|
||||
closure,
|
||||
*closure_layout,
|
||||
function_owns_closure_data,
|
||||
list,
|
||||
element_layout,
|
||||
),
|
||||
|
|
|
@ -858,26 +858,100 @@ pub fn list_map_with_index<'a, 'ctx, 'env>(
|
|||
)
|
||||
}
|
||||
|
||||
fn roc_function_call_1<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
transform: FunctionValue<'ctx>,
|
||||
closure_data: BasicValueEnum<'ctx>,
|
||||
closure_data_layout: Layout<'a>,
|
||||
closure_data_is_owned: bool,
|
||||
argument_layouts: &[Layout<'a>],
|
||||
) -> PointerValue<'ctx> {
|
||||
// %list.RocFunctionCall1 = type { void (i8*, i8*, i8*)*, i8*, void (i8*, i64)*, i1 }
|
||||
let struct_type = env.module.get_struct_type("list.RocFunctionCall1").unwrap();
|
||||
|
||||
let builder = env.builder;
|
||||
|
||||
let closure_data_ptr = builder.build_alloca(closure_data.get_type(), "closure_data_ptr");
|
||||
env.builder.build_store(closure_data_ptr, closure_data);
|
||||
|
||||
let stepper_caller =
|
||||
build_transform_caller_new(env, transform, closure_data_layout, argument_layouts)
|
||||
.as_global_value()
|
||||
.as_pointer_value();
|
||||
|
||||
let inc_closure_data = build_inc_n_wrapper(env, layout_ids, &closure_data_layout)
|
||||
.as_global_value()
|
||||
.as_pointer_value();
|
||||
|
||||
let closure_data_is_owned = env
|
||||
.context
|
||||
.bool_type()
|
||||
.const_int(closure_data_is_owned as u64, false);
|
||||
|
||||
let mut struct_value = builder
|
||||
.build_insert_value(struct_type.get_undef(), stepper_caller, 0, "")
|
||||
.unwrap();
|
||||
|
||||
struct_value = builder
|
||||
.build_insert_value(struct_value, pass_as_opaque(env, closure_data_ptr), 1, "")
|
||||
.unwrap();
|
||||
|
||||
struct_value = builder
|
||||
.build_insert_value(struct_value, inc_closure_data, 2, "")
|
||||
.unwrap();
|
||||
|
||||
struct_value = builder
|
||||
.build_insert_value(struct_value, closure_data_is_owned, 3, "")
|
||||
.unwrap();
|
||||
|
||||
let ptr = env.builder.build_alloca(struct_type, "roc_function_call_1");
|
||||
|
||||
env.builder.build_store(ptr, struct_value);
|
||||
|
||||
ptr
|
||||
}
|
||||
|
||||
/// List.map : List before, (before -> after) -> List after
|
||||
pub fn list_map<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
transform: FunctionValue<'ctx>,
|
||||
transform_layout: Layout<'a>,
|
||||
closure_data: BasicValueEnum<'ctx>,
|
||||
closure_data_layout: Layout<'a>,
|
||||
closure_data_is_owned: bool,
|
||||
list: BasicValueEnum<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
list_map_generic(
|
||||
let argument_layouts = &[*element_layout];
|
||||
|
||||
let return_layout = match transform_layout {
|
||||
Layout::FunctionPointer(_, ret) => ret,
|
||||
Layout::Closure(_, _, ret) => ret,
|
||||
_ => unreachable!("not a callable layout"),
|
||||
};
|
||||
|
||||
let roc_function_call = roc_function_call_1(
|
||||
env,
|
||||
layout_ids,
|
||||
transform,
|
||||
transform_layout,
|
||||
list,
|
||||
element_layout,
|
||||
closure_data,
|
||||
closure_data_layout,
|
||||
closure_data_is_owned,
|
||||
argument_layouts,
|
||||
);
|
||||
|
||||
call_bitcode_fn_returns_list(
|
||||
env,
|
||||
&[
|
||||
pass_list_as_i128(env, list),
|
||||
roc_function_call.into(),
|
||||
alignment_intvalue(env, &element_layout),
|
||||
layout_width(env, element_layout),
|
||||
layout_width(env, return_layout),
|
||||
],
|
||||
bitcode::LIST_MAP,
|
||||
&[*element_layout],
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -2049,12 +2049,6 @@ fn update<'a>(
|
|||
&& state.goal_phase == Phase::MakeSpecializations
|
||||
{
|
||||
Proc::insert_refcount_operations(arena, &mut state.procedures);
|
||||
Proc::optimize_refcount_operations(
|
||||
arena,
|
||||
module_id,
|
||||
&mut ident_ids,
|
||||
&mut state.procedures,
|
||||
);
|
||||
// display the mono IR of the module, for debug purposes
|
||||
if roc_mono::ir::PRETTY_PRINT_IR_SYMBOLS {
|
||||
let procs_string = state
|
||||
|
@ -2067,6 +2061,12 @@ fn update<'a>(
|
|||
|
||||
println!("{}", result);
|
||||
}
|
||||
// Proc::optimize_refcount_operations(
|
||||
// arena,
|
||||
// module_id,
|
||||
// &mut ident_ids,
|
||||
// &mut state.procedures,
|
||||
// );
|
||||
|
||||
state.constrained_ident_ids.insert(module_id, ident_ids);
|
||||
|
||||
|
|
|
@ -416,6 +416,12 @@ impl<'a> Context<'a> {
|
|||
and it has been borrowed by the application.
|
||||
Remark: `x` may occur multiple times in the application (e.g., `f x y x`).
|
||||
This is why we check whether it is the first occurrence. */
|
||||
dbg!(
|
||||
self.must_consume(*x),
|
||||
is_first_occurence(xs, i),
|
||||
*is_borrow,
|
||||
!b_live_vars.contains(x)
|
||||
);
|
||||
|
||||
if self.must_consume(*x)
|
||||
&& is_first_occurence(xs, i)
|
||||
|
@ -461,16 +467,21 @@ impl<'a> Context<'a> {
|
|||
Some(ps) => {
|
||||
let b = if ps[0].borrow {
|
||||
let ps = [BORROWED, BORROWED, BORROWED];
|
||||
println!("----------------");
|
||||
self.add_dec_after_lowlevel(arguments, &ps, b, b_live_vars)
|
||||
} else {
|
||||
// let ps = [OWNED, BORROWED, BORROWED];
|
||||
// self.add_dec_after_lowlevel(arguments, &ps, b, b_live_vars)
|
||||
let ps = [OWNED, BORROWED, BORROWED];
|
||||
println!("----------------");
|
||||
let b = self.add_dec_after_lowlevel(arguments, &ps, b, b_live_vars);
|
||||
|
||||
self.arena.alloc(Stmt::Refcounting(
|
||||
ModifyRc::DecRef(arguments[0]),
|
||||
self.arena.alloc(b),
|
||||
))
|
||||
};
|
||||
|
||||
dbg!(self.must_consume(arguments[2]));
|
||||
|
||||
let call_type = {
|
||||
if ps[1].borrow {
|
||||
call_type
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue