Merge pull request #3369 from rtfeldman/pure-roc-list-walk

List.walk and friends in pure Roc
This commit is contained in:
Folkert de Vries 2022-07-03 02:32:43 +02:00 committed by GitHub
commit 2a82d24847
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 344 additions and 1630 deletions

View file

@ -733,53 +733,6 @@ fn call_spec(
add_loop(builder, block, state_type, init_state, loop_body) add_loop(builder, block, state_type, init_state, loop_body)
} }
ListWalk { xs, state } | ListWalkBackwards { xs, state } => {
let list = env.symbols[xs];
let state = env.symbols[state];
let loop_body = |builder: &mut FuncDefBuilder, block, state| {
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
let element = builder.add_bag_get(block, bag)?;
let new_state = call_function!(builder, block, [state, element]);
Ok(new_state)
};
let state_layout = argument_layouts[0];
let state_type =
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
let init_state = state;
add_loop(builder, block, state_type, init_state, loop_body)
}
ListWalkUntil { xs, state } => {
let list = env.symbols[xs];
let state = env.symbols[state];
let loop_body = |builder: &mut FuncDefBuilder, block, state| {
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
let element = builder.add_bag_get(block, bag)?;
let continue_or_stop = call_function!(builder, block, [state, element]);
// just assume it is a continue
let unwrapped = builder.add_unwrap_union(block, continue_or_stop, 0)?;
let new_state = builder.add_get_tuple_field(block, unwrapped, 0)?;
Ok(new_state)
};
let state_layout = argument_layouts[0];
let state_type =
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
let init_state = state;
add_loop(builder, block, state_type, init_state, loop_body)
}
// List.mapWithIndex : List before, (before, Nat -> after) -> List after // List.mapWithIndex : List before, (before, Nat -> after) -> List after
ListMapWithIndex { xs } => { ListMapWithIndex { xs } => {
let list = env.symbols[xs]; let list = env.symbols[xs];
@ -963,82 +916,6 @@ fn call_spec(
add_loop(builder, block, state_type, init_state, loop_body) add_loop(builder, block, state_type, init_state, loop_body)
} }
ListAny { xs } => {
let list = env.symbols[xs];
let loop_body = |builder: &mut FuncDefBuilder, block, _state| {
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
let element = builder.add_bag_get(block, bag)?;
let new_state = call_function!(builder, block, [element]);
Ok(new_state)
};
let state_layout = Layout::Builtin(Builtin::Bool);
let state_type =
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
let init_state = new_num(builder, block)?;
add_loop(builder, block, state_type, init_state, loop_body)
}
ListAll { xs } => {
let list = env.symbols[xs];
let loop_body = |builder: &mut FuncDefBuilder, block, _state| {
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
let element = builder.add_bag_get(block, bag)?;
let new_state = call_function!(builder, block, [element]);
Ok(new_state)
};
let state_layout = Layout::Builtin(Builtin::Bool);
let state_type =
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
let init_state = new_num(builder, block)?;
add_loop(builder, block, state_type, init_state, loop_body)
}
ListFindUnsafe { xs } => {
let list = env.symbols[xs];
// ListFindUnsafe returns { value: v, found: Bool=Int1 }
let output_layouts = vec![argument_layouts[0], Layout::Builtin(Builtin::Bool)];
let output_layout = Layout::struct_no_name_order(&output_layouts);
let output_type =
layout_spec(builder, &output_layout, &WhenRecursive::Unreachable)?;
let loop_body = |builder: &mut FuncDefBuilder, block, output| {
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
let element = builder.add_bag_get(block, bag)?;
let _is_found = call_function!(builder, block, [element]);
// We may or may not use the element we got from the list in the output struct,
// depending on whether we found the element to satisfy the "find" predicate.
// If we did find the element, our output "changes" to be a record including that element.
let found_branch = builder.add_block();
let new_output =
builder.add_unknown_with(block, &[element], output_type)?;
let not_found_branch = builder.add_block();
builder.add_choice(
block,
&[
BlockExpr(found_branch, new_output),
BlockExpr(not_found_branch, output),
],
)
};
// Assume the output is initially { found: False, value: \empty }
let output_state = builder.add_unknown_with(block, &[], output_type)?;
add_loop(builder, block, output_type, output_state, loop_body)
}
} }
} }
} }

View file

@ -197,44 +197,6 @@ const Caller2 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
const Caller3 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void; const Caller3 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
const Caller4 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void; const Caller4 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
pub fn listReverse(list: RocList, alignment: u32, element_width: usize, update_mode: UpdateMode) callconv(.C) RocList {
if (list.bytes) |source_ptr| {
const size = list.len();
var i: usize = 0;
const end: usize = size - 1;
if (update_mode == .InPlace or list.isUnique()) {
// Working from the front and back so
// we only need to go ~(n / 2) iterations.
// If the length is an odd number the middle
// element stays in the same place anyways.
while (i < (end - i)) : (i += 1) {
swapElements(source_ptr, element_width, i, end - i);
}
return list;
} else {
const output = RocList.allocate(alignment, size, element_width);
const target_ptr = output.bytes orelse unreachable;
while (i < size) : (i += 1) {
const last_position = end - i;
@memcpy(target_ptr + (i * element_width), source_ptr + (last_position * element_width), element_width);
}
utils.decref(list.bytes, size * element_width, alignment);
return output;
}
} else {
return RocList.empty();
}
}
pub fn listMap( pub fn listMap(
list: RocList, list: RocList,
caller: Caller1, caller: Caller1,
@ -474,214 +436,6 @@ pub fn listMap4(
} }
} }
pub fn listWalk(
list: RocList,
caller: Caller2,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
accum: Opaque,
alignment: u32,
element_width: usize,
accum_width: usize,
output: Opaque,
) callconv(.C) void {
if (accum_width == 0) {
return;
}
if (list.isEmpty()) {
@memcpy(output orelse unreachable, accum orelse unreachable, accum_width);
return;
}
if (data_is_owned) {
inc_n_data(data, list.len());
}
// TODO handle alloc failing!
const bytes_ptr: [*]u8 = utils.alloc(accum_width, alignment) orelse unreachable;
var b1 = output orelse unreachable;
var b2 = bytes_ptr;
@memcpy(b2, accum orelse unreachable, accum_width);
if (list.bytes) |source_ptr| {
var i: usize = 0;
const size = list.len();
while (i < size) : (i += 1) {
const element = source_ptr + i * element_width;
caller(data, b2, element, b1);
std.mem.swap([*]u8, &b1, &b2);
}
}
@memcpy(output orelse unreachable, b2, accum_width);
utils.dealloc(bytes_ptr, alignment);
}
pub fn listWalkBackwards(
list: RocList,
caller: Caller2,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
accum: Opaque,
alignment: u32,
element_width: usize,
accum_width: usize,
output: Opaque,
) callconv(.C) void {
if (accum_width == 0) {
return;
}
if (list.isEmpty()) {
@memcpy(output orelse unreachable, accum orelse unreachable, accum_width);
return;
}
if (data_is_owned) {
inc_n_data(data, list.len());
}
// TODO handle alloc failing!
const bytes_ptr: [*]u8 = utils.alloc(accum_width, alignment) orelse unreachable;
var b1 = output orelse unreachable;
var b2 = bytes_ptr;
@memcpy(b2, accum orelse unreachable, accum_width);
if (list.bytes) |source_ptr| {
const size = list.len();
var i: usize = size;
while (i > 0) {
i -= 1;
const element = source_ptr + i * element_width;
caller(data, b2, element, b1);
std.mem.swap([*]u8, &b1, &b2);
}
}
@memcpy(output orelse unreachable, b2, accum_width);
utils.dealloc(bytes_ptr, alignment);
}
pub fn listWalkUntil(
list: RocList,
caller: Caller2,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
accum: Opaque,
alignment: u32,
element_width: usize,
continue_stop_width: usize,
accum_width: usize,
has_tag_id: HasTagId,
dec: Dec,
output: Opaque,
) callconv(.C) void {
// [Continue a, Stop a]
if (accum_width == 0) {
return;
}
if (list.isEmpty()) {
@memcpy(output orelse unreachable, accum orelse unreachable, accum_width);
return;
}
// TODO handle alloc failing!
const bytes_ptr: [*]u8 = utils.alloc(continue_stop_width, alignment) orelse unreachable;
// NOTE: assumes data bytes are the first bytes in a tag
@memcpy(bytes_ptr, accum orelse unreachable, accum_width);
if (list.bytes) |source_ptr| {
var i: usize = 0;
const size = list.len();
while (i < size) : (i += 1) {
const element = source_ptr + i * element_width;
if (data_is_owned) {
inc_n_data(data, 1);
}
caller(data, bytes_ptr, element, bytes_ptr);
// [Continue ..., Stop]
const tag_id = has_tag_id(0, bytes_ptr);
if (!tag_id.matched) {
// decrement refcount of the remaining items
i += 1;
while (i < size) : (i += 1) {
dec(source_ptr + i * element_width);
}
break;
}
}
}
@memcpy(output orelse unreachable, bytes_ptr, accum_width);
utils.dealloc(bytes_ptr, alignment);
}
// List.contains : List k, k -> Bool
pub fn listContains(list: RocList, key: Opaque, key_width: usize, is_eq: EqFn) callconv(.C) bool {
if (list.bytes) |source_ptr| {
const size = list.len();
var i: usize = 0;
while (i < size) : (i += 1) {
const element = source_ptr + i * key_width;
if (is_eq(element, key)) {
return true;
}
}
}
return false;
}
pub fn listRepeat(count: usize, alignment: u32, element: Opaque, element_width: usize, inc_n_element: IncN) callconv(.C) RocList {
if (count == 0) {
return RocList.empty();
}
var output = RocList.allocate(alignment, count, element_width);
if (output.bytes) |target_ptr| {
// increment the element's RC N times
inc_n_element(element, count);
var i: usize = 0;
const source = element orelse unreachable;
while (i < count) : (i += 1) {
@memcpy(target_ptr + i * element_width, source, element_width);
}
return output;
} else {
unreachable;
}
}
pub fn listSingle(alignment: u32, element: Opaque, element_width: usize) callconv(.C) RocList {
var output = RocList.allocate(alignment, 1, element_width);
if (output.bytes) |target| {
if (element) |source| {
@memcpy(target, source, element_width);
}
}
return output;
}
pub fn listWithCapacity(capacity: usize, alignment: u32, element_width: usize) callconv(.C) RocList { pub fn listWithCapacity(capacity: usize, alignment: u32, element_width: usize) callconv(.C) RocList {
var output = RocList.allocate(alignment, capacity, element_width); var output = RocList.allocate(alignment, capacity, element_width);
output.length = 0; output.length = 0;
@ -934,66 +688,6 @@ pub fn listSortWith(
return list; return list;
} }
pub fn listAny(
list: RocList,
caller: Caller1,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
element_width: usize,
) callconv(.C) bool {
if (list.bytes) |source_ptr| {
const size = list.len();
if (data_is_owned) {
inc_n_data(data, size);
}
var i: usize = 0;
var satisfied = false;
while (i < size) : (i += 1) {
const element = source_ptr + i * element_width;
caller(data, element, @ptrCast(?[*]u8, &satisfied));
if (satisfied) {
return satisfied;
}
}
}
return false;
}
pub fn listAll(
list: RocList,
caller: Caller1,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
element_width: usize,
) callconv(.C) bool {
if (list.bytes) |source_ptr| {
const size = list.len();
if (data_is_owned) {
inc_n_data(data, size);
}
var i: usize = 0;
while (i < size) : (i += 1) {
var satisfied = false;
const element = source_ptr + i * element_width;
caller(data, element, @ptrCast(?[*]u8, &satisfied));
if (!satisfied) {
return false;
}
}
return true;
}
return true;
}
// SWAP ELEMENTS // SWAP ELEMENTS
inline fn swapHelp(width: usize, temporary: [*]u8, ptr1: [*]u8, ptr2: [*]u8) void { inline fn swapHelp(width: usize, temporary: [*]u8, ptr1: [*]u8, ptr2: [*]u8) void {
@ -1127,41 +821,6 @@ inline fn listReplaceInPlaceHelp(
return list; return list;
} }
pub fn listFindUnsafe(
list: RocList,
caller: Caller1,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
element_width: usize,
inc: Inc,
dec: Dec,
) callconv(.C) extern struct { value: Opaque, found: bool } {
if (list.bytes) |source_ptr| {
const size = list.len();
if (data_is_owned) {
inc_n_data(data, size);
}
var i: usize = 0;
while (i < size) : (i += 1) {
var theOne = false;
const element = source_ptr + (i * element_width);
inc(element);
caller(data, element, @ptrCast(?[*]u8, &theOne));
if (theOne) {
return .{ .value = element, .found = true };
} else {
dec(element);
}
}
return .{ .value = null, .found = false };
} else {
return .{ .value = null, .found = false };
}
}
pub fn listIsUnique( pub fn listIsUnique(
list: RocList, list: RocList,
) callconv(.C) bool { ) callconv(.C) bool {

View file

@ -41,16 +41,9 @@ comptime {
exportListFn(list.listMap3, "map3"); exportListFn(list.listMap3, "map3");
exportListFn(list.listMap4, "map4"); exportListFn(list.listMap4, "map4");
exportListFn(list.listMapWithIndex, "map_with_index"); exportListFn(list.listMapWithIndex, "map_with_index");
exportListFn(list.listWalk, "walk");
exportListFn(list.listWalkUntil, "walkUntil");
exportListFn(list.listWalkBackwards, "walk_backwards");
exportListFn(list.listContains, "contains");
exportListFn(list.listRepeat, "repeat");
exportListFn(list.listAppend, "append"); exportListFn(list.listAppend, "append");
exportListFn(list.listPrepend, "prepend"); exportListFn(list.listPrepend, "prepend");
exportListFn(list.listSingle, "single");
exportListFn(list.listWithCapacity, "with_capacity"); exportListFn(list.listWithCapacity, "with_capacity");
exportListFn(list.listReverse, "reverse");
exportListFn(list.listSortWith, "sort_with"); exportListFn(list.listSortWith, "sort_with");
exportListFn(list.listConcat, "concat"); exportListFn(list.listConcat, "concat");
exportListFn(list.listSublist, "sublist"); exportListFn(list.listSublist, "sublist");
@ -58,9 +51,6 @@ comptime {
exportListFn(list.listReplace, "replace"); exportListFn(list.listReplace, "replace");
exportListFn(list.listReplaceInPlace, "replace_in_place"); exportListFn(list.listReplaceInPlace, "replace_in_place");
exportListFn(list.listSwap, "swap"); exportListFn(list.listSwap, "swap");
exportListFn(list.listAny, "any");
exportListFn(list.listAll, "all");
exportListFn(list.listFindUnsafe, "find_unsafe");
exportListFn(list.listIsUnique, "is_unique"); exportListFn(list.listIsUnique, "is_unique");
} }

View file

@ -372,10 +372,35 @@ contains = \list, needle ->
## Note that in other languages, `walk` is sometimes called `reduce`, ## Note that in other languages, `walk` is sometimes called `reduce`,
## `fold`, `foldLeft`, or `foldl`. ## `fold`, `foldLeft`, or `foldl`.
walk : List elem, state, (state, elem -> state) -> state walk : List elem, state, (state, elem -> state) -> state
walk = \list, state, func ->
walkHelp list state func 0 (len list)
## internal helper
walkHelp : List elem, state, (state, elem -> state), Nat, Nat -> state
walkHelp = \list, state, f, index, length ->
if index < length then
nextState = f state (getUnsafe list index)
walkHelp list nextState f (index + 1) length
else
state
## Note that in other languages, `walkBackwards` is sometimes called `reduceRight`, ## Note that in other languages, `walkBackwards` is sometimes called `reduceRight`,
## `fold`, `foldRight`, or `foldr`. ## `fold`, `foldRight`, or `foldr`.
walkBackwards : List elem, state, (state, elem -> state) -> state walkBackwards : List elem, state, (state, elem -> state) -> state
walkBackwards = \list, state, func ->
walkBackwardsHelp list state func (len list)
## internal helper
walkBackwardsHelp : List elem, state, (state, elem -> state), Nat -> state
walkBackwardsHelp = \list, state, f, indexPlusOne ->
if indexPlusOne == 0 then
state
else
index = indexPlusOne - 1
nextState = f state (getUnsafe list index)
walkBackwardsHelp list nextState f index
## Same as [List.walk], except you can stop walking early. ## Same as [List.walk], except you can stop walking early.
## ##
@ -387,7 +412,7 @@ walkBackwards : List elem, state, (state, elem -> state) -> state
## be outweighed if it results in skipping even a small number of elements. ## be outweighed if it results in skipping even a small number of elements.
## ##
## As such, it is typically better for performance to use this over [List.walk] ## As such, it is typically better for performance to use this over [List.walk]
## if returning `Done` earlier than the last element is expected to be common. ## if returning `Break` earlier than the last element is expected to be common.
walkUntil : List elem, state, (state, elem -> [Continue state, Break state]) -> state walkUntil : List elem, state, (state, elem -> [Continue state, Break state]) -> state
walkUntil = \list, initial, step -> walkUntil = \list, initial, step ->
when List.iterate list initial step is when List.iterate list initial step is
@ -763,7 +788,16 @@ findIndex = \list, matcher ->
## ##
## Some languages have a function called **`slice`** which works similarly to this. ## Some languages have a function called **`slice`** which works similarly to this.
sublist : List elem, { start : Nat, len : Nat } -> List elem sublist : List elem, { start : Nat, len : Nat } -> List elem
## Intersperses `sep` between the elements of `list`
## >>> List.intersperse 9 [1, 2, 3] # [1, 9, 2, 9, 3]
intersperse : List elem, elem -> List elem intersperse : List elem, elem -> List elem
intersperse = \list, sep ->
capacity = 2 * List.len list
init = List.withCapacity capacity
newList = List.walk list init (\acc, elem -> acc |> List.append elem |> List.append sep)
List.dropLast newList
## Splits the list into two lists, around the given index. ## Splits the list into two lists, around the given index.
## ##

View file

@ -354,26 +354,16 @@ pub const LIST_MAP2: &str = "roc_builtins.list.map2";
pub const LIST_MAP3: &str = "roc_builtins.list.map3"; pub const LIST_MAP3: &str = "roc_builtins.list.map3";
pub const LIST_MAP4: &str = "roc_builtins.list.map4"; pub const LIST_MAP4: &str = "roc_builtins.list.map4";
pub const LIST_MAP_WITH_INDEX: &str = "roc_builtins.list.map_with_index"; pub const LIST_MAP_WITH_INDEX: &str = "roc_builtins.list.map_with_index";
pub const LIST_WALK: &str = "roc_builtins.list.walk";
pub const LIST_WALK_UNTIL: &str = "roc_builtins.list.walkUntil";
pub const LIST_WALK_BACKWARDS: &str = "roc_builtins.list.walk_backwards";
pub const LIST_CONTAINS: &str = "roc_builtins.list.contains";
pub const LIST_REPEAT: &str = "roc_builtins.list.repeat";
pub const LIST_APPEND: &str = "roc_builtins.list.append"; pub const LIST_APPEND: &str = "roc_builtins.list.append";
pub const LIST_PREPEND: &str = "roc_builtins.list.prepend"; pub const LIST_PREPEND: &str = "roc_builtins.list.prepend";
pub const LIST_SUBLIST: &str = "roc_builtins.list.sublist"; pub const LIST_SUBLIST: &str = "roc_builtins.list.sublist";
pub const LIST_DROP_AT: &str = "roc_builtins.list.drop_at"; pub const LIST_DROP_AT: &str = "roc_builtins.list.drop_at";
pub const LIST_SWAP: &str = "roc_builtins.list.swap"; pub const LIST_SWAP: &str = "roc_builtins.list.swap";
pub const LIST_SINGLE: &str = "roc_builtins.list.single";
pub const LIST_WITH_CAPACITY: &str = "roc_builtins.list.with_capacity"; pub const LIST_WITH_CAPACITY: &str = "roc_builtins.list.with_capacity";
pub const LIST_REVERSE: &str = "roc_builtins.list.reverse";
pub const LIST_SORT_WITH: &str = "roc_builtins.list.sort_with"; pub const LIST_SORT_WITH: &str = "roc_builtins.list.sort_with";
pub const LIST_CONCAT: &str = "roc_builtins.list.concat"; pub const LIST_CONCAT: &str = "roc_builtins.list.concat";
pub const LIST_REPLACE: &str = "roc_builtins.list.replace"; pub const LIST_REPLACE: &str = "roc_builtins.list.replace";
pub const LIST_REPLACE_IN_PLACE: &str = "roc_builtins.list.replace_in_place"; pub const LIST_REPLACE_IN_PLACE: &str = "roc_builtins.list.replace_in_place";
pub const LIST_ANY: &str = "roc_builtins.list.any";
pub const LIST_ALL: &str = "roc_builtins.list.all";
pub const LIST_FIND_UNSAFE: &str = "roc_builtins.list.find_unsafe";
pub const LIST_IS_UNIQUE: &str = "roc_builtins.list.is_unique"; pub const LIST_IS_UNIQUE: &str = "roc_builtins.list.is_unique";
pub const DEC_FROM_STR: &str = "roc_builtins.dec.from_str"; pub const DEC_FROM_STR: &str = "roc_builtins.dec.from_str";

View file

@ -115,14 +115,10 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
LIST_MAP4 => list_map4, LIST_MAP4 => list_map4,
LIST_SUBLIST => list_sublist, LIST_SUBLIST => list_sublist,
LIST_SPLIT => list_split, LIST_SPLIT => list_split,
LIST_INTERSPERSE => list_intersperse,
LIST_DROP => list_drop, LIST_DROP => list_drop,
LIST_DROP_AT => list_drop_at, LIST_DROP_AT => list_drop_at,
LIST_SWAP => list_swap, LIST_SWAP => list_swap,
LIST_MAP_WITH_INDEX => list_map_with_index, LIST_MAP_WITH_INDEX => list_map_with_index,
LIST_WALK => list_walk,
LIST_WALK_BACKWARDS => list_walk_backwards,
LIST_WALK_UNTIL => list_walk_until,
LIST_SORT_WITH => list_sort_with, LIST_SORT_WITH => list_sort_with,
LIST_IS_UNIQUE => list_is_unique, LIST_IS_UNIQUE => list_is_unique,
DICT_LEN => dict_len, DICT_LEN => dict_len,
@ -2185,96 +2181,6 @@ fn list_sublist(symbol: Symbol, var_store: &mut VarStore) -> Def {
) )
} }
/// List.intersperse : List elem, elem -> List elem
fn list_intersperse(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();
let sep_var = var_store.fresh();
let list_sym = Symbol::ARG_1;
let sep_sym = Symbol::ARG_2;
let clos_var = var_store.fresh();
let clos_acc_var = var_store.fresh();
let clos_sym = Symbol::LIST_INTERSPERSE_CLOS;
let clos_acc_sym = Symbol::ARG_3;
let clos_elem_sym = Symbol::ARG_4;
let int_var = var_store.fresh();
let zero = int::<i128>(
int_var,
Variable::NATURAL,
0,
IntBound::Exact(IntWidth::Nat),
);
// \acc, elem -> acc |> List.append sep |> List.append elem
let clos = Closure(ClosureData {
function_type: clos_var,
closure_type: var_store.fresh(),
return_type: clos_acc_var,
name: clos_sym,
recursive: Recursive::NotRecursive,
captured_symbols: vec![(sep_sym, sep_var)],
arguments: vec![
(
clos_acc_var,
AnnotatedMark::new(var_store),
no_region(Pattern::Identifier(clos_acc_sym)),
),
(
sep_var,
AnnotatedMark::new(var_store),
no_region(Pattern::Identifier(clos_elem_sym)),
),
],
loc_body: {
let append_sep = RunLowLevel {
op: LowLevel::ListAppend,
args: vec![(clos_acc_var, Var(clos_acc_sym)), (sep_var, Var(sep_sym))],
ret_var: clos_acc_var,
};
Box::new(no_region(RunLowLevel {
op: LowLevel::ListAppend,
args: vec![(clos_acc_var, append_sep), (sep_var, Var(clos_elem_sym))],
ret_var: clos_acc_var,
}))
},
});
// List.walk [] l (\acc, elem -> acc |> List.append sep |> List.append elem)
let acc = RunLowLevel {
op: LowLevel::ListWalk,
args: vec![
(list_var, Var(list_sym)),
(
clos_acc_var,
List {
elem_var: sep_var,
loc_elems: vec![],
},
),
(clos_var, clos),
],
ret_var: clos_acc_var,
};
let body = RunLowLevel {
op: LowLevel::ListDropAt,
args: vec![(clos_acc_var, acc), (int_var, zero)],
ret_var: clos_acc_var,
};
defn(
symbol,
vec![(list_var, list_sym), (sep_var, sep_sym)],
var_store,
body,
clos_acc_var,
)
}
/// List.split : List elem, Nat -> { before: List elem, others: List elem } /// List.split : List elem, Nat -> { before: List elem, others: List elem }
fn list_split(symbol: Symbol, var_store: &mut VarStore) -> Def { fn list_split(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh(); let list_var = var_store.fresh();
@ -2481,21 +2387,6 @@ fn list_prepend(symbol: Symbol, var_store: &mut VarStore) -> Def {
) )
} }
/// List.walk : List elem, state, (state, elem -> state) -> state
fn list_walk(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_3(symbol, LowLevel::ListWalk, var_store)
}
/// List.walkBackwards : List elem, state, (state, elem -> state) -> state
fn list_walk_backwards(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_3(symbol, LowLevel::ListWalkBackwards, var_store)
}
/// List.walkUntil : List elem, state, (state, elem -> [Continue state, Stop state]) -> state
fn list_walk_until(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_3(symbol, LowLevel::ListWalkUntil, var_store)
}
/// List.map : List before, (before -> after) -> List after /// List.map : List before, (before -> after) -> List after
fn list_map(symbol: Symbol, var_store: &mut VarStore) -> Def { fn list_map(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_2(symbol, LowLevel::ListMap, var_store) lowlevel_2(symbol, LowLevel::ListMap, var_store)

View file

@ -8,10 +8,10 @@ use crate::llvm::build_dict::{
}; };
use crate::llvm::build_hash::generic_hash; use crate::llvm::build_hash::generic_hash;
use crate::llvm::build_list::{ use crate::llvm::build_list::{
self, allocate_list, empty_polymorphic_list, list_all, list_any, list_append, list_concat, self, allocate_list, empty_polymorphic_list, list_append, list_concat, list_drop_at,
list_drop_at, list_find_unsafe, list_get_unsafe, list_len, list_map, list_map2, list_map3, list_get_unsafe, list_len, list_map, list_map2, list_map3, list_map4, list_map_with_index,
list_map4, list_map_with_index, list_prepend, list_replace_unsafe, list_sort_with, list_prepend, list_replace_unsafe, list_sort_with, list_sublist, list_swap,
list_sublist, list_swap, list_symbol_to_c_abi, list_to_c_abi, list_with_capacity, list_symbol_to_c_abi, list_to_c_abi, list_with_capacity,
}; };
use crate::llvm::build_str::{ use crate::llvm::build_str::{
str_from_float, str_from_int, str_from_utf8, str_from_utf8_range, str_split, str_from_float, str_from_int, str_from_utf8, str_from_utf8_range, str_split,
@ -4881,44 +4881,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
}}; }};
} }
macro_rules! list_walk {
($variant:expr, $xs:expr, $state:expr) => {{
let (list, list_layout) = load_symbol_and_layout(scope, &$xs);
let (default, default_layout) = load_symbol_and_layout(scope, &$state);
let (function, closure, closure_layout) = function_details!();
match list_layout {
Layout::Builtin(Builtin::List(element_layout)) => {
let argument_layouts = &[*default_layout, **element_layout];
let roc_function_call = roc_function_call(
env,
layout_ids,
function,
closure,
closure_layout,
function_owns_closure_data,
argument_layouts,
result_layout,
);
crate::llvm::build_list::list_walk_generic(
env,
layout_ids,
roc_function_call,
&result_layout,
list,
element_layout,
default,
default_layout,
$variant,
)
}
_ => unreachable!("invalid list layout"),
}
}};
}
match op { match op {
ListMap { xs } => { ListMap { xs } => {
// List.map : List before, (before -> after) -> List after // List.map : List before, (before -> after) -> List after
@ -5119,15 +5081,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
_ => unreachable!("invalid list layout"), _ => unreachable!("invalid list layout"),
} }
} }
ListWalk { xs, state } => {
list_walk!(crate::llvm::build_list::ListWalk::Walk, xs, state)
}
ListWalkUntil { xs, state } => {
list_walk!(crate::llvm::build_list::ListWalk::WalkUntil, xs, state)
}
ListWalkBackwards { xs, state } => {
list_walk!(crate::llvm::build_list::ListWalk::WalkBackwards, xs, state)
}
ListSortWith { xs } => { ListSortWith { xs } => {
// List.sortWith : List a, (a, a -> Ordering) -> List a // List.sortWith : List a, (a, a -> Ordering) -> List a
let (list, list_layout) = load_symbol_and_layout(scope, xs); let (list, list_layout) = load_symbol_and_layout(scope, xs);
@ -5167,78 +5120,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
_ => unreachable!("invalid list layout"), _ => unreachable!("invalid list layout"),
} }
} }
ListAny { xs } => {
let (list, list_layout) = load_symbol_and_layout(scope, xs);
let (function, closure, closure_layout) = function_details!();
match list_layout {
Layout::Builtin(Builtin::List(element_layout)) => {
let argument_layouts = &[**element_layout];
let roc_function_call = roc_function_call(
env,
layout_ids,
function,
closure,
closure_layout,
function_owns_closure_data,
argument_layouts,
Layout::Builtin(Builtin::Bool),
);
list_any(env, roc_function_call, list, element_layout)
}
_ => unreachable!("invalid list layout"),
}
}
ListAll { xs } => {
let (list, list_layout) = load_symbol_and_layout(scope, xs);
let (function, closure, closure_layout) = function_details!();
match list_layout {
Layout::Builtin(Builtin::List(element_layout)) => {
let argument_layouts = &[**element_layout];
let roc_function_call = roc_function_call(
env,
layout_ids,
function,
closure,
closure_layout,
function_owns_closure_data,
argument_layouts,
Layout::Builtin(Builtin::Bool),
);
list_all(env, roc_function_call, list, element_layout)
}
_ => unreachable!("invalid list layout"),
}
}
ListFindUnsafe { xs } => {
let (list, list_layout) = load_symbol_and_layout(scope, xs);
let (function, closure, closure_layout) = function_details!();
match list_layout {
Layout::Builtin(Builtin::List(element_layout)) => {
let argument_layouts = &[**element_layout];
let roc_function_call = roc_function_call(
env,
layout_ids,
function,
closure,
closure_layout,
function_owns_closure_data,
argument_layouts,
Layout::Builtin(Builtin::Bool),
);
list_find_unsafe(env, layout_ids, roc_function_call, list, element_layout)
}
_ => unreachable!("invalid list layout"),
}
}
DictWalk { xs, state } => { DictWalk { xs, state } => {
let (dict, dict_layout) = load_symbol_and_layout(scope, xs); let (dict, dict_layout) = load_symbol_and_layout(scope, xs);
let (default, default_layout) = load_symbol_and_layout(scope, state); let (default, default_layout) = load_symbol_and_layout(scope, state);
@ -6064,8 +5945,7 @@ fn run_low_level<'a, 'ctx, 'env>(
set set
} }
ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListWalk | ListWalkUntil ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListSortWith | DictWalk => {
| ListWalkBackwards | ListSortWith | ListFindUnsafe | DictWalk => {
unreachable!("these are higher order, and are handled elsewhere") unreachable!("these are higher order, and are handled elsewhere")
} }

View file

@ -1,8 +1,5 @@
#![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_arguments)]
use crate::llvm::bitcode::{ use crate::llvm::bitcode::{build_dec_wrapper, call_list_bitcode_fn};
build_dec_wrapper, build_has_tag_id, build_inc_n_wrapper, build_inc_wrapper, call_bitcode_fn,
call_list_bitcode_fn, call_void_bitcode_fn,
};
use crate::llvm::build::{ use crate::llvm::build::{
allocate_with_refcount_help, cast_basic_basic, Env, RocFunctionCall, Scope, allocate_with_refcount_help, cast_basic_basic, Env, RocFunctionCall, Scope,
}; };
@ -122,29 +119,6 @@ pub fn list_with_capacity<'a, 'ctx, 'env>(
) )
} }
/// List.repeat : elem, Nat -> List elem
pub fn list_repeat<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
element: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
list_len: IntValue<'ctx>,
) -> BasicValueEnum<'ctx> {
let inc_element_fn = build_inc_n_wrapper(env, layout_ids, element_layout);
call_list_bitcode_fn(
env,
&[
list_len.into(),
env.alignment_intvalue(element_layout),
pass_element_as_opaque(env, element, *element_layout),
layout_width(env, element_layout),
inc_element_fn.as_global_value().as_pointer_value().into(),
],
bitcode::LIST_REPEAT,
)
}
pub fn list_get_unsafe<'a, 'ctx, 'env>( pub fn list_get_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
@ -370,133 +344,6 @@ pub fn list_len<'ctx>(
.into_int_value() .into_int_value()
} }
pub enum ListWalk {
Walk,
WalkBackwards,
WalkUntil,
WalkBackwardsUntil,
}
pub fn list_walk_generic<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
roc_function_call: RocFunctionCall<'ctx>,
function_call_return_layout: &Layout<'a>,
list: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
default: BasicValueEnum<'ctx>,
default_layout: &Layout<'a>,
variant: ListWalk,
) -> BasicValueEnum<'ctx> {
let builder = env.builder;
let zig_function = match variant {
ListWalk::Walk => bitcode::LIST_WALK,
ListWalk::WalkBackwards => bitcode::LIST_WALK_BACKWARDS,
ListWalk::WalkUntil => bitcode::LIST_WALK_UNTIL,
ListWalk::WalkBackwardsUntil => todo!(),
};
let default_ptr = if default_layout.is_passed_by_reference(env.target_info) {
debug_assert!(default.is_pointer_value());
default.into_pointer_value()
} else {
let default_ptr = builder.build_alloca(default.get_type(), "default_ptr");
env.builder.build_store(default_ptr, default);
default_ptr
};
let result_ptr = {
let basic_type = basic_type_from_layout(env, default_layout);
env.builder.build_alloca(basic_type, "result")
};
match variant {
ListWalk::Walk | ListWalk::WalkBackwards => {
call_void_bitcode_fn(
env,
&[
list_to_c_abi(env, list).into(),
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(),
pass_as_opaque(env, default_ptr),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
layout_width(env, default_layout),
pass_as_opaque(env, result_ptr),
],
zig_function,
);
}
ListWalk::WalkUntil | ListWalk::WalkBackwardsUntil => {
let function = env
.builder
.get_insert_block()
.unwrap()
.get_parent()
.unwrap();
let has_tag_id = match function_call_return_layout {
Layout::Union(union_layout) => build_has_tag_id(env, function, *union_layout),
_ => unreachable!(),
};
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
call_void_bitcode_fn(
env,
&[
list_to_c_abi(env, list).into(),
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(),
pass_as_opaque(env, default_ptr),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
layout_width(env, function_call_return_layout),
layout_width(env, default_layout),
has_tag_id_helper(env, has_tag_id).into(),
dec_element_fn.as_global_value().as_pointer_value().into(),
pass_as_opaque(env, result_ptr),
],
zig_function,
);
}
}
if default_layout.is_passed_by_reference(env.target_info) {
result_ptr.into()
} else {
env.builder.build_load(result_ptr, "load_result")
}
}
fn has_tag_id_helper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
has_tag_id: FunctionValue<'ctx>,
) -> PointerValue<'ctx> {
let u8_t = env.context.i8_type();
let u16_t = env.context.i16_type();
let u8_ptr_t = u8_t.ptr_type(AddressSpace::Generic);
let struct_t = env
.context
.struct_type(&[u8_t.into(), env.ptr_int().into()], false);
let has_tag_id_type = struct_t
.fn_type(&[u16_t.into(), u8_ptr_t.into()], false)
.ptr_type(AddressSpace::Generic);
env.builder.build_pointer_cast(
has_tag_id.as_global_value().as_pointer_value(),
has_tag_id_type,
"has_tag_id_cast",
)
}
/// List.sortWith : List a, (a, a -> Ordering) -> List a /// List.sortWith : List a, (a, a -> Ordering) -> List a
pub fn list_sort_with<'a, 'ctx, 'env>( pub fn list_sort_with<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
@ -704,144 +551,6 @@ pub fn list_concat<'a, 'ctx, 'env>(
) )
} }
/// List.any : List elem, \(elem -> Bool) -> Bool
pub fn list_any<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
roc_function_call: RocFunctionCall<'ctx>,
list: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
call_bitcode_fn(
env,
&[
list_to_c_abi(env, list).into(),
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(),
layout_width(env, element_layout),
],
bitcode::LIST_ANY,
)
}
/// List.all : List elem, \(elem -> Bool) -> Bool
pub fn list_all<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
roc_function_call: RocFunctionCall<'ctx>,
list: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
call_bitcode_fn(
env,
&[
list_to_c_abi(env, list).into(),
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(),
layout_width(env, element_layout),
],
bitcode::LIST_ALL,
)
}
/// 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,
&[
list_to_c_abi(env, list).into(),
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(),
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_int = env
.builder
.build_extract_value(result, 0, "get_value_ptr_int")
.unwrap()
.into_int_value();
let found_u8 = env
.builder
.build_extract_value(result, 1, "get_found")
.unwrap()
.into_int_value();
let found = env
.builder
.build_int_cast(found_u8, env.context.bool_type(), "found_as_bool");
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_int_to_ptr(
value_u8_ptr_int,
value_bt.ptr_type(AddressSpace::Generic),
"get_value_ptr",
);
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()
}
pub fn decrementing_elem_loop<'ctx, LoopFn>( pub fn decrementing_elem_loop<'ctx, LoopFn>(
builder: &Builder<'ctx>, builder: &Builder<'ctx>,
ctx: &'ctx Context, ctx: &'ctx Context,

View file

@ -1304,35 +1304,49 @@ impl<'a> WasmBackend<'a> {
storage: &StoredValue, storage: &StoredValue,
fields: &'a [Symbol], fields: &'a [Symbol],
) { ) {
if matches!(layout, Layout::Struct { .. }) { match layout {
match storage { Layout::Struct { .. } => {
StoredValue::StackMemory { location, size, .. } => { match storage {
if *size > 0 { StoredValue::StackMemory { location, size, .. } => {
let (local_id, struct_offset) = if *size > 0 {
location.local_and_offset(self.storage.stack_frame_pointer); let (local_id, struct_offset) =
let mut field_offset = struct_offset; location.local_and_offset(self.storage.stack_frame_pointer);
for field in fields.iter() { let mut field_offset = struct_offset;
field_offset += self.storage.copy_value_to_memory( for field in fields.iter() {
&mut self.code_builder, field_offset += self.storage.copy_value_to_memory(
local_id, &mut self.code_builder,
field_offset, local_id,
*field, field_offset,
); *field,
);
}
} else {
// Zero-size struct. No code to emit.
// These values are purely conceptual, they only exist internally in the compiler
} }
} else {
// Zero-size struct. No code to emit.
// These values are purely conceptual, they only exist internally in the compiler
} }
_ => {
internal_error!("Cannot create struct {:?} with storage {:?}", sym, storage)
}
};
}
Layout::LambdaSet(lambdaset) => {
self.expr_struct(sym, &lambdaset.runtime_representation(), storage, fields)
}
_ => {
if !fields.is_empty() {
// Struct expression but not Struct layout => single element. Copy it.
let field_storage = self.storage.get(&fields[0]).to_owned();
self.storage.clone_value(
&mut self.code_builder,
storage,
&field_storage,
fields[0],
);
} else {
// Empty record. Nothing to do.
} }
_ => internal_error!("Cannot create struct {:?} with storage {:?}", sym, storage), }
};
} else if !fields.is_empty() {
// Struct expression but not Struct layout => single element. Copy it.
let field_storage = self.storage.get(&fields[0]).to_owned();
self.storage
.clone_value(&mut self.code_builder, storage, &field_storage, fields[0]);
} else {
// Empty record. Nothing to do.
} }
} }

View file

@ -289,8 +289,8 @@ impl<'a> LowLevelCall<'a> {
ListIsUnique => self.load_args_and_call_zig(backend, bitcode::LIST_IS_UNIQUE), ListIsUnique => self.load_args_and_call_zig(backend, bitcode::LIST_IS_UNIQUE),
ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListWalk ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListSortWith
| ListWalkUntil | ListWalkBackwards | ListSortWith | ListFindUnsafe | DictWalk => { | DictWalk => {
internal_error!("HigherOrder lowlevels should not be handled here") internal_error!("HigherOrder lowlevels should not be handled here")
} }
@ -2061,15 +2061,7 @@ pub fn call_higher_order_lowlevel<'a>(
*owns_captured_environment, *owns_captured_environment,
), ),
ListMapWithIndex { .. } ListMapWithIndex { .. } | ListSortWith { .. } | DictWalk { .. } => todo!("{:?}", op),
| ListWalk { .. }
| ListWalkUntil { .. }
| ListWalkBackwards { .. }
| ListSortWith { .. }
| ListAny { .. }
| ListAll { .. }
| ListFindUnsafe { .. }
| DictWalk { .. } => todo!("{:?}", op),
} }
} }

View file

@ -3,11 +3,12 @@ use roc_std::{RocDec, RocList, RocOrder, RocStr};
pub trait Wasm32Sized: Sized { pub trait Wasm32Sized: Sized {
const SIZE_OF_WASM: usize; const SIZE_OF_WASM: usize;
const ALIGN_OF_WASM: usize; const ALIGN_OF_WASM: usize;
const ACTUAL_WIDTH: usize = if (Self::SIZE_OF_WASM % Self::ALIGN_OF_WASM) == 0 { const ACTUAL_WIDTH: usize =
Self::SIZE_OF_WASM if (Self::ALIGN_OF_WASM == 0) || (Self::SIZE_OF_WASM % Self::ALIGN_OF_WASM) == 0 {
} else { Self::SIZE_OF_WASM
Self::SIZE_OF_WASM + (Self::ALIGN_OF_WASM - (Self::SIZE_OF_WASM % Self::ALIGN_OF_WASM)) } else {
}; Self::SIZE_OF_WASM + (Self::ALIGN_OF_WASM - (Self::SIZE_OF_WASM % Self::ALIGN_OF_WASM))
};
} }
macro_rules! wasm32_sized_primitive { macro_rules! wasm32_sized_primitive {

View file

@ -36,14 +36,10 @@ pub enum LowLevel {
ListMap3, ListMap3,
ListMap4, ListMap4,
ListMapWithIndex, ListMapWithIndex,
ListWalk,
ListWalkUntil,
ListWalkBackwards,
ListSortWith, ListSortWith,
ListSublist, ListSublist,
ListDropAt, ListDropAt,
ListSwap, ListSwap,
ListFindUnsafe,
ListIsUnique, ListIsUnique,
DictSize, DictSize,
DictEmpty, DictEmpty,
@ -124,17 +120,7 @@ pub enum LowLevel {
macro_rules! higher_order { macro_rules! higher_order {
() => { () => {
ListMap ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListSortWith | DictWalk
| ListMap2
| ListMap3
| ListMap4
| ListMapWithIndex
| ListWalk
| ListWalkUntil
| ListWalkBackwards
| ListSortWith
| ListFindUnsafe
| DictWalk
}; };
} }
@ -156,11 +142,7 @@ impl LowLevel {
ListMap3 => 3, ListMap3 => 3,
ListMap4 => 4, ListMap4 => 4,
ListMapWithIndex => 1, ListMapWithIndex => 1,
ListWalk => 2,
ListWalkUntil => 2,
ListWalkBackwards => 2,
ListSortWith => 1, ListSortWith => 1,
ListFindUnsafe => 1,
DictWalk => 2, DictWalk => 2,
_ => unreachable!(), _ => unreachable!(),
} }
@ -225,9 +207,6 @@ impl LowLevelWrapperType {
Symbol::LIST_MAP3 => WrapperIsRequired, Symbol::LIST_MAP3 => WrapperIsRequired,
Symbol::LIST_MAP4 => WrapperIsRequired, Symbol::LIST_MAP4 => WrapperIsRequired,
Symbol::LIST_MAP_WITH_INDEX => WrapperIsRequired, Symbol::LIST_MAP_WITH_INDEX => WrapperIsRequired,
Symbol::LIST_WALK => WrapperIsRequired,
Symbol::LIST_WALK_UNTIL => WrapperIsRequired,
Symbol::LIST_WALK_BACKWARDS => WrapperIsRequired,
Symbol::LIST_SORT_WITH => WrapperIsRequired, Symbol::LIST_SORT_WITH => WrapperIsRequired,
Symbol::LIST_SUBLIST => WrapperIsRequired, Symbol::LIST_SUBLIST => WrapperIsRequired,
Symbol::LIST_DROP_AT => CanBeReplacedBy(ListDropAt), Symbol::LIST_DROP_AT => CanBeReplacedBy(ListDropAt),

View file

@ -552,7 +552,7 @@ impl<'a> BorrowInfState<'a> {
}; };
match op { match op {
ListMap { xs } | ListAny { xs } | ListAll { xs } | ListFindUnsafe { xs } => { ListMap { xs } => {
// own the list if the function wants to own the element // own the list if the function wants to own the element
if !function_ps[0].borrow { if !function_ps[0].borrow {
self.own_var(*xs); self.own_var(*xs);
@ -606,10 +606,7 @@ impl<'a> BorrowInfState<'a> {
// always own the input list // always own the input list
self.own_var(*xs); self.own_var(*xs);
} }
ListWalk { xs, state } DictWalk { xs, state } => {
| ListWalkUntil { xs, state }
| ListWalkBackwards { xs, state }
| DictWalk { xs, state } => {
// own the default value if the function wants to own it // own the default value if the function wants to own it
if !function_ps[0].borrow { if !function_ps[0].borrow {
self.own_var(*state); self.own_var(*state);
@ -909,11 +906,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
ListMap2 => arena.alloc_slice_copy(&[owned, owned, function, closure_data]), ListMap2 => arena.alloc_slice_copy(&[owned, owned, function, closure_data]),
ListMap3 => arena.alloc_slice_copy(&[owned, owned, owned, function, closure_data]), ListMap3 => arena.alloc_slice_copy(&[owned, owned, owned, function, closure_data]),
ListMap4 => arena.alloc_slice_copy(&[owned, owned, owned, owned, function, closure_data]), ListMap4 => arena.alloc_slice_copy(&[owned, owned, owned, owned, function, closure_data]),
ListWalk | ListWalkUntil | ListWalkBackwards => {
arena.alloc_slice_copy(&[owned, owned, function, closure_data])
}
ListSortWith => arena.alloc_slice_copy(&[owned, function, closure_data]), ListSortWith => arena.alloc_slice_copy(&[owned, function, closure_data]),
ListFindUnsafe => arena.alloc_slice_copy(&[owned, function, closure_data]),
// TODO when we have lists with capacity (if ever) // TODO when we have lists with capacity (if ever)
// List.append should own its first argument // List.append should own its first argument

View file

@ -693,7 +693,7 @@ impl<'a> Context<'a> {
let after_arguments = &arguments[op.function_index()..]; let after_arguments = &arguments[op.function_index()..];
match *op { match *op {
ListMap { xs } | ListAny { xs } | ListAll { xs } | ListFindUnsafe { xs } => { ListMap { xs } => {
let ownerships = [(xs, function_ps[0])]; let ownerships = [(xs, function_ps[0])];
let b = self.add_dec_after_lowlevel(after_arguments, &borrows, b, b_live_vars); let b = self.add_dec_after_lowlevel(after_arguments, &borrows, b, b_live_vars);
@ -820,10 +820,7 @@ impl<'a> Context<'a> {
handle_ownerships_pre!(Stmt::Let(z, v, l, b), ownerships) handle_ownerships_pre!(Stmt::Let(z, v, l, b), ownerships)
} }
ListWalk { xs, state: _ } DictWalk { xs, state: _ } => {
| ListWalkUntil { xs, state: _ }
| ListWalkBackwards { xs, state: _ }
| DictWalk { xs, state: _ } => {
let ownerships = [ let ownerships = [
// borrow data structure based on second argument of the folded function // borrow data structure based on second argument of the folded function
(xs, function_ps[1]), (xs, function_ps[1]),

View file

@ -5048,9 +5048,6 @@ pub fn with_hole<'a>(
let xs = arg_symbols[0]; let xs = arg_symbols[0];
match_on_closure_argument!(ListSortWith, [xs]) match_on_closure_argument!(ListSortWith, [xs])
} }
ListWalk => walk!(ListWalk),
ListWalkUntil => walk!(ListWalkUntil),
ListWalkBackwards => walk!(ListWalkBackwards),
DictWalk => walk!(DictWalk), DictWalk => walk!(DictWalk),
ListMap2 => { ListMap2 => {
debug_assert_eq!(arg_symbols.len(), 3); debug_assert_eq!(arg_symbols.len(), 3);
@ -5079,11 +5076,6 @@ pub fn with_hole<'a>(
match_on_closure_argument!(ListMap4, [xs, ys, zs, ws]) match_on_closure_argument!(ListMap4, [xs, ys, zs, ws])
} }
ListFindUnsafe => {
debug_assert_eq!(arg_symbols.len(), 2);
let xs = arg_symbols[0];
match_on_closure_argument!(ListFindUnsafe, [xs])
}
BoxExpr => { BoxExpr => {
debug_assert_eq!(arg_symbols.len(), 1); debug_assert_eq!(arg_symbols.len(), 1);
let x = arg_symbols[0]; let x = arg_symbols[0];

View file

@ -23,30 +23,9 @@ pub enum HigherOrder {
ListMapWithIndex { ListMapWithIndex {
xs: Symbol, xs: Symbol,
}, },
ListWalk {
xs: Symbol,
state: Symbol,
},
ListWalkUntil {
xs: Symbol,
state: Symbol,
},
ListWalkBackwards {
xs: Symbol,
state: Symbol,
},
ListSortWith { ListSortWith {
xs: Symbol, xs: Symbol,
}, },
ListAny {
xs: Symbol,
},
ListAll {
xs: Symbol,
},
ListFindUnsafe {
xs: Symbol,
},
DictWalk { DictWalk {
xs: Symbol, xs: Symbol,
state: Symbol, state: Symbol,
@ -61,14 +40,8 @@ impl HigherOrder {
HigherOrder::ListMap3 { .. } => 3, HigherOrder::ListMap3 { .. } => 3,
HigherOrder::ListMap4 { .. } => 4, HigherOrder::ListMap4 { .. } => 4,
HigherOrder::ListMapWithIndex { .. } => 2, HigherOrder::ListMapWithIndex { .. } => 2,
HigherOrder::ListWalk { .. } => 2,
HigherOrder::ListWalkUntil { .. } => 2,
HigherOrder::ListWalkBackwards { .. } => 2,
HigherOrder::ListSortWith { .. } => 2, HigherOrder::ListSortWith { .. } => 2,
HigherOrder::ListFindUnsafe { .. } => 1,
HigherOrder::DictWalk { .. } => 2, HigherOrder::DictWalk { .. } => 2,
HigherOrder::ListAny { .. } => 1,
HigherOrder::ListAll { .. } => 1,
} }
} }
@ -78,18 +51,11 @@ impl HigherOrder {
use HigherOrder::*; use HigherOrder::*;
match self { match self {
ListMap { .. } ListMap { .. } | ListMapWithIndex { .. } | ListSortWith { .. } => 2,
| ListMapWithIndex { .. }
| ListSortWith { .. }
| ListAny { .. }
| ListAll { .. }
| ListFindUnsafe { .. } => 2,
ListMap2 { .. } => 3, ListMap2 { .. } => 3,
ListMap3 { .. } => 4, ListMap3 { .. } => 4,
ListMap4 { .. } => 5, ListMap4 { .. } => 5,
ListWalk { .. } | ListWalkUntil { .. } | ListWalkBackwards { .. } | DictWalk { .. } => { DictWalk { .. } => 3,
3
}
} }
} }

View file

@ -32,7 +32,7 @@ fn empty_list_literal() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_literal_empty_record() { fn list_literal_empty_record() {
assert_evals_to!("[{}]", RocList::from_slice(&[()]), RocList<()>); assert_evals_to!("[{}]", RocList::from_slice(&[()]), RocList<()>);
} }
@ -168,7 +168,7 @@ fn list_append() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_take_first() { fn list_take_first() {
assert_evals_to!( assert_evals_to!(
"List.takeFirst [1, 2, 3] 2", "List.takeFirst [1, 2, 3] 2",
@ -193,7 +193,7 @@ fn list_take_first() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_take_last() { fn list_take_last() {
assert_evals_to!( assert_evals_to!(
"List.takeLast [1, 2, 3] 2", "List.takeLast [1, 2, 3] 2",
@ -258,7 +258,7 @@ fn list_sublist() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_split() { fn list_split() {
assert_evals_to!( assert_evals_to!(
r#" r#"
@ -691,7 +691,7 @@ fn list_prepend_big_list() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_backwards_empty_all_inline() { fn list_walk_backwards_empty_all_inline() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -719,7 +719,7 @@ fn list_walk_backwards_empty_all_inline() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_backwards_with_str() { fn list_walk_backwards_with_str() {
assert_evals_to!( assert_evals_to!(
r#"List.walkBackwards ["x", "y", "z"] "<" Str.concat"#, r#"List.walkBackwards ["x", "y", "z"] "<" Str.concat"#,
@ -735,7 +735,7 @@ fn list_walk_backwards_with_str() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_backwards_with_record() { fn list_walk_backwards_with_record() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -763,7 +763,7 @@ fn list_walk_backwards_with_record() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_with_str() { fn list_walk_with_str() {
assert_evals_to!( assert_evals_to!(
r#"List.walk ["x", "y", "z"] "<" Str.concat"#, r#"List.walk ["x", "y", "z"] "<" Str.concat"#,
@ -779,13 +779,13 @@ fn list_walk_with_str() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_subtraction() { fn list_walk_subtraction() {
assert_evals_to!(r#"List.walk [1, 2] 1 Num.sub"#, (1 - 1) - 2, i64); assert_evals_to!(r#"List.walk [1, 2] 1 Num.sub"#, (1 - 1) - 2, i64);
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_until_sum() { fn list_walk_until_sum() {
assert_evals_to!( assert_evals_to!(
r#"List.walkUntil [1, 2] 0 \a,b -> Continue (a + b)"#, r#"List.walkUntil [1, 2] 0 \a,b -> Continue (a + b)"#,
@ -823,7 +823,7 @@ fn list_walk_implements_position() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_walk_until_even_prefix_sum() { fn list_walk_until_even_prefix_sum() {
assert_evals_to!( assert_evals_to!(
r#" r#"
@ -1079,7 +1079,7 @@ fn list_map_all_inline() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_map_closure() { fn list_map_closure() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -1197,7 +1197,7 @@ fn list_map2_different_lengths() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_join_empty_list() { fn list_join_empty_list() {
assert_evals_to!( assert_evals_to!(
"List.join []", "List.join []",
@ -1207,7 +1207,7 @@ fn list_join_empty_list() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_join_one_list() { fn list_join_one_list() {
assert_evals_to!( assert_evals_to!(
"List.join [[1, 2, 3]]", "List.join [[1, 2, 3]]",
@ -1217,7 +1217,7 @@ fn list_join_one_list() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_join_two_non_empty_lists() { fn list_join_two_non_empty_lists() {
assert_evals_to!( assert_evals_to!(
"List.join [[1, 2, 3] , [4 ,5, 6]]", "List.join [[1, 2, 3] , [4 ,5, 6]]",
@ -1227,7 +1227,7 @@ fn list_join_two_non_empty_lists() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_join_two_non_empty_lists_of_float() { fn list_join_two_non_empty_lists_of_float() {
assert_evals_to!( assert_evals_to!(
"List.join [[1.2, 1.1], [2.1, 2.2]]", "List.join [[1.2, 1.1], [2.1, 2.2]]",
@ -1237,7 +1237,7 @@ fn list_join_two_non_empty_lists_of_float() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_join_to_big_list() { fn list_join_to_big_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -1263,7 +1263,7 @@ fn list_join_to_big_list() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_join_defined_empty_list() { fn list_join_defined_empty_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -1281,7 +1281,7 @@ fn list_join_defined_empty_list() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_join_all_empty_lists() { fn list_join_all_empty_lists() {
assert_evals_to!( assert_evals_to!(
"List.join [[], [], []]", "List.join [[], [], []]",
@ -1291,7 +1291,7 @@ fn list_join_all_empty_lists() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_join_one_empty_list() { fn list_join_one_empty_list() {
assert_evals_to!( assert_evals_to!(
"List.join [[1.2, 1.1], []]", "List.join [[1.2, 1.1], []]",
@ -2000,7 +2000,7 @@ fn gen_wrap_len() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn gen_wrap_first() { fn gen_wrap_first() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -2381,7 +2381,7 @@ fn list_wrap_in_tag() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_contains_int() { fn list_contains_int() {
assert_evals_to!(indoc!("List.contains [1,2,3] 1"), true, bool); assert_evals_to!(indoc!("List.contains [1,2,3] 1"), true, bool);
@ -2391,7 +2391,7 @@ fn list_contains_int() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_contains_str() { fn list_contains_str() {
assert_evals_to!(indoc!(r#"List.contains ["foo", "bar"] "bar""#), true, bool); assert_evals_to!(indoc!(r#"List.contains ["foo", "bar"] "bar""#), true, bool);
@ -2426,7 +2426,7 @@ fn list_manual_range() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_min() { fn list_min() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -2453,7 +2453,7 @@ fn list_min() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_max() { fn list_max() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -2480,7 +2480,7 @@ fn list_max() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_sum() { fn list_sum() {
assert_evals_to!("List.sum []", 0, i64); assert_evals_to!("List.sum []", 0, i64);
assert_evals_to!("List.sum [1, 2, 3]", 6, i64); assert_evals_to!("List.sum [1, 2, 3]", 6, i64);
@ -2488,7 +2488,7 @@ fn list_sum() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_product() { fn list_product() {
assert_evals_to!("List.product []", 1, i64); assert_evals_to!("List.product []", 1, i64);
assert_evals_to!("List.product [1, 2, 3]", 6, i64); assert_evals_to!("List.product [1, 2, 3]", 6, i64);
@ -2663,7 +2663,7 @@ fn list_sort_desc() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_any() { fn list_any() {
assert_evals_to!("List.any [] (\\e -> e > 3)", false, bool); assert_evals_to!("List.any [] (\\e -> e > 3)", false, bool);
assert_evals_to!("List.any [1, 2, 3] (\\e -> e > 3)", false, bool); assert_evals_to!("List.any [1, 2, 3] (\\e -> e > 3)", false, bool);
@ -2687,7 +2687,7 @@ fn list_any_empty_with_unknown_element_type() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_all() { fn list_all() {
assert_evals_to!("List.all [] (\\e -> e > 3)", true, bool); assert_evals_to!("List.all [] (\\e -> e > 3)", true, bool);
assert_evals_to!("List.all [1, 2, 3] (\\e -> e > 3)", false, bool); assert_evals_to!("List.all [1, 2, 3] (\\e -> e > 3)", false, bool);
@ -2811,7 +2811,7 @@ fn list_join_map_empty() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_find() { fn list_find() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -2827,7 +2827,7 @@ fn list_find() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_find_not_found() { fn list_find_not_found() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -2843,7 +2843,7 @@ fn list_find_not_found() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_find_empty_typed_list() { fn list_find_empty_typed_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -2859,7 +2859,7 @@ fn list_find_empty_typed_list() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[ignore = "Fails because monomorphization can't be done if we don't have a concrete element type!"] #[ignore = "Fails because monomorphization can't be done if we don't have a concrete element type!"]
fn list_find_empty_layout() { fn list_find_empty_layout() {
assert_evals_to!( assert_evals_to!(

View file

@ -1,17 +0,0 @@
procedure Test.2 (Test.6, #Attr.12):
let Test.1 : U8 = StructAtIndex 0 #Attr.12;
let Test.11 : {U8} = Struct {Test.1};
ret Test.11;
procedure Test.4 (Test.5, #Attr.12):
let Test.1 : U8 = StructAtIndex 0 #Attr.12;
ret Test.1;
procedure Test.0 ():
let Test.1 : U8 = 1i64;
let Test.8 : {} = Struct {};
let Test.10 : {} = Struct {};
let Test.14 : {U8} = Struct {Test.1};
let Test.9 : {U8} = CallByName Test.2 Test.10 Test.14;
let Test.7 : U8 = CallByName Test.4 Test.8 Test.9;
ret Test.7;

View file

@ -1,6 +1,6 @@
procedure List.6 (#Attr.2): procedure List.6 (#Attr.2):
let List.259 : U64 = lowlevel ListLen #Attr.2; let List.284 : U64 = lowlevel ListLen #Attr.2;
ret List.259; ret List.284;
procedure Test.1 (Test.5): procedure Test.1 (Test.5):
let Test.2 : I64 = 41i64; let Test.2 : I64 = 41i64;

View file

@ -1,22 +1,22 @@
procedure List.2 (List.73, List.74): procedure List.2 (List.75, List.76):
let List.265 : U64 = CallByName List.6 List.73; let List.290 : U64 = CallByName List.6 List.75;
let List.261 : Int1 = CallByName Num.22 List.74 List.265; let List.286 : Int1 = CallByName Num.22 List.76 List.290;
if List.261 then if List.286 then
let List.263 : {} = CallByName List.60 List.73 List.74; let List.288 : {} = CallByName List.60 List.75 List.76;
let List.262 : [C {}, C {}] = Ok List.263; let List.287 : [C {}, C {}] = Ok List.288;
ret List.262; ret List.287;
else else
let List.260 : {} = Struct {}; let List.285 : {} = Struct {};
let List.259 : [C {}, C {}] = Err List.260; let List.284 : [C {}, C {}] = Err List.285;
ret List.259; ret List.284;
procedure List.6 (#Attr.2): procedure List.6 (#Attr.2):
let List.268 : U64 = lowlevel ListLen #Attr.2; let List.293 : U64 = lowlevel ListLen #Attr.2;
ret List.268; ret List.293;
procedure List.60 (#Attr.2, #Attr.3): procedure List.60 (#Attr.2, #Attr.3):
let List.267 : {} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; let List.292 : {} = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.267; ret List.292;
procedure Num.22 (#Attr.2, #Attr.3): procedure Num.22 (#Attr.2, #Attr.3):
let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View file

@ -1,6 +1,6 @@
procedure List.4 (#Attr.2, #Attr.3): procedure List.4 (#Attr.2, #Attr.3):
let List.259 : List U8 = lowlevel ListAppend #Attr.2 #Attr.3; let List.284 : List U8 = lowlevel ListAppend #Attr.2 #Attr.3;
ret List.259; ret List.284;
procedure Test.20 (Test.22): procedure Test.20 (Test.22):
let Test.34 : {U8} = Struct {Test.22}; let Test.34 : {U8} = Struct {Test.22};

View file

@ -1,104 +0,0 @@
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.107 : List U8 = CallByName Test.3 Encode.94 Encode.96;
ret Encode.107;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.114 : List U8 = CallByName Json.65 Encode.94 Encode.96 Encode.102;
ret Encode.114;
procedure Encode.25 (Encode.100, Encode.101):
let Encode.104 : List U8 = Array [];
let Encode.105 : {} = CallByName Test.2 Encode.100;
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
ret Encode.103;
procedure Json.1 ():
let Json.102 : {} = Struct {};
ret Json.102;
procedure Json.17 (Json.64):
let Json.104 : {Str} = Struct {Json.64};
let Json.103 : {Str} = CallByName Encode.22 Json.104;
ret Json.103;
procedure Json.65 (Json.66, Json.105, #Attr.12):
let Json.64 : Str = StructAtIndex 0 #Attr.12;
inc Json.64;
dec #Attr.12;
let Json.114 : I32 = 34i64;
let Json.113 : U8 = CallByName Num.122 Json.114;
let Json.111 : List U8 = CallByName List.4 Json.66 Json.113;
let Json.112 : List U8 = CallByName Str.12 Json.64;
let Json.108 : List U8 = CallByName List.8 Json.111 Json.112;
let Json.110 : I32 = 34i64;
let Json.109 : U8 = CallByName Num.122 Json.110;
let Json.107 : List U8 = CallByName List.4 Json.108 Json.109;
ret Json.107;
procedure List.4 (#Attr.2, #Attr.3):
let List.141 : List U8 = lowlevel ListAppend #Attr.2 #Attr.3;
ret List.141;
procedure List.8 (#Attr.2, #Attr.3):
let List.142 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
ret List.142;
procedure Num.122 (#Attr.2):
let Num.272 : U8 = lowlevel NumIntCast #Attr.2;
ret Num.272;
procedure Str.12 (#Attr.2):
let Str.73 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.73;
procedure Str.9 (#Attr.2):
let #Attr.3 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
let Str.69 : Int1 = StructAtIndex 2 #Attr.3;
if Str.69 then
let Str.71 : Str = StructAtIndex 1 #Attr.3;
inc Str.71;
dec #Attr.3;
let Str.70 : [C {U64, U8}, C Str] = Ok Str.71;
ret Str.70;
else
let Str.67 : U8 = StructAtIndex 3 #Attr.3;
let Str.68 : U64 = StructAtIndex 0 #Attr.3;
dec #Attr.3;
let Str.66 : {U64, U8} = Struct {Str.68, Str.67};
let Str.65 : [C {U64, U8}, C Str] = Err Str.66;
ret Str.65;
procedure Test.2 (Test.8):
let Test.18 : {} = Struct {};
let Test.17 : {} = CallByName Encode.22 Test.18;
ret Test.17;
procedure Test.3 (Test.4, Test.5):
let Test.21 : Str = "Hello, World!\n";
let Test.20 : {Str} = CallByName Json.17 Test.21;
let Test.19 : List U8 = CallByName Encode.23 Test.4 Test.20 Test.5;
ret Test.19;
procedure Test.0 ():
let Test.15 : {} = Struct {};
let Test.16 : {} = CallByName Json.1;
let Test.14 : List U8 = CallByName Encode.25 Test.15 Test.16;
let Test.6 : [C {U64, U8}, C Str] = CallByName Str.9 Test.14;
let Test.11 : U8 = 1i64;
let Test.12 : U8 = GetTagId Test.6;
let Test.13 : Int1 = lowlevel Eq Test.11 Test.12;
if Test.13 then
let Test.7 : Str = UnionAtIndex (Id 1) (Index 0) Test.6;
inc Test.7;
dec Test.6;
ret Test.7;
else
dec Test.6;
let Test.10 : Str = "<bad>";
ret Test.10;

View file

@ -1,30 +0,0 @@
procedure Test.4 (Test.30):
joinpoint Test.14 Test.5:
let Test.24 : Int1 = 1i64;
let Test.25 : Int1 = GetTagId Test.5;
let Test.26 : Int1 = lowlevel Eq Test.24 Test.25;
if Test.26 then
let Test.15 : Int1 = false;
ret Test.15;
else
let Test.20 : [C I64, C ] = UnionAtIndex (Id 0) (Index 0) Test.5;
let Test.21 : U8 = 1i64;
let Test.22 : U8 = GetTagId Test.20;
let Test.23 : Int1 = lowlevel Eq Test.21 Test.22;
if Test.23 then
let Test.16 : Int1 = true;
ret Test.16;
else
let Test.8 : [<rnu><null>, C [C I64, C ] *self] = UnionAtIndex (Id 0) (Index 1) Test.5;
jump Test.14 Test.8;
in
jump Test.14 Test.30;
procedure Test.0 ():
let Test.29 : I64 = 3i64;
let Test.27 : [C I64, C ] = Just Test.29;
let Test.28 : [<rnu><null>, C [C I64, C ] *self] = Nil ;
let Test.13 : [<rnu><null>, C [C I64, C ] *self] = Cons Test.27 Test.28;
let Test.12 : Int1 = CallByName Test.4 Test.13;
dec Test.13;
ret Test.12;

View file

@ -1,6 +1,6 @@
procedure List.6 (#Attr.2): procedure List.6 (#Attr.2):
let List.259 : U64 = lowlevel ListLen #Attr.2; let List.284 : U64 = lowlevel ListLen #Attr.2;
ret List.259; ret List.284;
procedure Num.19 (#Attr.2, #Attr.3): procedure Num.19 (#Attr.2, #Attr.3):
let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;

View file

@ -1,37 +1,37 @@
procedure List.2 (List.73, List.74): procedure List.2 (List.75, List.76):
let List.274 : U64 = CallByName List.6 List.73; let List.299 : U64 = CallByName List.6 List.75;
let List.270 : Int1 = CallByName Num.22 List.74 List.274; let List.295 : Int1 = CallByName Num.22 List.76 List.299;
if List.270 then if List.295 then
let List.272 : I64 = CallByName List.60 List.73 List.74; let List.297 : I64 = CallByName List.60 List.75 List.76;
let List.271 : [C {}, C I64] = Ok List.272; let List.296 : [C {}, C I64] = Ok List.297;
ret List.271; ret List.296;
else else
let List.269 : {} = Struct {}; let List.294 : {} = Struct {};
let List.268 : [C {}, C I64] = Err List.269; let List.293 : [C {}, C I64] = Err List.294;
ret List.268; ret List.293;
procedure List.6 (#Attr.2): procedure List.6 (#Attr.2):
let List.275 : U64 = lowlevel ListLen #Attr.2; let List.300 : U64 = lowlevel ListLen #Attr.2;
ret List.275; ret List.300;
procedure List.60 (#Attr.2, #Attr.3): procedure List.60 (#Attr.2, #Attr.3):
let List.273 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; let List.298 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.273; ret List.298;
procedure List.9 (List.184): procedure List.9 (List.202):
let List.266 : U64 = 0i64; let List.291 : U64 = 0i64;
let List.259 : [C {}, C I64] = CallByName List.2 List.184 List.266; let List.284 : [C {}, C I64] = CallByName List.2 List.202 List.291;
let List.263 : U8 = 1i64; let List.288 : U8 = 1i64;
let List.264 : U8 = GetTagId List.259; let List.289 : U8 = GetTagId List.284;
let List.265 : Int1 = lowlevel Eq List.263 List.264; let List.290 : Int1 = lowlevel Eq List.288 List.289;
if List.265 then if List.290 then
let List.185 : I64 = UnionAtIndex (Id 1) (Index 0) List.259; let List.203 : I64 = UnionAtIndex (Id 1) (Index 0) List.284;
let List.260 : [C Int1, C I64] = Ok List.185; let List.285 : [C Int1, C I64] = Ok List.203;
ret List.260; ret List.285;
else else
let List.262 : Int1 = true; let List.287 : Int1 = true;
let List.261 : [C Int1, C I64] = Err List.262; let List.286 : [C Int1, C I64] = Err List.287;
ret List.261; ret List.286;
procedure Num.22 (#Attr.2, #Attr.3): procedure Num.22 (#Attr.2, #Attr.3):
let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View file

@ -1,25 +0,0 @@
procedure Num.19 (#Attr.2, #Attr.3):
let Num.274 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
ret Num.274;
procedure Test.4 (Test.6):
let Test.16 : Int1 = 1i64;
let Test.17 : Int1 = GetTagId Test.6;
let Test.18 : Int1 = lowlevel Eq Test.16 Test.17;
if Test.18 then
let Test.12 : I64 = 0i64;
ret Test.12;
else
let Test.7 : [<rnu><null>, C I64 *self] = UnionAtIndex (Id 0) (Index 1) Test.6;
let Test.14 : I64 = 1i64;
let Test.15 : I64 = CallByName Test.4 Test.7;
let Test.13 : I64 = CallByName Num.19 Test.14 Test.15;
ret Test.13;
procedure Test.0 ():
let Test.3 : [<rnu><null>, C I64 *self] = Nil ;
let Test.9 : I64 = CallByName Test.4 Test.3;
let Test.10 : I64 = CallByName Test.4 Test.3;
dec Test.3;
let Test.8 : I64 = CallByName Num.19 Test.9 Test.10;
ret Test.8;

View file

@ -1,6 +1,6 @@
procedure List.4 (#Attr.2, #Attr.3): procedure List.4 (#Attr.2, #Attr.3):
let List.259 : List I64 = lowlevel ListAppend #Attr.2 #Attr.3; let List.284 : List I64 = lowlevel ListAppend #Attr.2 #Attr.3;
ret List.259; ret List.284;
procedure Test.0 (): procedure Test.0 ():
let Test.2 : List I64 = Array [1i64]; let Test.2 : List I64 = Array [1i64];

View file

@ -1,6 +1,6 @@
procedure List.4 (#Attr.2, #Attr.3): procedure List.4 (#Attr.2, #Attr.3):
let List.259 : List I64 = lowlevel ListAppend #Attr.2 #Attr.3; let List.284 : List I64 = lowlevel ListAppend #Attr.2 #Attr.3;
ret List.259; ret List.284;
procedure Test.1 (Test.2): procedure Test.1 (Test.2):
let Test.6 : I64 = 42i64; let Test.6 : I64 = 42i64;

View file

@ -1,27 +1,27 @@
procedure List.3 (List.82, List.83, List.84): procedure List.3 (List.84, List.85, List.86):
let List.262 : {List I64, I64} = CallByName List.57 List.82 List.83 List.84; let List.287 : {List I64, I64} = CallByName List.57 List.84 List.85 List.86;
let List.261 : List I64 = StructAtIndex 0 List.262; let List.286 : List I64 = StructAtIndex 0 List.287;
inc List.261; inc List.286;
dec List.262; dec List.287;
ret List.261; ret List.286;
procedure List.57 (List.79, List.80, List.81): procedure List.57 (List.81, List.82, List.83):
let List.268 : U64 = CallByName List.6 List.79; let List.293 : U64 = CallByName List.6 List.81;
let List.265 : Int1 = CallByName Num.22 List.80 List.268; let List.290 : Int1 = CallByName Num.22 List.82 List.293;
if List.265 then if List.290 then
let List.266 : {List I64, I64} = CallByName List.61 List.79 List.80 List.81; let List.291 : {List I64, I64} = CallByName List.61 List.81 List.82 List.83;
ret List.266; ret List.291;
else else
let List.264 : {List I64, I64} = Struct {List.79, List.81}; let List.289 : {List I64, I64} = Struct {List.81, List.83};
ret List.264; ret List.289;
procedure List.6 (#Attr.2): procedure List.6 (#Attr.2):
let List.260 : U64 = lowlevel ListLen #Attr.2; let List.285 : U64 = lowlevel ListLen #Attr.2;
ret List.260; ret List.285;
procedure List.61 (#Attr.2, #Attr.3, #Attr.4): procedure List.61 (#Attr.2, #Attr.3, #Attr.4):
let List.267 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; let List.292 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.267; ret List.292;
procedure Num.19 (#Attr.2, #Attr.3): procedure Num.19 (#Attr.2, #Attr.3):
let Num.273 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; let Num.273 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;

View file

@ -1,22 +1,22 @@
procedure List.2 (List.73, List.74): procedure List.2 (List.75, List.76):
let List.265 : U64 = CallByName List.6 List.73; let List.290 : U64 = CallByName List.6 List.75;
let List.261 : Int1 = CallByName Num.22 List.74 List.265; let List.286 : Int1 = CallByName Num.22 List.76 List.290;
if List.261 then if List.286 then
let List.263 : I64 = CallByName List.60 List.73 List.74; let List.288 : I64 = CallByName List.60 List.75 List.76;
let List.262 : [C {}, C I64] = Ok List.263; let List.287 : [C {}, C I64] = Ok List.288;
ret List.262; ret List.287;
else else
let List.260 : {} = Struct {}; let List.285 : {} = Struct {};
let List.259 : [C {}, C I64] = Err List.260; let List.284 : [C {}, C I64] = Err List.285;
ret List.259; ret List.284;
procedure List.6 (#Attr.2): procedure List.6 (#Attr.2):
let List.268 : U64 = lowlevel ListLen #Attr.2; let List.293 : U64 = lowlevel ListLen #Attr.2;
ret List.268; ret List.293;
procedure List.60 (#Attr.2, #Attr.3): procedure List.60 (#Attr.2, #Attr.3):
let List.267 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; let List.292 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.267; ret List.292;
procedure Num.22 (#Attr.2, #Attr.3): procedure Num.22 (#Attr.2, #Attr.3):
let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View file

@ -1,10 +1,10 @@
procedure List.6 (#Attr.2): procedure List.6 (#Attr.2):
let List.259 : U64 = lowlevel ListLen #Attr.2; let List.284 : U64 = lowlevel ListLen #Attr.2;
ret List.259; ret List.284;
procedure List.6 (#Attr.2): procedure List.6 (#Attr.2):
let List.260 : U64 = lowlevel ListLen #Attr.2; let List.285 : U64 = lowlevel ListLen #Attr.2;
ret List.260; ret List.285;
procedure Num.19 (#Attr.2, #Attr.3): procedure Num.19 (#Attr.2, #Attr.3):
let Num.273 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; let Num.273 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;

View file

@ -1,26 +1,26 @@
procedure List.2 (List.73, List.74): procedure List.2 (List.75, List.76):
let List.265 : U64 = CallByName List.6 List.73; let List.290 : U64 = CallByName List.6 List.75;
let List.261 : Int1 = CallByName Num.22 List.74 List.265; let List.286 : Int1 = CallByName Num.22 List.76 List.290;
if List.261 then if List.286 then
let List.263 : Str = CallByName List.60 List.73 List.74; let List.288 : Str = CallByName List.60 List.75 List.76;
let List.262 : [C {}, C Str] = Ok List.263; let List.287 : [C {}, C Str] = Ok List.288;
ret List.262; ret List.287;
else else
let List.260 : {} = Struct {}; let List.285 : {} = Struct {};
let List.259 : [C {}, C Str] = Err List.260; let List.284 : [C {}, C Str] = Err List.285;
ret List.259; ret List.284;
procedure List.5 (#Attr.2, #Attr.3): procedure List.5 (#Attr.2, #Attr.3):
let List.267 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; let List.292 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3;
ret List.267; ret List.292;
procedure List.6 (#Attr.2): procedure List.6 (#Attr.2):
let List.269 : U64 = lowlevel ListLen #Attr.2; let List.294 : U64 = lowlevel ListLen #Attr.2;
ret List.269; ret List.294;
procedure List.60 (#Attr.2, #Attr.3): procedure List.60 (#Attr.2, #Attr.3):
let List.268 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; let List.293 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.268; ret List.293;
procedure Num.22 (#Attr.2, #Attr.3): procedure Num.22 (#Attr.2, #Attr.3):
let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View file

@ -1,28 +1,28 @@
procedure List.2 (List.73, List.74): procedure List.2 (List.75, List.76):
let List.265 : U64 = CallByName List.6 List.73; let List.290 : U64 = CallByName List.6 List.75;
let List.261 : Int1 = CallByName Num.22 List.74 List.265; let List.286 : Int1 = CallByName Num.22 List.76 List.290;
if List.261 then if List.286 then
let List.263 : Str = CallByName List.60 List.73 List.74; let List.288 : Str = CallByName List.60 List.75 List.76;
let List.262 : [C {}, C Str] = Ok List.263; let List.287 : [C {}, C Str] = Ok List.288;
ret List.262; ret List.287;
else else
let List.260 : {} = Struct {}; let List.285 : {} = Struct {};
let List.259 : [C {}, C Str] = Err List.260; let List.284 : [C {}, C Str] = Err List.285;
ret List.259; ret List.284;
procedure List.5 (#Attr.2, #Attr.3): procedure List.5 (#Attr.2, #Attr.3):
inc #Attr.2; inc #Attr.2;
let List.267 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; let List.292 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3;
decref #Attr.2; decref #Attr.2;
ret List.267; ret List.292;
procedure List.6 (#Attr.2): procedure List.6 (#Attr.2):
let List.269 : U64 = lowlevel ListLen #Attr.2; let List.294 : U64 = lowlevel ListLen #Attr.2;
ret List.269; ret List.294;
procedure List.60 (#Attr.2, #Attr.3): procedure List.60 (#Attr.2, #Attr.3):
let List.268 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; let List.293 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.268; ret List.293;
procedure Num.22 (#Attr.2, #Attr.3): procedure Num.22 (#Attr.2, #Attr.3):
let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View file

@ -1,27 +1,27 @@
procedure List.3 (List.82, List.83, List.84): procedure List.3 (List.84, List.85, List.86):
let List.260 : {List I64, I64} = CallByName List.57 List.82 List.83 List.84; let List.285 : {List I64, I64} = CallByName List.57 List.84 List.85 List.86;
let List.259 : List I64 = StructAtIndex 0 List.260; let List.284 : List I64 = StructAtIndex 0 List.285;
inc List.259; inc List.284;
dec List.260; dec List.285;
ret List.259; ret List.284;
procedure List.57 (List.79, List.80, List.81): procedure List.57 (List.81, List.82, List.83):
let List.266 : U64 = CallByName List.6 List.79; let List.291 : U64 = CallByName List.6 List.81;
let List.263 : Int1 = CallByName Num.22 List.80 List.266; let List.288 : Int1 = CallByName Num.22 List.82 List.291;
if List.263 then if List.288 then
let List.264 : {List I64, I64} = CallByName List.61 List.79 List.80 List.81; let List.289 : {List I64, I64} = CallByName List.61 List.81 List.82 List.83;
ret List.264; ret List.289;
else else
let List.262 : {List I64, I64} = Struct {List.79, List.81}; let List.287 : {List I64, I64} = Struct {List.81, List.83};
ret List.262; ret List.287;
procedure List.6 (#Attr.2): procedure List.6 (#Attr.2):
let List.267 : U64 = lowlevel ListLen #Attr.2; let List.292 : U64 = lowlevel ListLen #Attr.2;
ret List.267; ret List.292;
procedure List.61 (#Attr.2, #Attr.3, #Attr.4): procedure List.61 (#Attr.2, #Attr.3, #Attr.4):
let List.265 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; let List.290 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.265; ret List.290;
procedure Num.22 (#Attr.2, #Attr.3): procedure Num.22 (#Attr.2, #Attr.3):
let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View file

@ -1,16 +1,16 @@
procedure List.28 (#Attr.2, #Attr.3): procedure List.28 (#Attr.2, #Attr.3):
let List.262 : List I64 = lowlevel ListSortWith { xs: `#Attr.#arg1` } #Attr.2 Num.46 #Attr.3; let List.287 : List I64 = lowlevel ListSortWith { xs: `#Attr.#arg1` } #Attr.2 Num.46 #Attr.3;
let Bool.14 : Int1 = lowlevel ListIsUnique #Attr.2; let Bool.14 : Int1 = lowlevel ListIsUnique #Attr.2;
if Bool.14 then if Bool.14 then
ret List.262; ret List.287;
else else
decref #Attr.2; decref #Attr.2;
ret List.262; ret List.287;
procedure List.54 (List.178): procedure List.54 (List.196):
let List.260 : {} = Struct {}; let List.285 : {} = Struct {};
let List.259 : List I64 = CallByName List.28 List.178 List.260; let List.284 : List I64 = CallByName List.28 List.196 List.285;
ret List.259; ret List.284;
procedure Num.46 (#Attr.2, #Attr.3): procedure Num.46 (#Attr.2, #Attr.3):
let Num.273 : U8 = lowlevel NumCompare #Attr.2 #Attr.3; let Num.273 : U8 = lowlevel NumCompare #Attr.2 #Attr.3;

View file

@ -1,21 +0,0 @@
procedure Num.19 (#Attr.2, #Attr.3):
let Num.273 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
ret Num.273;
procedure Test.5 (Test.7, Test.8):
let Test.17 : U64 = 1i64;
ret Test.17;
procedure Test.6 (Test.7, Test.8):
let Test.14 : U64 = 1i64;
ret Test.14;
procedure Test.0 ():
let Test.15 : U8 = 100i64;
let Test.16 : U32 = 100i64;
let Test.10 : U64 = CallByName Test.5 Test.15 Test.16;
let Test.12 : U32 = 100i64;
let Test.13 : U8 = 100i64;
let Test.11 : U64 = CallByName Test.6 Test.12 Test.13;
let Test.9 : U64 = CallByName Num.19 Test.10 Test.11;
ret Test.9;

View file

@ -1,43 +1,43 @@
procedure List.2 (List.73, List.74): procedure List.2 (List.75, List.76):
let List.279 : U64 = CallByName List.6 List.73; let List.304 : U64 = CallByName List.6 List.75;
let List.275 : Int1 = CallByName Num.22 List.74 List.279; let List.300 : Int1 = CallByName Num.22 List.76 List.304;
if List.275 then if List.300 then
let List.277 : I64 = CallByName List.60 List.73 List.74; let List.302 : I64 = CallByName List.60 List.75 List.76;
let List.276 : [C {}, C I64] = Ok List.277; let List.301 : [C {}, C I64] = Ok List.302;
ret List.276; ret List.301;
else else
let List.274 : {} = Struct {}; let List.299 : {} = Struct {};
let List.273 : [C {}, C I64] = Err List.274; let List.298 : [C {}, C I64] = Err List.299;
ret List.273; ret List.298;
procedure List.3 (List.82, List.83, List.84): procedure List.3 (List.84, List.85, List.86):
let List.263 : {List I64, I64} = CallByName List.57 List.82 List.83 List.84; let List.288 : {List I64, I64} = CallByName List.57 List.84 List.85 List.86;
let List.262 : List I64 = StructAtIndex 0 List.263; let List.287 : List I64 = StructAtIndex 0 List.288;
inc List.262; inc List.287;
dec List.263; dec List.288;
ret List.262;
procedure List.57 (List.79, List.80, List.81):
let List.285 : U64 = CallByName List.6 List.79;
let List.282 : Int1 = CallByName Num.22 List.80 List.285;
if List.282 then
let List.283 : {List I64, I64} = CallByName List.61 List.79 List.80 List.81;
ret List.283;
else
let List.281 : {List I64, I64} = Struct {List.79, List.81};
ret List.281;
procedure List.6 (#Attr.2):
let List.286 : U64 = lowlevel ListLen #Attr.2;
ret List.286;
procedure List.60 (#Attr.2, #Attr.3):
let List.287 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.287; ret List.287;
procedure List.57 (List.81, List.82, List.83):
let List.310 : U64 = CallByName List.6 List.81;
let List.307 : Int1 = CallByName Num.22 List.82 List.310;
if List.307 then
let List.308 : {List I64, I64} = CallByName List.61 List.81 List.82 List.83;
ret List.308;
else
let List.306 : {List I64, I64} = Struct {List.81, List.83};
ret List.306;
procedure List.6 (#Attr.2):
let List.311 : U64 = lowlevel ListLen #Attr.2;
ret List.311;
procedure List.60 (#Attr.2, #Attr.3):
let List.312 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.312;
procedure List.61 (#Attr.2, #Attr.3, #Attr.4): procedure List.61 (#Attr.2, #Attr.3, #Attr.4):
let List.284 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; let List.309 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.284; ret List.309;
procedure Num.22 (#Attr.2, #Attr.3): procedure Num.22 (#Attr.2, #Attr.3):
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View file

@ -1,43 +1,43 @@
procedure List.2 (List.73, List.74): procedure List.2 (List.75, List.76):
let List.279 : U64 = CallByName List.6 List.73; let List.304 : U64 = CallByName List.6 List.75;
let List.275 : Int1 = CallByName Num.22 List.74 List.279; let List.300 : Int1 = CallByName Num.22 List.76 List.304;
if List.275 then if List.300 then
let List.277 : I64 = CallByName List.60 List.73 List.74; let List.302 : I64 = CallByName List.60 List.75 List.76;
let List.276 : [C {}, C I64] = Ok List.277; let List.301 : [C {}, C I64] = Ok List.302;
ret List.276; ret List.301;
else else
let List.274 : {} = Struct {}; let List.299 : {} = Struct {};
let List.273 : [C {}, C I64] = Err List.274; let List.298 : [C {}, C I64] = Err List.299;
ret List.273; ret List.298;
procedure List.3 (List.82, List.83, List.84): procedure List.3 (List.84, List.85, List.86):
let List.263 : {List I64, I64} = CallByName List.57 List.82 List.83 List.84; let List.288 : {List I64, I64} = CallByName List.57 List.84 List.85 List.86;
let List.262 : List I64 = StructAtIndex 0 List.263; let List.287 : List I64 = StructAtIndex 0 List.288;
inc List.262; inc List.287;
dec List.263; dec List.288;
ret List.262;
procedure List.57 (List.79, List.80, List.81):
let List.285 : U64 = CallByName List.6 List.79;
let List.282 : Int1 = CallByName Num.22 List.80 List.285;
if List.282 then
let List.283 : {List I64, I64} = CallByName List.61 List.79 List.80 List.81;
ret List.283;
else
let List.281 : {List I64, I64} = Struct {List.79, List.81};
ret List.281;
procedure List.6 (#Attr.2):
let List.286 : U64 = lowlevel ListLen #Attr.2;
ret List.286;
procedure List.60 (#Attr.2, #Attr.3):
let List.287 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.287; ret List.287;
procedure List.57 (List.81, List.82, List.83):
let List.310 : U64 = CallByName List.6 List.81;
let List.307 : Int1 = CallByName Num.22 List.82 List.310;
if List.307 then
let List.308 : {List I64, I64} = CallByName List.61 List.81 List.82 List.83;
ret List.308;
else
let List.306 : {List I64, I64} = Struct {List.81, List.83};
ret List.306;
procedure List.6 (#Attr.2):
let List.311 : U64 = lowlevel ListLen #Attr.2;
ret List.311;
procedure List.60 (#Attr.2, #Attr.3):
let List.312 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.312;
procedure List.61 (#Attr.2, #Attr.3, #Attr.4): procedure List.61 (#Attr.2, #Attr.3, #Attr.4):
let List.284 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; let List.309 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.284; ret List.309;
procedure Num.22 (#Attr.2, #Attr.3): procedure Num.22 (#Attr.2, #Attr.3):
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View file

@ -1,53 +0,0 @@
procedure Num.19 (#Attr.2, #Attr.3):
let Num.274 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
ret Num.274;
procedure Num.21 (#Attr.2, #Attr.3):
let Num.273 : I64 = lowlevel NumMul #Attr.2 #Attr.3;
ret Num.273;
procedure Test.1 ():
let Test.26 : I64 = 1i64;
ret Test.26;
procedure Test.2 ():
let Test.22 : I64 = 2i64;
ret Test.22;
procedure Test.3 (Test.6):
let Test.25 : I64 = CallByName Test.1;
let Test.24 : I64 = CallByName Num.19 Test.6 Test.25;
ret Test.24;
procedure Test.4 (Test.7):
let Test.21 : I64 = CallByName Test.2;
let Test.20 : I64 = CallByName Num.21 Test.7 Test.21;
ret Test.20;
procedure Test.5 (Test.8, Test.9):
joinpoint Test.15 Test.14:
ret Test.14;
in
switch Test.8:
case 0:
let Test.16 : I64 = CallByName Test.3 Test.9;
jump Test.15 Test.16;
default:
let Test.17 : I64 = CallByName Test.4 Test.9;
jump Test.15 Test.17;
procedure Test.0 ():
joinpoint Test.19 Test.12:
let Test.13 : I64 = 42i64;
let Test.11 : I64 = CallByName Test.5 Test.12 Test.13;
ret Test.11;
in
let Test.23 : Int1 = true;
if Test.23 then
let Test.3 : Int1 = false;
jump Test.19 Test.3;
else
let Test.4 : Int1 = true;
jump Test.19 Test.4;