List.join works in all cases

This commit is contained in:
Chad Stearns 2020-08-08 00:33:05 -04:00
parent 910389cef2
commit 0e15f75f3b
2 changed files with 89 additions and 29 deletions

View file

@ -1694,16 +1694,26 @@ fn list_join<'a, 'ctx, 'env>(
.build_load(wrapper_ptr, "inner_list_wrapper") .build_load(wrapper_ptr, "inner_list_wrapper")
.into_struct_value() .into_struct_value()
}; };
let inner_list_len = load_list_len(builder, inner_list_wrapper);
let inner_list_ptr = load_list_ptr(builder, inner_list_wrapper, elem_ptr_type);
let inner_index_name = "#inner_index";
let inner_index_alloca = builder.build_alloca(ctx.i64_type(), inner_index_name);
// Inner Loop // Inner Loop
{ {
let inner_list_index = ctx.i64_type().const_int(0, false); let inner_list_len = load_list_len(builder, inner_list_wrapper);
let inner_list_ptr =
load_list_ptr(builder, inner_list_wrapper, elem_ptr_type);
// inner_list_len > 0
let inner_list_comparison = builder.build_int_compare(
IntPredicate::UGT,
inner_list_len,
ctx.i64_type().const_int(0, false),
"greaterthanzero",
);
let inner_index_name = "#inner_index";
let inner_index_alloca =
builder.build_alloca(ctx.i64_type(), inner_index_name);
let inner_list_index = ctx.i64_type().const_int(0, false);
builder.build_store(inner_index_alloca, inner_list_index); builder.build_store(inner_index_alloca, inner_list_index);
let inner_loop_bb = ctx.append_basic_block(parent, "loop"); let inner_loop_bb = ctx.append_basic_block(parent, "loop");
@ -1711,19 +1721,33 @@ fn list_join<'a, 'ctx, 'env>(
builder.position_at_end(inner_loop_bb); builder.position_at_end(inner_loop_bb);
// #index = #index + 1 // #index = #index + 1
let curr_index = builder let curr_inner_index = builder
.build_load(inner_index_alloca, inner_index_name) .build_load(inner_index_alloca, inner_index_name)
.into_int_value(); .into_int_value();
let next_index = builder.build_int_add( let next_inner_index = builder.build_int_add(
curr_index, curr_inner_index,
ctx.i64_type().const_int(1, false), ctx.i64_type().const_int(1, false),
"nextindex", "nextindex",
); );
builder.build_store(inner_index_alloca, next_index); builder.build_store(inner_index_alloca, next_inner_index);
let build_empty = || {
BasicValueEnum::PointerValue(
builder
.build_load(dest_elem_ptr_alloca, "load_dest_elem_ptr")
// .into_int_value()
.into_pointer_value(),
)
};
let build_non_empty = || {
let src_elem_ptr = unsafe { let src_elem_ptr = unsafe {
builder.build_in_bounds_gep(inner_list_ptr, &[curr_index], "load_index") builder.build_in_bounds_gep(
inner_list_ptr,
&[curr_inner_index],
"load_index",
)
}; };
let src_elem = builder.build_load(src_elem_ptr, "get_elem"); let src_elem = builder.build_load(src_elem_ptr, "get_elem");
@ -1735,19 +1759,32 @@ fn list_join<'a, 'ctx, 'env>(
builder.build_store(curr_dest_elem_ptr, src_elem); builder.build_store(curr_dest_elem_ptr, src_elem);
let next_dest_elem_ptr = unsafe { BasicValueEnum::PointerValue(unsafe {
builder.build_in_bounds_gep( builder.build_in_bounds_gep(
curr_dest_elem_ptr, curr_dest_elem_ptr,
&[env.ptr_int().const_int(1 as u64, false)], &[env.ptr_int().const_int(1 as u64, false)],
"increment_dest_elem", "increment_dest_elem",
) )
})
}; };
let next_dest_elem_ptr = build_basic_phi2(
env,
parent,
inner_list_comparison,
build_non_empty,
build_empty,
BasicTypeEnum::PointerType(get_ptr_type(
&elem_type,
AddressSpace::Generic,
)),
);
builder.build_store(dest_elem_ptr_alloca, next_dest_elem_ptr); builder.build_store(dest_elem_ptr_alloca, next_dest_elem_ptr);
let inner_loop_end_cond = builder.build_int_compare( let inner_loop_end_cond = builder.build_int_compare(
IntPredicate::ULT, IntPredicate::ULT,
next_index, next_inner_index,
inner_list_len, inner_list_len,
"loopcond", "loopcond",
); );

View file

@ -113,6 +113,28 @@ mod gen_list {
&'static [f64] &'static [f64]
); );
assert_evals_to!(
indoc!(
r#"
List.join
[
[ 1.2, 1.1 ],
[ 2.1, 2.2 ],
[ 3.0, 4.0, 5.0, 6.1, 9.0 ],
[ 3.0, 4.0, 5.0, 6.1, 9.0 ],
[ 3.0, 4.0, 5.0, 6.1, 9.0 ],
[ 3.0, 4.0, 5.0, 6.1, 9.0 ],
[ 3.0, 4.0, 5.0, 6.1, 9.0 ]
]
"#
),
&[
1.2, 1.1, 2.1, 2.2, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0,
5.0, 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0
],
&'static [f64]
);
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
@ -128,6 +150,7 @@ mod gen_list {
); );
assert_evals_to!("List.join [ [], [], [] ]", &[], &'static [f64]); assert_evals_to!("List.join [ [], [], [] ]", &[], &'static [f64]);
assert_evals_to!( assert_evals_to!(
"List.join [ [ 1.2, 1.1 ], [] ]", "List.join [ [ 1.2, 1.1 ], [] ]",
&[1.2, 1.1], &[1.2, 1.1],