mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
call ListReplace and generate struct afterwards
This commit is contained in:
parent
dc59ba97c2
commit
aff962809b
2 changed files with 40 additions and 17 deletions
|
@ -1257,12 +1257,12 @@ pub fn listConcat(list_a: RocList, list_b: RocList, alignment: u32, element_widt
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listReplaceInPlace(
|
pub fn listReplaceInPlace(
|
||||||
list: RocList
|
list: RocList,
|
||||||
index: usize,
|
index: usize,
|
||||||
element: Opaque,
|
element: Opaque,
|
||||||
element_width: usize,
|
element_width: usize,
|
||||||
out_element: ?[*]u8,
|
out_element: ?[*]u8,
|
||||||
) callconv(.C) extern RocList {
|
) callconv(.C) RocList {
|
||||||
// INVARIANT: bounds checking happens on the roc side
|
// INVARIANT: bounds checking happens on the roc side
|
||||||
//
|
//
|
||||||
// at the time of writing, the function is implemented roughly as
|
// at the time of writing, the function is implemented roughly as
|
||||||
|
@ -1273,7 +1273,7 @@ pub fn listReplaceInPlace(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listReplace(
|
pub fn listReplace(
|
||||||
list: RocList
|
list: RocList,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
index: usize,
|
index: usize,
|
||||||
element: Opaque,
|
element: Opaque,
|
||||||
|
@ -1286,16 +1286,16 @@ pub fn listReplace(
|
||||||
// `if inBounds then LowLevelListReplace input index item else input`
|
// `if inBounds then LowLevelListReplace input index item else input`
|
||||||
// so we don't do a bounds check here. Hence, the list is also non-empty,
|
// so we don't do a bounds check here. Hence, the list is also non-empty,
|
||||||
// because inserting into an empty list is always out of bounds
|
// because inserting into an empty list is always out of bounds
|
||||||
listReplaceInPlaceHelp(list.makeUnique(alignment, element_width), index, element, element_width, out_element);
|
return listReplaceInPlaceHelp(list.makeUnique(alignment, element_width), index, element, element_width, out_element);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn listReplaceInPlaceHelp(
|
inline fn listReplaceInPlaceHelp(
|
||||||
list: RocList
|
list: RocList,
|
||||||
index: usize,
|
index: usize,
|
||||||
element: Opaque,
|
element: Opaque,
|
||||||
element_width: usize,
|
element_width: usize,
|
||||||
out_element: ?[*]u8,
|
out_element: ?[*]u8,
|
||||||
) extern struct RocList {
|
) RocList {
|
||||||
// the element we will replace
|
// the element we will replace
|
||||||
var element_at_index = (list.bytes orelse undefined) + (index * element_width);
|
var element_at_index = (list.bytes orelse undefined) + (index * element_width);
|
||||||
|
|
||||||
|
|
|
@ -301,41 +301,64 @@ pub fn list_replace_unsafe<'a, 'ctx, 'env>(
|
||||||
element_layout: &Layout<'a>,
|
element_layout: &Layout<'a>,
|
||||||
update_mode: UpdateMode,
|
update_mode: UpdateMode,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
// TODO: This or elsewhere needs to deal with building the record that gets returned.
|
let element_type = basic_type_from_layout(env, &element_layout);
|
||||||
let (length, bytes) = load_list(
|
let element_ptr = env
|
||||||
env.builder,
|
.builder
|
||||||
list.into_struct_value(),
|
.build_alloca(element_type, "output_element_as_opaque");
|
||||||
env.context.i8_type().ptr_type(AddressSpace::Generic),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Assume the bounds have already been checked earlier
|
// Assume the bounds have already been checked earlier
|
||||||
// (e.g. by List.replace or List.set, which wrap List.#replaceUnsafe)
|
// (e.g. by List.replace or List.set, which wrap List.#replaceUnsafe)
|
||||||
let new_bytes = match update_mode {
|
let new_list = match update_mode {
|
||||||
UpdateMode::InPlace => call_bitcode_fn(
|
UpdateMode::InPlace => call_bitcode_fn(
|
||||||
env,
|
env,
|
||||||
&[
|
&[
|
||||||
bytes.into(),
|
list.into(),
|
||||||
index.into(),
|
index.into(),
|
||||||
pass_element_as_opaque(env, element, *element_layout),
|
pass_element_as_opaque(env, element, *element_layout),
|
||||||
layout_width(env, element_layout),
|
layout_width(env, element_layout),
|
||||||
|
pass_as_opaque(env, element_ptr),
|
||||||
],
|
],
|
||||||
bitcode::LIST_REPLACE_IN_PLACE,
|
bitcode::LIST_REPLACE_IN_PLACE,
|
||||||
),
|
),
|
||||||
UpdateMode::Immutable => call_bitcode_fn(
|
UpdateMode::Immutable => call_bitcode_fn(
|
||||||
env,
|
env,
|
||||||
&[
|
&[
|
||||||
bytes.into(),
|
list.into(),
|
||||||
length.into(),
|
|
||||||
env.alignment_intvalue(element_layout),
|
env.alignment_intvalue(element_layout),
|
||||||
index.into(),
|
index.into(),
|
||||||
pass_element_as_opaque(env, element, *element_layout),
|
pass_element_as_opaque(env, element, *element_layout),
|
||||||
layout_width(env, element_layout),
|
layout_width(env, element_layout),
|
||||||
|
pass_as_opaque(env, element_ptr),
|
||||||
],
|
],
|
||||||
bitcode::LIST_REPLACE,
|
bitcode::LIST_REPLACE,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
store_list(env, new_bytes.into_pointer_value(), length)
|
// Load the element and returned list into a struct.
|
||||||
|
let old_element = env.builder.build_load(element_ptr, "load_element");
|
||||||
|
|
||||||
|
let result = env
|
||||||
|
.context
|
||||||
|
.struct_type(
|
||||||
|
// TODO: does the order need to be decided by the size of the element type.
|
||||||
|
&[
|
||||||
|
super::convert::zig_list_type(env).into(),
|
||||||
|
element_type.into(),
|
||||||
|
],
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.const_zero();
|
||||||
|
|
||||||
|
let result = env
|
||||||
|
.builder
|
||||||
|
.build_insert_value(result, old_element, 0, "insert_value")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
env.builder
|
||||||
|
.build_insert_value(result, new_list, 1, "insert_list")
|
||||||
|
.unwrap()
|
||||||
|
.into_struct_value()
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List.set : List elem, Nat, elem -> List elem
|
/// List.set : List elem, Nat, elem -> List elem
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue