Merge remote-tracking branch 'origin/trunk' into tag-union-imitate-rust

This commit is contained in:
Folkert 2021-11-10 16:31:14 +01:00
commit 144dbef434
76 changed files with 3845 additions and 7801 deletions

View file

@ -300,6 +300,47 @@ pub fn list_swap<'a, 'ctx, 'env>(
)
}
/// List.takeFirst : List elem, Nat -> List elem
pub fn list_take_first<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
original_wrapper: StructValue<'ctx>,
count: IntValue<'ctx>,
element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
call_bitcode_fn_returns_list(
env,
&[
pass_list_cc(env, original_wrapper.into()),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
count.into(),
],
bitcode::LIST_TAKE_FIRST,
)
}
/// List.takeLast : List elem, Nat -> List elem
pub fn list_take_last<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>,
count: IntValue<'ctx>,
element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
call_bitcode_fn_returns_list(
env,
&[
pass_list_cc(env, original_wrapper.into()),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
count.into(),
dec_element_fn.as_global_value().as_pointer_value().into(),
],
bitcode::LIST_TAKE_LAST,
)
}
/// List.drop : List elem, Nat -> List elem
pub fn list_drop<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
@ -920,6 +961,123 @@ pub fn list_any<'a, 'ctx, 'env>(
)
}
/// List.findUnsafe : List elem, (elem -> Bool) -> { value: elem, found: bool }
pub fn list_find_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
roc_function_call: RocFunctionCall<'ctx>,
list: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
let inc_element_fn = build_inc_wrapper(env, layout_ids, element_layout);
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
// { value: *const u8, found: bool }
let result = call_bitcode_fn(
env,
&[
pass_list_cc(env, list),
roc_function_call.caller.into(),
pass_as_opaque(env, roc_function_call.data),
roc_function_call.inc_n_data.into(),
roc_function_call.data_is_owned.into(),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
inc_element_fn.as_global_value().as_pointer_value().into(),
dec_element_fn.as_global_value().as_pointer_value().into(),
],
bitcode::LIST_FIND_UNSAFE,
)
.into_struct_value();
// We promised the caller we'd give them back a struct containing the element
// loaded on the stack, so we do that now. The element can't be loaded directly
// in the Zig definition called above, because we don't know the size of the
// element until user compile time, which is later than the compile time of bitcode defs.
let value_u8_ptr = env
.builder
.build_extract_value(result, 0, "get_value_ptr")
.unwrap()
.into_pointer_value();
let found = env
.builder
.build_extract_value(result, 1, "get_found")
.unwrap()
.into_int_value();
let start_block = env.builder.get_insert_block().unwrap();
let parent = start_block.get_parent().unwrap();
let if_not_null = env.context.append_basic_block(parent, "if_not_null");
let done_block = env.context.append_basic_block(parent, "done");
let value_bt = basic_type_from_layout(env, element_layout);
let default = value_bt.const_zero();
env.builder
.build_conditional_branch(found, if_not_null, done_block);
env.builder.position_at_end(if_not_null);
let value_ptr = env
.builder
.build_bitcast(
value_u8_ptr,
value_bt.ptr_type(AddressSpace::Generic),
"from_opaque",
)
.into_pointer_value();
let loaded = env.builder.build_load(value_ptr, "load_value");
env.builder.build_unconditional_branch(done_block);
env.builder.position_at_end(done_block);
let result_phi = env.builder.build_phi(value_bt, "result");
result_phi.add_incoming(&[(&default, start_block), (&loaded, if_not_null)]);
let value = result_phi.as_basic_value();
let result = env
.context
.struct_type(&[value_bt, env.context.bool_type().into()], false)
.const_zero();
let result = env
.builder
.build_insert_value(result, value, 0, "insert_value")
.unwrap();
env.builder
.build_insert_value(result, found, 1, "insert_found")
.unwrap()
.into_struct_value()
.into()
}
/// Returns { value: \empty, found: False }, representing that no element was found in a call
/// to List.find when the layout of the element is also unknown.
pub fn list_find_trivial_not_found<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
) -> BasicValueEnum<'ctx> {
let empty_type = env.context.custom_width_int_type(0);
let result = env
.context
.struct_type(&[empty_type.into(), env.context.bool_type().into()], false)
.const_zero();
env.builder
.build_insert_value(
result,
env.context.bool_type().const_zero(),
1,
"insert_found",
)
.unwrap()
.into_struct_value()
.into()
}
pub fn decrementing_elem_loop<'ctx, LoopFn>(
builder: &Builder<'ctx>,
ctx: &'ctx Context,