mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
Set.walk closure trouble
This commit is contained in:
parent
35e1e94a94
commit
9527434be8
3 changed files with 111 additions and 22 deletions
|
@ -1850,6 +1850,7 @@ fn invoke_roc_function<'a, 'ctx, 'env>(
|
||||||
layout: Layout<'a>,
|
layout: Layout<'a>,
|
||||||
function_value: Either<FunctionValue<'ctx>, PointerValue<'ctx>>,
|
function_value: Either<FunctionValue<'ctx>, PointerValue<'ctx>>,
|
||||||
arguments: &[Symbol],
|
arguments: &[Symbol],
|
||||||
|
closure_argument: Option<BasicValueEnum<'ctx>>,
|
||||||
pass: &'a roc_mono::ir::Stmt<'a>,
|
pass: &'a roc_mono::ir::Stmt<'a>,
|
||||||
fail: &'a roc_mono::ir::Stmt<'a>,
|
fail: &'a roc_mono::ir::Stmt<'a>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
@ -1860,6 +1861,7 @@ fn invoke_roc_function<'a, 'ctx, 'env>(
|
||||||
for arg in arguments.iter() {
|
for arg in arguments.iter() {
|
||||||
arg_vals.push(load_symbol(scope, arg));
|
arg_vals.push(load_symbol(scope, arg));
|
||||||
}
|
}
|
||||||
|
arg_vals.extend(closure_argument);
|
||||||
|
|
||||||
let pass_block = context.append_basic_block(parent, "invoke_pass");
|
let pass_block = context.append_basic_block(parent, "invoke_pass");
|
||||||
let fail_block = context.append_basic_block(parent, "invoke_fail");
|
let fail_block = context.append_basic_block(parent, "invoke_fail");
|
||||||
|
@ -2019,6 +2021,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
layout.clone(),
|
layout.clone(),
|
||||||
function_value.into(),
|
function_value.into(),
|
||||||
call.arguments,
|
call.arguments,
|
||||||
|
None,
|
||||||
pass,
|
pass,
|
||||||
fail,
|
fail,
|
||||||
)
|
)
|
||||||
|
@ -2026,28 +2029,57 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
CallType::ByPointer { name, .. } => {
|
CallType::ByPointer { name, .. } => {
|
||||||
let sub_expr = load_symbol(scope, &name);
|
let sub_expr = load_symbol(scope, &name);
|
||||||
|
|
||||||
let function_ptr = match sub_expr {
|
match sub_expr {
|
||||||
BasicValueEnum::PointerValue(ptr) => ptr,
|
BasicValueEnum::PointerValue(function_ptr) => {
|
||||||
|
// basic call by pointer
|
||||||
|
invoke_roc_function(
|
||||||
|
env,
|
||||||
|
layout_ids,
|
||||||
|
scope,
|
||||||
|
parent,
|
||||||
|
*symbol,
|
||||||
|
layout.clone(),
|
||||||
|
function_ptr.into(),
|
||||||
|
call.arguments,
|
||||||
|
None,
|
||||||
|
pass,
|
||||||
|
fail,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
BasicValueEnum::StructValue(ptr_and_data) => {
|
||||||
|
// this is a closure
|
||||||
|
let builder = env.builder;
|
||||||
|
|
||||||
|
let function_ptr = builder
|
||||||
|
.build_extract_value(ptr_and_data, 0, "function_ptr")
|
||||||
|
.unwrap()
|
||||||
|
.into_pointer_value();
|
||||||
|
|
||||||
|
let closure_data = builder
|
||||||
|
.build_extract_value(ptr_and_data, 1, "closure_data")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
invoke_roc_function(
|
||||||
|
env,
|
||||||
|
layout_ids,
|
||||||
|
scope,
|
||||||
|
parent,
|
||||||
|
*symbol,
|
||||||
|
layout.clone(),
|
||||||
|
function_ptr.into(),
|
||||||
|
call.arguments,
|
||||||
|
Some(closure_data),
|
||||||
|
pass,
|
||||||
|
fail,
|
||||||
|
)
|
||||||
|
}
|
||||||
non_ptr => {
|
non_ptr => {
|
||||||
panic!(
|
panic!(
|
||||||
"Tried to call by pointer, but encountered a non-pointer: {:?}",
|
"Tried to call by pointer, but encountered a non-pointer: {:?}",
|
||||||
non_ptr
|
non_ptr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
invoke_roc_function(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
scope,
|
|
||||||
parent,
|
|
||||||
*symbol,
|
|
||||||
layout.clone(),
|
|
||||||
function_ptr.into(),
|
|
||||||
call.arguments,
|
|
||||||
pass,
|
|
||||||
fail,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
CallType::Foreign {
|
CallType::Foreign {
|
||||||
ref foreign_symbol,
|
ref foreign_symbol,
|
||||||
|
|
|
@ -921,6 +921,63 @@ pub fn list_walk<'a, 'ctx, 'env>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
BasicValueEnum::StructValue(ptr_and_data),
|
||||||
|
Layout::Closure(_, closure_layout, ret_elem_layout),
|
||||||
|
) => {
|
||||||
|
let builder = env.builder;
|
||||||
|
|
||||||
|
let func_ptr = builder
|
||||||
|
.build_extract_value(ptr_and_data, 0, "function_ptr")
|
||||||
|
.unwrap()
|
||||||
|
.into_pointer_value();
|
||||||
|
|
||||||
|
let closure_data = builder
|
||||||
|
.build_extract_value(ptr_and_data, 1, "closure_data")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let elem_layout = match list_layout {
|
||||||
|
Layout::Builtin(Builtin::List(_, layout)) => layout,
|
||||||
|
_ => unreachable!("can only fold over a list"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let elem_type = basic_type_from_layout(env.arena, ctx, elem_layout, env.ptr_bytes);
|
||||||
|
let elem_ptr_type = get_ptr_type(&elem_type, AddressSpace::Generic);
|
||||||
|
|
||||||
|
let list_ptr = load_list_ptr(builder, list_wrapper, elem_ptr_type);
|
||||||
|
|
||||||
|
let walk_right_loop = |_, elem: BasicValueEnum<'ctx>| {
|
||||||
|
// load current accumulator
|
||||||
|
let current = builder.build_load(accum_alloca, "retrieve_accum");
|
||||||
|
|
||||||
|
let call_site_value = builder.build_call(
|
||||||
|
func_ptr,
|
||||||
|
&[elem, current, closure_data],
|
||||||
|
"#walk_right_func",
|
||||||
|
);
|
||||||
|
|
||||||
|
// set the calling convention explicitly for this call
|
||||||
|
call_site_value.set_call_convention(crate::llvm::build::FAST_CALL_CONV);
|
||||||
|
|
||||||
|
let new_current = call_site_value
|
||||||
|
.try_as_basic_value()
|
||||||
|
.left()
|
||||||
|
.unwrap_or_else(|| panic!("LLVM error: Invalid call by pointer."));
|
||||||
|
|
||||||
|
builder.build_store(accum_alloca, new_current);
|
||||||
|
};
|
||||||
|
|
||||||
|
incrementing_elem_loop(
|
||||||
|
builder,
|
||||||
|
ctx,
|
||||||
|
parent,
|
||||||
|
list_ptr,
|
||||||
|
len,
|
||||||
|
"#index",
|
||||||
|
walk_right_loop,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!(
|
unreachable!(
|
||||||
"Invalid function basic value enum or layout for List.keepIf : {:?}",
|
"Invalid function basic value enum or layout for List.keepIf : {:?}",
|
||||||
|
|
|
@ -5933,12 +5933,6 @@ fn call_by_name<'a>(
|
||||||
None if assigned.module_id() != proc_name.module_id() => {
|
None if assigned.module_id() != proc_name.module_id() => {
|
||||||
add_needed_external(procs, env, original_fn_var, proc_name);
|
add_needed_external(procs, env, original_fn_var, proc_name);
|
||||||
|
|
||||||
debug_assert_eq!(
|
|
||||||
arg_layouts.len(),
|
|
||||||
field_symbols.len(),
|
|
||||||
"scroll up a bit for background"
|
|
||||||
);
|
|
||||||
|
|
||||||
let call = if proc_name.module_id() == ModuleId::ATTR {
|
let call = if proc_name.module_id() == ModuleId::ATTR {
|
||||||
// the callable is one of the ATTR::ARG_n symbols
|
// the callable is one of the ATTR::ARG_n symbols
|
||||||
// we must call those by-pointer
|
// we must call those by-pointer
|
||||||
|
@ -5952,6 +5946,12 @@ fn call_by_name<'a>(
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
debug_assert_eq!(
|
||||||
|
arg_layouts.len(),
|
||||||
|
field_symbols.len(),
|
||||||
|
"scroll up a bit for background {:?}",
|
||||||
|
proc_name
|
||||||
|
);
|
||||||
self::Call {
|
self::Call {
|
||||||
call_type: CallType::ByName {
|
call_type: CallType::ByName {
|
||||||
name: proc_name,
|
name: proc_name,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue