Merge branch 'trunk' of github.com:rtfeldman/roc into crates-folder

This commit is contained in:
Anton-4 2022-07-02 12:35:19 +02:00
commit b74fc3554b
No known key found for this signature in database
GPG Key ID: C954D6E0F9C0ABFD
35 changed files with 359 additions and 1204 deletions

View File

@ -1,27 +1,27 @@
procedure List.3 (List.76, List.77, List.78):
let List.167 : {List I64, I64} = CallByName List.57 List.76 List.77 List.78;
let List.166 : List I64 = StructAtIndex 0 List.167;
inc List.166;
dec List.167;
ret List.166;
procedure List.3 (List.81, List.82, List.83):
let List.242 : {List I64, I64} = CallByName List.57 List.81 List.82 List.83;
let List.241 : List I64 = StructAtIndex 0 List.242;
inc List.241;
dec List.242;
ret List.241;
procedure List.57 (List.73, List.74, List.75):
let List.173 : U64 = CallByName List.6 List.73;
let List.170 : Int1 = CallByName Num.22 List.74 List.173;
if List.170 then
let List.171 : {List I64, I64} = CallByName List.61 List.73 List.74 List.75;
ret List.171;
procedure List.57 (List.78, List.79, List.80):
let List.248 : U64 = CallByName List.6 List.78;
let List.245 : Int1 = CallByName Num.22 List.79 List.248;
if List.245 then
let List.246 : {List I64, I64} = CallByName List.61 List.78 List.79 List.80;
ret List.246;
else
let List.169 : {List I64, I64} = Struct {List.73, List.75};
ret List.169;
let List.244 : {List I64, I64} = Struct {List.78, List.80};
ret List.244;
procedure List.6 (#Attr.2):
let List.165 : U64 = lowlevel ListLen #Attr.2;
ret List.165;
let List.240 : U64 = lowlevel ListLen #Attr.2;
ret List.240;
procedure List.61 (#Attr.2, #Attr.3, #Attr.4):
let List.172 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.172;
let List.247 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.247;
procedure Num.19 (#Attr.2, #Attr.3):
let Num.273 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;

View File

@ -1,22 +1,22 @@
procedure List.2 (List.67, List.68):
let List.170 : U64 = CallByName List.6 List.67;
let List.166 : Int1 = CallByName Num.22 List.68 List.170;
if List.166 then
let List.168 : I64 = CallByName List.60 List.67 List.68;
let List.167 : [C {}, C I64] = Ok List.168;
ret List.167;
procedure List.2 (List.72, List.73):
let List.245 : U64 = CallByName List.6 List.72;
let List.241 : Int1 = CallByName Num.22 List.73 List.245;
if List.241 then
let List.243 : I64 = CallByName List.60 List.72 List.73;
let List.242 : [C {}, C I64] = Ok List.243;
ret List.242;
else
let List.165 : {} = Struct {};
let List.164 : [C {}, C I64] = Err List.165;
ret List.164;
let List.240 : {} = Struct {};
let List.239 : [C {}, C I64] = Err List.240;
ret List.239;
procedure List.6 (#Attr.2):
let List.173 : U64 = lowlevel ListLen #Attr.2;
ret List.173;
let List.248 : U64 = lowlevel ListLen #Attr.2;
ret List.248;
procedure List.60 (#Attr.2, #Attr.3):
let List.172 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.172;
let List.247 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.247;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View File

@ -1,27 +1,27 @@
procedure List.3 (List.76, List.77, List.78):
let List.165 : {List I64, I64} = CallByName List.57 List.76 List.77 List.78;
let List.164 : List I64 = StructAtIndex 0 List.165;
inc List.164;
dec List.165;
ret List.164;
procedure List.3 (List.81, List.82, List.83):
let List.240 : {List I64, I64} = CallByName List.57 List.81 List.82 List.83;
let List.239 : List I64 = StructAtIndex 0 List.240;
inc List.239;
dec List.240;
ret List.239;
procedure List.57 (List.73, List.74, List.75):
let List.171 : U64 = CallByName List.6 List.73;
let List.168 : Int1 = CallByName Num.22 List.74 List.171;
if List.168 then
let List.169 : {List I64, I64} = CallByName List.61 List.73 List.74 List.75;
ret List.169;
procedure List.57 (List.78, List.79, List.80):
let List.246 : U64 = CallByName List.6 List.78;
let List.243 : Int1 = CallByName Num.22 List.79 List.246;
if List.243 then
let List.244 : {List I64, I64} = CallByName List.61 List.78 List.79 List.80;
ret List.244;
else
let List.167 : {List I64, I64} = Struct {List.73, List.75};
ret List.167;
let List.242 : {List I64, I64} = Struct {List.78, List.80};
ret List.242;
procedure List.6 (#Attr.2):
let List.172 : U64 = lowlevel ListLen #Attr.2;
ret List.172;
let List.247 : U64 = lowlevel ListLen #Attr.2;
ret List.247;
procedure List.61 (#Attr.2, #Attr.3, #Attr.4):
let List.170 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.170;
let List.245 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.245;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View File

@ -1332,16 +1332,6 @@ fn lowlevel_spec(
with_new_heap_cell(builder, block, bag)
}
ListReverse => {
let list = env.symbols[&arguments[0]];
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
let cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?;
let _unit = builder.add_update(block, update_mode_var, cell)?;
with_new_heap_cell(builder, block, bag)
}
ListAppend => {
let list = env.symbols[&arguments[0]];
let to_insert = env.symbols[&arguments[1]];

View File

@ -990,66 +990,6 @@ pub fn listDropAt(
}
}
pub fn listRange(width: utils.IntWidth, low: Opaque, high: Opaque) callconv(.C) RocList {
return switch (width) {
.U8 => helper1(u8, low, high),
.U16 => helper1(u16, low, high),
.U32 => helper1(u32, low, high),
.U64 => helper1(u64, low, high),
.U128 => helper1(u128, low, high),
.I8 => helper1(i8, low, high),
.I16 => helper1(i16, low, high),
.I32 => helper1(i32, low, high),
.I64 => helper1(i64, low, high),
.I128 => helper1(i128, low, high),
};
}
fn helper1(comptime T: type, low: Opaque, high: Opaque) RocList {
const ptr1 = @ptrCast(*T, @alignCast(@alignOf(T), low));
const ptr2 = @ptrCast(*T, @alignCast(@alignOf(T), high));
return listRangeHelp(T, ptr1.*, ptr2.*);
}
fn listRangeHelp(comptime T: type, low: T, high: T) RocList {
const Order = std.math.Order;
switch (std.math.order(low, high)) {
Order.gt => {
return RocList.empty();
},
Order.eq => {
const list = RocList.allocate(@alignOf(usize), 1, @sizeOf(T));
const buffer = @ptrCast([*]T, @alignCast(@alignOf(T), list.bytes orelse unreachable));
buffer[0] = low;
return list;
},
Order.lt => {
const length: usize = @intCast(usize, high - low);
const list = RocList.allocate(@alignOf(usize), length, @sizeOf(T));
const buffer = @ptrCast([*]T, @alignCast(@alignOf(T), list.bytes orelse unreachable));
var i: usize = 0;
var current = low;
while (i < length) {
buffer[i] = current;
i += 1;
current += 1;
}
return list;
},
}
}
fn partition(source_ptr: [*]u8, transform: Opaque, wrapper: CompareFn, element_width: usize, low: isize, high: isize) isize {
const pivot = source_ptr + (@intCast(usize, high) * element_width);
var i = (low - 1); // Index of smaller element and indicates the right position of pivot found so far
@ -1209,34 +1149,6 @@ fn swapElements(source_ptr: [*]u8, element_width: usize, index_1: usize, index_2
return swap(element_width, element_at_i, element_at_j);
}
pub fn listJoin(list_of_lists: RocList, alignment: u32, element_width: usize) callconv(.C) RocList {
var total_length: usize = 0;
const slice_of_lists = @ptrCast([*]RocList, @alignCast(@alignOf(RocList), list_of_lists.bytes));
var i: usize = 0;
while (i < list_of_lists.len()) : (i += 1) {
total_length += slice_of_lists[i].len();
}
const output = RocList.allocate(alignment, total_length, element_width);
if (output.bytes) |target| {
var elements_copied: usize = 0;
i = 0;
while (i < list_of_lists.len()) : (i += 1) {
const list = slice_of_lists[i];
if (list.bytes) |source| {
@memcpy(target + elements_copied * element_width, source, list.len() * element_width);
elements_copied += list.len();
}
}
}
return output;
}
pub fn listConcat(list_a: RocList, list_b: RocList, alignment: u32, element_width: usize) callconv(.C) RocList {
if (list_a.isEmpty()) {
return list_b;

View File

@ -53,8 +53,6 @@ comptime {
exportListFn(list.listPrepend, "prepend");
exportListFn(list.listSingle, "single");
exportListFn(list.listWithCapacity, "with_capacity");
exportListFn(list.listJoin, "join");
exportListFn(list.listRange, "range");
exportListFn(list.listReverse, "reverse");
exportListFn(list.listSortWith, "sort_with");
exportListFn(list.listConcat, "concat");

View File

@ -9,6 +9,7 @@ interface List
map,
len,
withCapacity,
iterate,
walkBackwards,
concat,
first,
@ -273,6 +274,10 @@ concat : List a, List a -> List a
## Returns the last element in the list, or `ListWasEmpty` if it was empty.
last : List a -> Result a [ListWasEmpty]*
last = \list ->
when List.get list (Num.subSaturated (List.len list) 1) is
Ok v -> Ok v
Err _ -> Err ListWasEmpty
## A list with a single element in it.
##
@ -283,15 +288,34 @@ last : List a -> Result a [ListWasEmpty]*
## |> List.single
##
single : a -> List a
single = \x -> [x]
## Returns a list with the given length, where every element is the given value.
##
##
repeat : a, Nat -> List a
repeat = \value, count ->
repeatHelp value count (List.withCapacity count)
repeatHelp : a, Nat, List a -> List a
repeatHelp = \value, count, accum ->
if count > 0 then
repeatHelp value (count - 1) (List.append accum value)
else
accum
## Returns the list with its elements reversed.
##
## >>> List.reverse [1, 2, 3]
reverse : List a -> List a
reverse = \list ->
reverseHelp list 0 (Num.subSaturated (List.len list) 1)
reverseHelp = \list, left, right ->
if left < right then
reverseHelp (List.swap list left right) (left + 1) (right - 1)
else
list
## Join the given lists together into one list.
##
@ -301,7 +325,15 @@ reverse : List a -> List a
##
## >>> List.join []
join : List (List a) -> List a
join = \lists ->
totalLength =
List.walk lists 0 (\state, list -> state + List.len list)
List.walk lists (List.withCapacity totalLength) (\state, list -> List.concat state list)
contains : List a, a -> Bool
contains = \list, needle ->
List.any list (\x -> x == needle)
## Build a value using each element in the list.
##
@ -356,7 +388,11 @@ walkBackwards : List elem, state, (state, elem -> state) -> state
##
## 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.
walkUntil : List elem, state, (state, elem -> [Continue state, Stop state]) -> state
walkUntil : List elem, state, (state, elem -> [Continue state, Break state]) -> state
walkUntil = \list, initial, step ->
when List.iterate list initial step is
Continue new -> new
Break new -> new
sum : List (Num a) -> Num a
sum = \list ->
@ -369,10 +405,30 @@ product = \list ->
## Run the given predicate on each element of the list, returning `True` if
## any of the elements satisfy it.
any : List a, (a -> Bool) -> Bool
any = \list, predicate ->
looper = \{}, element ->
if predicate element then
Break {}
else
Continue {}
when List.iterate list {} looper is
Continue {} -> False
Break {} -> True
## Run the given predicate on each element of the list, returning `True` if
## all of the elements satisfy it.
all : List a, (a -> Bool) -> Bool
all = \list, predicate ->
looper = \{}, element ->
if predicate element then
Continue {}
else
Break {}
when List.iterate list {} looper is
Continue {} -> True
Break {} -> False
## Run the given function on each element of a list, and return all the
## elements for which the function returned `True`.
@ -467,6 +523,23 @@ mapWithIndex : List a, (a, Nat -> b) -> List b
##
## >>> List.range 2 8
range : Int a, Int a -> List (Int a)
range = \start, end ->
when Num.compare start end is
GT -> []
EQ -> [start]
LT ->
length = Num.intCast (start - end)
rangeHelp (List.withCapacity length) start end
rangeHelp : List (Int a), Int a, Int a -> List (Int a)
rangeHelp = \accum, start, end ->
if end <= start then
accum
else
rangeHelp (List.append accum start) (start + 1) end
## Sort with a custom comparison function
sortWith : List a, (a, a -> [LT, EQ, GT]) -> List a
## Sorts a list in ascending order (lowest to highest), using a function which
@ -487,6 +560,10 @@ swap : List a, Nat, Nat -> List a
## Returns the first element in the list, or `ListWasEmpty` if it was empty.
first : List a -> Result a [ListWasEmpty]*
first = \list ->
when List.get list 0 is
Ok v -> Ok v
Err _ -> Err ListWasEmpty
## Remove the first element from the list.
##
@ -610,22 +687,33 @@ joinMap = \list, mapper ->
## Returns the first element of the list satisfying a predicate function.
## If no satisfying element is found, an `Err NotFound` is returned.
find : List elem, (elem -> Bool) -> Result elem [NotFound]*
find = \array, pred ->
callback = \_, elem ->
if pred elem then
Break elem
else
Continue {}
when List.iterate array {} callback is
Continue {} ->
Err NotFound
Break found ->
Ok found
## Returns the index at which the first element in the list
## satisfying a predicate function can be found.
## If no satisfying element is found, an `Err NotFound` is returned.
findIndex : List elem, (elem -> Bool) -> Result Nat [NotFound]*
findIndex = \list, matcher ->
foundIndex = List.walkUntil list 0 \index, elem ->
foundIndex = List.iterate list 0 \index, elem ->
if matcher elem then
Stop index
Break index
else
Continue (index + 1)
if foundIndex < List.len list then
Ok foundIndex
else
Err NotFound
when foundIndex is
Break index -> Ok index
Continue _ -> Err NotFound
## Returns a subsection of the given list, beginning at the `start` index and
## including a total of `len` elements.
@ -653,3 +741,20 @@ intersperse : List elem, elem -> List elem
## means if you give an index of 0, the `before` list will be empty and the
## `others` list will have the same elements as the original list.)
split : List elem, Nat -> { before : List elem, others : List elem }
## Primitive for iterating over a List, being able to decide at every element whether to continue
iterate : List elem, s, (s, elem -> [Continue s, Break b]) -> [Continue s, Break b]
iterate = \list, init, func ->
iterHelp list init func 0 (List.len list)
## internal helper
iterHelp : List elem, s, (s, elem -> [Continue s, Break b]), Nat, Nat -> [Continue s, Break b]
iterHelp = \list, state, f, index, length ->
if index < length then
when f state (List.getUnsafe list index) is
Continue nextState ->
iterHelp list nextState f (index + 1) length
Break b ->
Break b
else
Continue state

View File

@ -368,8 +368,6 @@ pub const LIST_DROP_AT: &str = "roc_builtins.list.drop_at";
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_JOIN: &str = "roc_builtins.list.join";
pub const LIST_RANGE: &str = "roc_builtins.list.range";
pub const LIST_REVERSE: &str = "roc_builtins.list.reverse";
pub const LIST_SORT_WITH: &str = "roc_builtins.list.sort_with";
pub const LIST_CONCAT: &str = "roc_builtins.list.concat";

View File

@ -1214,11 +1214,11 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
);
fn until_type(content: SolvedType) -> SolvedType {
// [LT, EQ, GT]
// [Continue, Break]
SolvedType::TagUnion(
vec![
(TagName("Continue".into()), vec![content.clone()]),
(TagName("Stop".into()), vec![content]),
(TagName("Break".into()), vec![content]),
],
Box::new(SolvedType::EmptyTagUnion),
)

View File

@ -56,7 +56,6 @@ pub fn builtin_dependencies(symbol: Symbol) -> &'static [Symbol] {
Symbol::LIST_SORT_DESC => &[Symbol::LIST_SORT_WITH],
Symbol::LIST_PRODUCT => &[Symbol::LIST_WALK, Symbol::NUM_MUL],
Symbol::LIST_SUM => &[Symbol::LIST_WALK, Symbol::NUM_ADD],
Symbol::LIST_JOIN_MAP => &[Symbol::LIST_WALK, Symbol::LIST_CONCAT],
Symbol::LIST_SET => &[Symbol::LIST_REPLACE],
_ => &[],
}
@ -105,19 +104,10 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
LIST_WITH_CAPACITY => list_with_capacity,
LIST_GET_UNSAFE => list_get_unsafe,
LIST_REPLACE_UNSAFE => list_replace_unsafe,
LIST_SET => list_set,
LIST_APPEND => list_append,
LIST_FIRST => list_first,
LIST_LAST => list_last,
LIST_IS_EMPTY => list_is_empty,
LIST_SINGLE => list_single,
LIST_REPEAT => list_repeat,
LIST_REVERSE => list_reverse,
LIST_CONCAT => list_concat,
LIST_CONTAINS => list_contains,
LIST_PREPEND => list_prepend,
LIST_JOIN => list_join,
LIST_JOIN_MAP => list_join_map,
LIST_MAP => list_map,
LIST_MAP2 => list_map2,
LIST_MAP3 => list_map3,
@ -134,14 +124,10 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
LIST_KEEP_IF => list_keep_if,
LIST_KEEP_OKS => list_keep_oks,
LIST_KEEP_ERRS=> list_keep_errs,
LIST_RANGE => list_range,
LIST_WALK => list_walk,
LIST_WALK_BACKWARDS => list_walk_backwards,
LIST_WALK_UNTIL => list_walk_until,
LIST_SORT_WITH => list_sort_with,
LIST_ANY => list_any,
LIST_ALL => list_all,
LIST_FIND => list_find,
LIST_IS_UNIQUE => list_is_unique,
DICT_LEN => dict_len,
DICT_EMPTY => dict_empty,
@ -1517,25 +1503,6 @@ fn list_is_empty(symbol: Symbol, var_store: &mut VarStore) -> Def {
)
}
/// List.reverse : List elem -> List elem
fn list_reverse(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::ListReverse,
args: vec![(list_var, Var(Symbol::ARG_1))],
ret_var: list_var,
};
defn(
symbol,
vec![(list_var, Symbol::ARG_1)],
var_store,
body,
list_var,
)
}
/// Str.split : Str, Str -> List Str
fn str_split(symbol: Symbol, var_store: &mut VarStore) -> Def {
let str_var = var_store.fresh();
@ -2107,50 +2074,6 @@ fn list_concat(symbol: Symbol, var_store: &mut VarStore) -> Def {
)
}
/// List.repeat : elem, Nat -> List elem
fn list_repeat(symbol: Symbol, var_store: &mut VarStore) -> Def {
let elem_var = var_store.fresh();
let len_var = var_store.fresh();
let list_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::ListRepeat,
args: vec![
(elem_var, Var(Symbol::ARG_1)),
(len_var, Var(Symbol::ARG_2)),
],
ret_var: list_var,
};
defn(
symbol,
vec![(elem_var, Symbol::ARG_1), (len_var, Symbol::ARG_2)],
var_store,
body,
list_var,
)
}
/// List.single : elem -> List elem
fn list_single(symbol: Symbol, var_store: &mut VarStore) -> Def {
let elem_var = var_store.fresh();
let list_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::ListSingle,
args: vec![(elem_var, Var(Symbol::ARG_1))],
ret_var: list_var,
};
defn(
symbol,
vec![(elem_var, Symbol::ARG_1)],
var_store,
body,
list_var,
)
}
/// List.len : List a -> Nat
fn list_len(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_1(symbol, LowLevel::ListLen, var_store)
@ -2171,91 +2094,6 @@ fn list_replace_unsafe(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_3(symbol, LowLevel::ListReplaceUnsafe, var_store)
}
/// List.set : List elem, Nat, elem -> List elem
fn list_set(symbol: Symbol, var_store: &mut VarStore) -> Def {
let arg_list = Symbol::ARG_1;
let arg_index = Symbol::ARG_2;
let arg_elem = Symbol::ARG_3;
let bool_var = var_store.fresh();
let len_var = var_store.fresh();
let elem_var = var_store.fresh();
let replace_record_var = var_store.fresh();
let list_arg_var = var_store.fresh(); // Uniqueness type Attr differs between
let list_ret_var = var_store.fresh(); // the arg list and the returned list
let replace_function = (
var_store.fresh(),
Loc::at_zero(Expr::Var(Symbol::LIST_REPLACE)),
var_store.fresh(),
replace_record_var,
);
let replace_call = Expr::Call(
Box::new(replace_function),
vec![
(list_arg_var, Loc::at_zero(Var(arg_list))),
(len_var, Loc::at_zero(Var(arg_index))),
(elem_var, Loc::at_zero(Var(arg_elem))),
],
CalledVia::Space,
);
// Perform a bounds check. If it passes, run LowLevel::ListSet.
// Otherwise, return the list unmodified.
let body = If {
cond_var: bool_var,
branch_var: list_ret_var,
branches: vec![(
// if-condition
no_region(
// index < List.len list
RunLowLevel {
op: LowLevel::NumLt,
args: vec![
(len_var, Var(arg_index)),
(
len_var,
RunLowLevel {
op: LowLevel::ListLen,
args: vec![(list_arg_var, Var(arg_list))],
ret_var: len_var,
},
),
],
ret_var: bool_var,
},
),
// then-branch
no_region(Access {
record_var: replace_record_var,
ext_var: var_store.fresh(),
field_var: list_ret_var,
loc_expr: Box::new(no_region(
// List.replaceUnsafe list index elem
replace_call,
)),
field: "list".into(),
}),
)],
final_else: Box::new(
// else-branch
no_region(Var(arg_list)),
),
};
defn(
symbol,
vec![
(list_arg_var, Symbol::ARG_1),
(len_var, Symbol::ARG_2),
(elem_var, Symbol::ARG_3),
],
var_store,
body,
list_ret_var,
)
}
/// List.swap : List elem, Nat, Nat -> List elem
fn list_swap(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();
@ -2718,26 +2556,6 @@ fn list_prepend(symbol: Symbol, var_store: &mut VarStore) -> Def {
)
}
/// List.join : List (List elem) -> List elem
fn list_join(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();
let list_of_list_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::ListJoin,
args: vec![(list_of_list_var, Var(Symbol::ARG_1))],
ret_var: list_var,
};
defn(
symbol,
vec![(list_of_list_var, Symbol::ARG_1)],
var_store,
body,
list_var,
)
}
/// 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)
@ -2753,90 +2571,6 @@ fn list_walk_until(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_3(symbol, LowLevel::ListWalkUntil, var_store)
}
/// List.joinMap : List before, (before -> List after) -> List after
fn list_join_map(symbol: Symbol, var_store: &mut VarStore) -> Def {
let before = var_store.fresh();
let list_before = var_store.fresh();
let after = var_store.fresh();
let list_after = var_store.fresh();
let before2list_after = var_store.fresh();
let t_concat_clos = var_store.fresh();
let mapper_lambda_set = var_store.fresh();
// \state, elem -> List.concat state (mapper elem)
let concat_clos = Closure(ClosureData {
function_type: t_concat_clos,
closure_type: var_store.fresh(),
return_type: list_after,
name: Symbol::LIST_JOIN_MAP_CONCAT,
recursive: Recursive::NotRecursive,
captured_symbols: vec![(Symbol::ARG_2, before2list_after)],
arguments: vec![
(
list_after,
AnnotatedMark::new(var_store),
no_region(Pattern::Identifier(Symbol::ARG_3)),
),
(
before,
AnnotatedMark::new(var_store),
no_region(Pattern::Identifier(Symbol::ARG_4)),
),
],
loc_body: {
let mapper = Box::new((
before2list_after,
no_region(Var(Symbol::ARG_2)),
mapper_lambda_set,
list_after, // return type
));
// (mapper elem)
let mapper_elem = Call(
mapper,
vec![(before, no_region(Var(Symbol::ARG_4)))],
CalledVia::Space,
);
Box::new(no_region(RunLowLevel {
op: LowLevel::ListConcat,
args: vec![(list_after, Var(Symbol::ARG_3)), (list_after, mapper_elem)],
ret_var: list_after,
}))
},
});
// List.joinMap = \input_list, mapper ->
// List.walk [] input_list (\state, elem -> List.concat state (mapper elem))
let body = RunLowLevel {
op: LowLevel::ListWalk,
args: vec![
// input_list : List before
(list_before, Var(Symbol::ARG_1)),
// [] : List after
(
list_after,
List {
elem_var: after,
loc_elems: vec![],
},
),
// \state, elem -> List.concat state (mapper elem)
(t_concat_clos, concat_clos),
],
ret_var: list_after,
};
defn(
symbol,
vec![
(list_before, Symbol::ARG_1),
(before2list_after, Symbol::ARG_2),
],
var_store,
body,
list_after,
)
}
/// List.keepIf : List elem, (elem -> Bool) -> List elem
fn list_keep_if(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();
@ -2860,11 +2594,6 @@ fn list_keep_if(symbol: Symbol, var_store: &mut VarStore) -> Def {
)
}
/// List.contains : List elem, elem -> Bool
fn list_contains(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_2(symbol, LowLevel::ListContains, var_store)
}
/// List.keepOks : List before, (before -> Result after *) -> List after
fn list_keep_oks(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_2(symbol, LowLevel::ListKeepOks, var_store)
@ -2875,11 +2604,6 @@ fn list_keep_errs(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_2(symbol, LowLevel::ListKeepErrs, var_store)
}
/// List.range: Int a, Int a -> List (Int a)
fn list_range(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_2(symbol, LowLevel::ListRange, var_store)
}
/// List.map : List before, (before -> after) -> List after
fn list_map(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_2(symbol, LowLevel::ListMap, var_store)
@ -2910,93 +2634,6 @@ fn list_sort_with(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_2(symbol, LowLevel::ListSortWith, var_store)
}
/// List.any: List elem, (elem -> Bool) -> Bool
fn list_any(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_2(symbol, LowLevel::ListAny, var_store)
}
/// List.all: List elem, (elem -> Bool) -> Bool
fn list_all(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_2(symbol, LowLevel::ListAll, var_store)
}
/// List.find : List elem, (elem -> Bool) -> Result elem [NotFound]*
fn list_find(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list = Symbol::ARG_1;
let find_predicate = Symbol::ARG_2;
let find_result = Symbol::LIST_FIND_RESULT;
let t_list = var_store.fresh();
let t_pred_fn = var_store.fresh();
let t_bool = var_store.fresh();
let t_found = var_store.fresh();
let t_value = var_store.fresh();
let t_ret = var_store.fresh();
let t_find_result = var_store.fresh();
let t_ext_var1 = var_store.fresh();
let t_ext_var2 = var_store.fresh();
// ListFindUnsafe returns { value: elem, found: Bool }.
// When `found` is true, the value was found. Otherwise `List.find` should return `Err ...`
let find_result_def = Def {
annotation: None,
expr_var: t_find_result,
loc_expr: no_region(RunLowLevel {
op: LowLevel::ListFindUnsafe,
args: vec![(t_list, Var(list)), (t_pred_fn, Var(find_predicate))],
ret_var: t_find_result,
}),
loc_pattern: no_region(Pattern::Identifier(find_result)),
pattern_vars: Default::default(),
};
let get_value = Access {
record_var: t_find_result,
ext_var: t_ext_var1,
field_var: t_value,
loc_expr: Box::new(no_region(Var(find_result))),
field: "value".into(),
};
let get_found = Access {
record_var: t_find_result,
ext_var: t_ext_var2,
field_var: t_found,
loc_expr: Box::new(no_region(Var(find_result))),
field: "found".into(),
};
let make_ok = tag("Ok", vec![get_value], var_store);
let make_err = tag(
"Err",
vec![tag("NotFound", Vec::new(), var_store)],
var_store,
);
let inspect = If {
cond_var: t_bool,
branch_var: t_ret,
branches: vec![(
// if-condition
no_region(get_found),
no_region(make_ok),
)],
final_else: Box::new(no_region(make_err)),
};
let body = LetNonRec(Box::new(find_result_def), Box::new(no_region(inspect)));
defn(
symbol,
vec![(t_list, Symbol::ARG_1), (t_pred_fn, Symbol::ARG_2)],
var_store,
body,
t_ret,
)
}
/// List.isUnique : List * -> Bool
fn list_is_unique(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_1(symbol, LowLevel::ListIsUnique, var_store)
@ -3720,203 +3357,6 @@ fn num_div_ceil_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
)
}
/// List.first : List elem -> Result elem [ListWasEmpty]*
///
/// List.first :
/// Attr (* | u) (List (Attr u a)),
/// -> Attr * (Result (Attr u a) (Attr * [OutOfBounds]*))
fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bool_var = var_store.fresh();
let list_var = var_store.fresh();
let len_var = Variable::NAT;
let zero_var = len_var;
let zero_precision_var = Variable::NATURAL;
let list_elem_var = var_store.fresh();
let ret_var = var_store.fresh();
// Perform a bounds check. If it passes, delegate to List.getUnsafe.
let body = If {
cond_var: bool_var,
branch_var: var_store.fresh(),
branches: vec![(
// if-condition
no_region(
// List.len list != 0
RunLowLevel {
op: LowLevel::NotEq,
args: vec![
(
len_var,
int::<i128>(zero_var, zero_precision_var, 0, int_no_bound()),
),
(
len_var,
RunLowLevel {
op: LowLevel::ListLen,
args: vec![(list_var, Var(Symbol::ARG_1))],
ret_var: len_var,
},
),
],
ret_var: bool_var,
},
),
// list was not empty
no_region(
// Ok (List.#getUnsafe list 0)
tag(
"Ok",
vec![
// List.#getUnsafe list 0
RunLowLevel {
op: LowLevel::ListGetUnsafe,
args: vec![
(list_var, Var(Symbol::ARG_1)),
(
len_var,
int::<i128>(zero_var, zero_precision_var, 0, int_no_bound()),
),
],
ret_var: list_elem_var,
},
],
var_store,
),
),
)],
final_else: Box::new(
// list was empty
no_region(
// Err ListWasEmpty
tag(
"Err",
vec![tag("ListWasEmpty", Vec::new(), var_store)],
var_store,
),
),
),
};
defn(
symbol,
vec![(list_var, Symbol::ARG_1)],
var_store,
body,
ret_var,
)
}
/// List.last : List elem -> Result elem [ListWasEmpty]*
///
/// List.last :
/// Attr (* | u) (List (Attr u a)),
/// -> Attr * (Result (Attr u a) (Attr * [OutOfBounds]*))
fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
let arg_var = var_store.fresh();
let bool_var = var_store.fresh();
let list_var = var_store.fresh();
let len_var = Variable::NAT;
let num_var = len_var;
let num_precision_var = Variable::NATURAL;
let list_elem_var = var_store.fresh();
let ret_var = var_store.fresh();
// Perform a bounds check. If it passes, delegate to List.getUnsafe.
let body = If {
cond_var: bool_var,
branch_var: var_store.fresh(),
branches: vec![(
// if-condition
no_region(
// List.len list != 0
RunLowLevel {
op: LowLevel::NotEq,
args: vec![
(
len_var,
int::<i128>(num_var, num_precision_var, 0, int_no_bound()),
),
(
len_var,
RunLowLevel {
op: LowLevel::ListLen,
args: vec![(list_var, Var(Symbol::ARG_1))],
ret_var: len_var,
},
),
],
ret_var: bool_var,
},
),
// list was not empty
no_region(
// Ok (List.getUnsafe list (Num.sub (List.len list) 1))
tag(
"Ok",
vec![
// List.getUnsafe list (Num.sub (List.len list) 1)
RunLowLevel {
op: LowLevel::ListGetUnsafe,
args: vec![
(list_var, Var(Symbol::ARG_1)),
(
len_var,
// Num.sub (List.len list) 1
RunLowLevel {
op: LowLevel::NumSubWrap,
args: vec![
(
arg_var,
// List.len list
RunLowLevel {
op: LowLevel::ListLen,
args: vec![(list_var, Var(Symbol::ARG_1))],
ret_var: len_var,
},
),
(
arg_var,
int::<i128>(
num_var,
num_precision_var,
1,
int_no_bound(),
),
),
],
ret_var: len_var,
},
),
],
ret_var: list_elem_var,
},
],
var_store,
),
),
)],
final_else: Box::new(
// list was empty
no_region(
// Err ListWasEmpty
tag(
"Err",
vec![tag("ListWasEmpty", Vec::new(), var_store)],
var_store,
),
),
),
};
defn(
symbol,
vec![(list_var, Symbol::ARG_1)],
var_store,
body,
ret_var,
)
}
fn result_map(symbol: Symbol, var_store: &mut VarStore) -> Def {
let ret_var = var_store.fresh();
let func_var = var_store.fresh();

View File

@ -9,11 +9,10 @@ use crate::llvm::build_dict::{
use crate::llvm::build_hash::generic_hash;
use crate::llvm::build_list::{
self, allocate_list, empty_polymorphic_list, list_all, list_any, list_append, list_concat,
list_contains, list_drop_at, list_find_unsafe, list_get_unsafe, list_join, list_keep_errs,
list_keep_if, list_keep_oks, list_len, list_map, list_map2, list_map3, list_map4,
list_map_with_index, list_prepend, list_range, list_repeat, list_replace_unsafe, list_reverse,
list_single, list_sort_with, list_sublist, list_swap, list_symbol_to_c_abi, list_to_c_abi,
list_with_capacity,
list_drop_at, list_find_unsafe, list_get_unsafe, list_keep_errs, list_keep_if, list_keep_oks,
list_len, list_map, list_map2, list_map3, list_map4, list_map_with_index, list_prepend,
list_replace_unsafe, list_sort_with, list_sublist, list_swap, list_symbol_to_c_abi,
list_to_c_abi, list_with_capacity,
};
use crate::llvm::build_str::{
str_from_float, str_from_int, str_from_utf8, str_from_utf8_range, str_split,
@ -5595,33 +5594,6 @@ fn run_low_level<'a, 'ctx, 'env>(
list_with_capacity(env, list_len, &list_element_layout!(result_layout))
}
ListSingle => {
// List.single : a -> List a
debug_assert_eq!(args.len(), 1);
let (arg, arg_layout) = load_symbol_and_layout(scope, &args[0]);
list_single(env, arg, arg_layout)
}
ListRepeat => {
// List.repeat : elem, Nat -> List elem
debug_assert_eq!(args.len(), 2);
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[0]);
let list_len = load_symbol(scope, &args[1]).into_int_value();
list_repeat(env, layout_ids, elem, elem_layout, list_len)
}
ListReverse => {
// List.reverse : List elem -> List elem
debug_assert_eq!(args.len(), 1);
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
let element_layout = list_element_layout!(list_layout);
list_reverse(env, list, element_layout, update_mode)
}
ListConcat => {
debug_assert_eq!(args.len(), 2);
@ -5633,30 +5605,6 @@ fn run_low_level<'a, 'ctx, 'env>(
list_concat(env, first_list, second_list, element_layout)
}
ListContains => {
// List.contains : List elem, elem -> Bool
debug_assert_eq!(args.len(), 2);
let list = load_symbol(scope, &args[0]);
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]);
list_contains(env, layout_ids, elem, elem_layout, list)
}
ListRange => {
// List.contains : List elem, elem -> Bool
debug_assert_eq!(args.len(), 2);
let (low, low_layout) = load_symbol_and_layout(scope, &args[0]);
let high = load_symbol(scope, &args[1]);
let int_width = match low_layout {
Layout::Builtin(Builtin::Int(int_width)) => *int_width,
_ => unreachable!(),
};
list_range(env, int_width, low.into_int_value(), high.into_int_value())
}
ListAppend => {
// List.append : List elem, elem -> List elem
debug_assert_eq!(args.len(), 2);
@ -5736,17 +5684,6 @@ fn run_low_level<'a, 'ctx, 'env>(
list_prepend(env, original_wrapper, elem, elem_layout)
}
ListJoin => {
// List.join : List (List elem) -> List elem
debug_assert_eq!(args.len(), 1);
let (list, outer_list_layout) = load_symbol_and_layout(scope, &args[0]);
let inner_list_layout = list_element_layout!(outer_list_layout);
let element_layout = list_element_layout!(inner_list_layout);
list_join(env, list, element_layout)
}
ListGetUnsafe => {
// List.get : List elem, Nat -> [Ok elem, OutOfBounds]*
debug_assert_eq!(args.len(), 2);
@ -6226,7 +6163,7 @@ fn run_low_level<'a, 'ctx, 'env>(
ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListKeepIf | ListWalk
| ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith
| ListAny | ListAll | ListFindUnsafe | DictWalk => {
| ListFindUnsafe | DictWalk => {
unreachable!("these are higher order, and are handled elsewhere")
}

View File

@ -1,7 +1,7 @@
#![allow(clippy::too_many_arguments)]
use crate::llvm::bitcode::{
build_dec_wrapper, build_eq_wrapper, build_has_tag_id, build_inc_n_wrapper, build_inc_wrapper,
call_bitcode_fn, call_list_bitcode_fn, call_void_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::{
allocate_with_refcount_help, cast_basic_basic, Env, RocFunctionCall, Scope,
@ -14,7 +14,7 @@ use inkwell::types::{BasicType, BasicTypeEnum, PointerType};
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
use inkwell::{AddressSpace, IntPredicate};
use morphic_lib::UpdateMode;
use roc_builtins::bitcode::{self, IntWidth};
use roc_builtins::bitcode;
use roc_module::symbol::Symbol;
use roc_mono::layout::{Builtin, Layout, LayoutIds};
@ -106,23 +106,6 @@ pub fn pass_as_opaque<'a, 'ctx, 'env>(
)
}
/// List.single : a -> List a
pub fn list_single<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
element: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
call_list_bitcode_fn(
env,
&[
env.alignment_intvalue(element_layout),
pass_element_as_opaque(env, element, *element_layout),
layout_width(env, element_layout),
],
bitcode::LIST_SINGLE,
)
}
pub fn list_with_capacity<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
capacity: IntValue<'ctx>,
@ -162,42 +145,6 @@ pub fn list_repeat<'a, 'ctx, 'env>(
)
}
/// List.join : List (List elem) -> List elem
pub fn list_join<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
outer_list: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
call_list_bitcode_fn(
env,
&[
list_to_c_abi(env, outer_list).into(),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
],
bitcode::LIST_JOIN,
)
}
/// List.reverse : List elem -> List elem
pub fn list_reverse<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
list: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> {
call_list_bitcode_fn(
env,
&[
list_to_c_abi(env, list).into(),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
pass_update_mode(env, update_mode),
],
bitcode::LIST_REVERSE,
)
}
pub fn list_get_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
@ -526,63 +473,6 @@ pub fn list_walk_generic<'a, 'ctx, 'env>(
}
}
/// List.range : Int a, Int a -> List (Int a)
pub fn list_range<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
int_width: IntWidth,
low: IntValue<'ctx>,
high: IntValue<'ctx>,
) -> BasicValueEnum<'ctx> {
let builder = env.builder;
let low_ptr = builder.build_alloca(low.get_type(), "low_ptr");
env.builder.build_store(low_ptr, low);
let high_ptr = builder.build_alloca(high.get_type(), "high_ptr");
env.builder.build_store(high_ptr, high);
let int_width = env
.context
.i8_type()
.const_int(int_width as u64, false)
.into();
call_list_bitcode_fn(
env,
&[
int_width,
pass_as_opaque(env, low_ptr),
pass_as_opaque(env, high_ptr),
],
bitcode::LIST_RANGE,
)
}
/// List.contains : List elem, elem -> Bool
pub fn list_contains<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
element: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
list: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> {
let eq_fn = build_eq_wrapper(env, layout_ids, element_layout)
.as_global_value()
.as_pointer_value()
.into();
call_bitcode_fn(
env,
&[
list_to_c_abi(env, list).into(),
pass_element_as_opaque(env, element, *element_layout),
layout_width(env, element_layout),
eq_fn,
],
bitcode::LIST_CONTAINS,
)
}
/// List.keepIf : List elem, (elem -> Bool) -> List elem
pub fn list_keep_if<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,

View File

@ -5,7 +5,7 @@ use roc_error_macros::internal_error;
use roc_module::low_level::LowLevel;
use roc_module::symbol::Symbol;
use roc_mono::code_gen_help::HelperOp;
use roc_mono::ir::{HigherOrderLowLevel, ListLiteralElement, PassedFunction, ProcLayout};
use roc_mono::ir::{HigherOrderLowLevel, PassedFunction, ProcLayout};
use roc_mono::layout::{Builtin, FieldOrderHash, Layout, UnionLayout};
use roc_mono::low_level::HigherOrder;
@ -290,7 +290,7 @@ impl<'a> LowLevelCall<'a> {
ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListKeepIf | ListWalk
| ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith
| ListAny | ListAll | ListFindUnsafe | DictWalk => {
| ListFindUnsafe | DictWalk => {
internal_error!("HigherOrder lowlevels should not be handled here")
}
@ -419,12 +419,6 @@ impl<'a> LowLevelCall<'a> {
// There is an in-place version of this but we don't use it for dev backends. No morphic_lib analysis.
backend.call_host_fn_after_loading_args(bitcode::LIST_REPLACE, 8, false);
}
ListSingle => {
let elem = self.arguments[0];
let elem_layout = &backend.storage.symbol_layouts[&elem].clone();
let elems = backend.env.arena.alloc([ListLiteralElement::Symbol(elem)]);
backend.expr_array(self.ret_symbol, &self.ret_storage, elem_layout, elems)
}
ListWithCapacity => {
// List.withCapacity : Nat -> List elem
@ -446,72 +440,6 @@ impl<'a> LowLevelCall<'a> {
backend.call_host_fn_after_loading_args(bitcode::LIST_WITH_CAPACITY, 4, false);
}
ListRepeat => {
// List.repeat : elem, Nat -> List elem
let element: Symbol = self.arguments[0];
let count: Symbol = self.arguments[1];
let elem_layout = unwrap_list_elem_layout(self.ret_layout);
let (elem_width, elem_align) = elem_layout.stack_size_and_alignment(TARGET_INFO);
let (elem_local, elem_offset, elem_in_memory_layout) =
ensure_symbol_is_in_memory(backend, element, *elem_layout, backend.env.arena);
let inc_fn = backend.get_refcount_fn_index(elem_in_memory_layout, HelperOp::Inc);
let inc_fn_ptr = backend.get_fn_ptr(inc_fn);
// Zig arguments Wasm types
// (return pointer) i32
// count: usize i32
// alignment: u32 i32
// element: Opaque i32
// element_width: usize i32
// inc_n_element: IncN i32
backend
.storage
.load_symbols(&mut backend.code_builder, &[self.ret_symbol, count]);
backend.code_builder.i32_const(elem_align as i32);
backend.code_builder.get_local(elem_local);
if elem_offset > 0 {
backend.code_builder.i32_const(elem_offset as i32);
backend.code_builder.i32_add();
}
backend.code_builder.i32_const(elem_width as i32);
backend.code_builder.i32_const(inc_fn_ptr);
backend.call_host_fn_after_loading_args(bitcode::LIST_REPEAT, 6, false);
}
ListReverse => {
// List.reverse : List elem -> List elem
// Zig arguments Wasm types
// (return pointer) i32
// list: RocList i64, i32
// alignment: u32 i32
// element_width: usize i32
// update_mode: UpdateMode i32
// Load the arguments that have symbols
backend.storage.load_symbols_for_call(
backend.env.arena,
&mut backend.code_builder,
self.arguments,
self.ret_symbol,
&WasmLayout::new(&self.ret_layout),
CallConv::Zig,
);
// Load monomorphization constants
let elem_layout = unwrap_list_elem_layout(self.ret_layout);
let (elem_width, elem_align) = elem_layout.stack_size_and_alignment(TARGET_INFO);
backend.code_builder.i32_const(elem_align as i32);
backend.code_builder.i32_const(elem_width as i32);
backend.code_builder.i32_const(UPDATE_MODE_IMMUTABLE);
backend.call_host_fn_after_loading_args(bitcode::LIST_REVERSE, 6, false);
}
ListConcat => {
// List.concat : List elem, List elem -> List elem
// Zig arguments Wasm types
@ -539,7 +467,6 @@ impl<'a> LowLevelCall<'a> {
backend.call_host_fn_after_loading_args(bitcode::LIST_CONCAT, 7, false);
}
ListContains => todo!("{:?}", self.lowlevel),
ListAppend => {
// List.append : List elem, elem -> List elem
@ -583,33 +510,6 @@ impl<'a> LowLevelCall<'a> {
backend.call_host_fn_after_loading_args(bitcode::LIST_APPEND, 7, false);
}
ListPrepend => todo!("{:?}", self.lowlevel),
ListJoin => {
// List.join : List (List elem) -> List elem
// Zig arguments Wasm types
// (return pointer) i32
// list_of_lists: RocList i64, i32
// alignment: u32 i32
// element_width: usize i32
// Load the arguments that have symbols
backend.storage.load_symbols_for_call(
backend.env.arena,
&mut backend.code_builder,
self.arguments,
self.ret_symbol,
&WasmLayout::new(&self.ret_layout),
CallConv::Zig,
);
// Load monomorphization constants
let elem_layout = unwrap_list_elem_layout(self.ret_layout);
let (elem_width, elem_align) = elem_layout.stack_size_and_alignment(TARGET_INFO);
backend.code_builder.i32_const(elem_align as i32);
backend.code_builder.i32_const(elem_width as i32);
backend.call_host_fn_after_loading_args(bitcode::LIST_JOIN, 5, false);
}
ListRange => todo!("{:?}", self.lowlevel),
ListSublist => {
// As a low-level, record is destructured
// List.sublist : List elem, start : Nat, len : Nat -> List elem

View File

@ -134,7 +134,9 @@ impl<'a> Storage<'a> {
}
fn allocate_stack_memory(&mut self, size: u32, alignment_bytes: u32) -> u32 {
if self.stack_frame_pointer.is_none() && size > 0 {
// Note: We need a stack frame pointer even if size is zero.
// e.g. when passing an empty record to a Zig builtin, we pass the frame pointer
if self.stack_frame_pointer.is_none() {
let next_local_id = self.get_next_local_id();
self.stack_frame_pointer = Some(next_local_id);
self.local_types.push(PTR_TYPE);

View File

@ -26,16 +26,10 @@ pub enum LowLevel {
ListLen,
ListWithCapacity,
ListGetUnsafe,
ListSingle,
ListRepeat,
ListReplaceUnsafe,
ListReverse,
ListConcat,
ListContains,
ListAppend,
ListPrepend,
ListJoin,
ListRange,
ListMap,
ListMap2,
ListMap3,
@ -51,8 +45,6 @@ pub enum LowLevel {
ListSublist,
ListDropAt,
ListSwap,
ListAny,
ListAll,
ListFindUnsafe,
ListIsUnique,
DictSize,
@ -146,8 +138,6 @@ macro_rules! higher_order {
| ListKeepOks
| ListKeepErrs
| ListSortWith
| ListAny
| ListAll
| ListFindUnsafe
| DictWalk
};
@ -178,8 +168,6 @@ impl LowLevel {
ListKeepOks => 1,
ListKeepErrs => 1,
ListSortWith => 1,
ListAny => 1,
ListAll => 1,
ListFindUnsafe => 1,
DictWalk => 2,
_ => unreachable!(),
@ -236,15 +224,9 @@ impl LowLevelWrapperType {
Symbol::LIST_LEN => CanBeReplacedBy(ListLen),
Symbol::LIST_GET => WrapperIsRequired,
Symbol::LIST_REPLACE => WrapperIsRequired,
Symbol::LIST_SINGLE => CanBeReplacedBy(ListSingle),
Symbol::LIST_REPEAT => CanBeReplacedBy(ListRepeat),
Symbol::LIST_REVERSE => CanBeReplacedBy(ListReverse),
Symbol::LIST_CONCAT => CanBeReplacedBy(ListConcat),
Symbol::LIST_CONTAINS => CanBeReplacedBy(ListContains),
Symbol::LIST_APPEND => CanBeReplacedBy(ListAppend),
Symbol::LIST_PREPEND => CanBeReplacedBy(ListPrepend),
Symbol::LIST_JOIN => CanBeReplacedBy(ListJoin),
Symbol::LIST_RANGE => CanBeReplacedBy(ListRange),
Symbol::LIST_MAP => WrapperIsRequired,
Symbol::LIST_MAP2 => WrapperIsRequired,
Symbol::LIST_MAP3 => WrapperIsRequired,

View File

@ -1254,6 +1254,7 @@ define_builtins! {
60 LIST_GET_UNSAFE: "getUnsafe"
61 LIST_REPLACE_UNSAFE: "replaceUnsafe"
62 LIST_WITH_CAPACITY: "withCapacity"
63 LIST_ITERATE: "iterate"
}
6 RESULT: "Result" => {
0 RESULT_RESULT: "Result" // the Result.Result type alias

View File

@ -907,22 +907,15 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
StrTrimRight => arena.alloc_slice_copy(&[owned]),
StrSplit => arena.alloc_slice_copy(&[borrowed, borrowed]),
StrToNum => arena.alloc_slice_copy(&[borrowed]),
ListSingle => arena.alloc_slice_copy(&[irrelevant]),
// List.repeat : elem, Nat -> List.elem
ListRepeat => arena.alloc_slice_copy(&[borrowed, irrelevant]),
ListReverse => arena.alloc_slice_copy(&[owned]),
ListPrepend => arena.alloc_slice_copy(&[owned, owned]),
StrJoinWith => arena.alloc_slice_copy(&[borrowed, borrowed]),
ListJoin => arena.alloc_slice_copy(&[irrelevant]),
ListMap | ListMapWithIndex => arena.alloc_slice_copy(&[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]),
ListMap4 => arena.alloc_slice_copy(&[owned, owned, owned, owned, function, closure_data]),
ListKeepIf | ListKeepOks | ListKeepErrs | ListAny | ListAll => {
ListKeepIf | ListKeepOks | ListKeepErrs => {
arena.alloc_slice_copy(&[owned, function, closure_data])
}
ListContains => arena.alloc_slice_copy(&[borrowed, irrelevant]),
ListRange => arena.alloc_slice_copy(&[irrelevant, irrelevant]),
ListWalk | ListWalkUntil | ListWalkBackwards => {
arena.alloc_slice_copy(&[owned, owned, function, closure_data])
}

View File

@ -5061,17 +5061,6 @@ pub fn with_hole<'a>(
stmt,
)
}
ListAny => {
debug_assert_eq!(arg_symbols.len(), 2);
let xs = arg_symbols[0];
match_on_closure_argument!(ListAny, [xs])
}
ListAll => {
debug_assert_eq!(arg_symbols.len(), 2);
let xs = arg_symbols[0];
match_on_closure_argument!(ListAll, [xs])
}
ListKeepOks => {
debug_assert_eq!(arg_symbols.len(), 2);
let xs = arg_symbols[0];

View File

@ -132,18 +132,11 @@ enum FirstOrder {
StrFromFloat,
ListLen,
ListGetUnsafe,
ListSet,
ListSublist,
ListDropAt,
ListSingle,
ListRepeat,
ListReverse,
ListConcat,
ListContains,
ListAppend,
ListPrepend,
ListJoin,
ListRange,
ListSwap,
DictSize,
DictEmpty,

View File

@ -809,7 +809,7 @@ fn list_walk_implements_position() {
findHelp = \list, needle ->
List.walkUntil list { n: 0, v: None } \{ n, v }, element ->
if element == needle then
Stop { n, v: Some n }
Break { n, v: Some n }
else
Continue { n: n + 1, v }
@ -832,7 +832,7 @@ fn list_walk_until_even_prefix_sum() {
Continue (a + b)
else
Stop a
Break a
List.walkUntil [2, 4, 8, 9] 0 helper"#,
2 + 4 + 8,
@ -1197,7 +1197,7 @@ fn list_map2_different_lengths() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm"))]
fn list_join_empty_list() {
assert_evals_to!(
"List.join []",
@ -1207,7 +1207,7 @@ fn list_join_empty_list() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm"))]
fn list_join_one_list() {
assert_evals_to!(
"List.join [[1, 2, 3]]",
@ -1217,7 +1217,7 @@ fn list_join_one_list() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm"))]
fn list_join_two_non_empty_lists() {
assert_evals_to!(
"List.join [[1, 2, 3] , [4 ,5, 6]]",
@ -1227,7 +1227,7 @@ fn list_join_two_non_empty_lists() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm"))]
fn list_join_two_non_empty_lists_of_float() {
assert_evals_to!(
"List.join [[1.2, 1.1], [2.1, 2.2]]",
@ -1237,7 +1237,7 @@ fn list_join_two_non_empty_lists_of_float() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm"))]
fn list_join_to_big_list() {
assert_evals_to!(
indoc!(
@ -1263,7 +1263,7 @@ fn list_join_to_big_list() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm"))]
fn list_join_defined_empty_list() {
assert_evals_to!(
indoc!(
@ -1281,7 +1281,7 @@ fn list_join_defined_empty_list() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm"))]
fn list_join_all_empty_lists() {
assert_evals_to!(
"List.join [[], [], []]",
@ -1291,7 +1291,7 @@ fn list_join_all_empty_lists() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm"))]
fn list_join_one_empty_list() {
assert_evals_to!(
"List.join [[1.2, 1.1], []]",
@ -2597,7 +2597,7 @@ fn cleanup_because_exception() {
}
#[test]
#[cfg(any(feature = "gen-llvm"))]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_range() {
assert_evals_to!(
"List.range 0 -1",

View File

@ -2804,7 +2804,7 @@ fn list_walk_until() {
satisfyA = \_ -> []
oneOfResult =
List.walkUntil [satisfyA] [] \_, _ -> Stop []
List.walkUntil [satisfyA] [] \_, _ -> Break []
main =
when oneOfResult is
@ -3004,10 +3004,10 @@ fn do_pass_bool_byte_closure_layout() {
\input ->
walker = \accum, (Pair u rest) ->
if predicate u then
Stop [Pair u rest]
Break [Pair u rest]
else
Stop accum
Break accum
List.walkUntil (any input) [] walker
@ -3019,7 +3019,7 @@ fn do_pass_bool_byte_closure_layout() {
walker = \accum, p ->
output = p input
if List.len output == 1 then
Stop output
Break output
else
Continue accum

View File

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

View File

@ -1,22 +1,22 @@
procedure List.2 (List.67, List.68):
let List.170 : U64 = CallByName List.6 List.67;
let List.166 : Int1 = CallByName Num.22 List.68 List.170;
if List.166 then
let List.168 : {} = CallByName List.60 List.67 List.68;
let List.167 : [C {}, C {}] = Ok List.168;
ret List.167;
procedure List.2 (List.72, List.73):
let List.245 : U64 = CallByName List.6 List.72;
let List.241 : Int1 = CallByName Num.22 List.73 List.245;
if List.241 then
let List.243 : {} = CallByName List.60 List.72 List.73;
let List.242 : [C {}, C {}] = Ok List.243;
ret List.242;
else
let List.165 : {} = Struct {};
let List.164 : [C {}, C {}] = Err List.165;
ret List.164;
let List.240 : {} = Struct {};
let List.239 : [C {}, C {}] = Err List.240;
ret List.239;
procedure List.6 (#Attr.2):
let List.173 : U64 = lowlevel ListLen #Attr.2;
ret List.173;
let List.248 : U64 = lowlevel ListLen #Attr.2;
ret List.248;
procedure List.60 (#Attr.2, #Attr.3):
let List.172 : {} = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.172;
let List.247 : {} = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.247;
procedure Num.22 (#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):
let List.164 : List U8 = lowlevel ListAppend #Attr.2 #Attr.3;
ret List.164;
let List.239 : List U8 = lowlevel ListAppend #Attr.2 #Attr.3;
ret List.239;
procedure Test.20 (Test.22):
let Test.34 : {U8} = Struct {Test.22};

View File

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

View File

@ -1,16 +1,41 @@
procedure List.9 (#Attr.2):
let List.170 : U64 = 0i64;
let List.171 : U64 = lowlevel ListLen #Attr.2;
let List.166 : Int1 = lowlevel NotEq List.170 List.171;
if List.166 then
let List.169 : U64 = 0i64;
let List.168 : I64 = lowlevel ListGetUnsafe #Attr.2 List.169;
let List.167 : [C Int1, C I64] = Ok List.168;
ret List.167;
procedure List.2 (List.72, List.73):
let List.254 : U64 = CallByName List.6 List.72;
let List.250 : Int1 = CallByName Num.22 List.73 List.254;
if List.250 then
let List.252 : I64 = CallByName List.60 List.72 List.73;
let List.251 : [C {}, C I64] = Ok List.252;
ret List.251;
else
let List.165 : Int1 = true;
let List.164 : [C Int1, C I64] = Err List.165;
ret List.164;
let List.249 : {} = Struct {};
let List.248 : [C {}, C I64] = Err List.249;
ret List.248;
procedure List.6 (#Attr.2):
let List.255 : U64 = lowlevel ListLen #Attr.2;
ret List.255;
procedure List.60 (#Attr.2, #Attr.3):
let List.253 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.253;
procedure List.9 (List.166):
let List.246 : U64 = 0i64;
let List.239 : [C {}, C I64] = CallByName List.2 List.166 List.246;
let List.243 : U8 = 1i64;
let List.244 : U8 = GetTagId List.239;
let List.245 : Int1 = lowlevel Eq List.243 List.244;
if List.245 then
let List.167 : I64 = UnionAtIndex (Id 1) (Index 0) List.239;
let List.240 : [C Int1, C I64] = Ok List.167;
ret List.240;
else
let List.242 : Int1 = true;
let List.241 : [C Int1, C I64] = Err List.242;
ret List.241;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
ret Num.273;
procedure Str.27 (#Attr.2):
let #Attr.3 : {I64, U8} = lowlevel StrToNum #Attr.2;

View File

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

View File

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

View File

@ -1,10 +1,10 @@
procedure List.6 (#Attr.2):
let List.164 : U64 = lowlevel ListLen #Attr.2;
ret List.164;
let List.239 : U64 = lowlevel ListLen #Attr.2;
ret List.239;
procedure List.6 (#Attr.2):
let List.165 : U64 = lowlevel ListLen #Attr.2;
ret List.165;
let List.240 : U64 = lowlevel ListLen #Attr.2;
ret List.240;
procedure Num.19 (#Attr.2, #Attr.3):
let Num.273 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;

View File

@ -1,26 +1,26 @@
procedure List.2 (List.67, List.68):
let List.170 : U64 = CallByName List.6 List.67;
let List.166 : Int1 = CallByName Num.22 List.68 List.170;
if List.166 then
let List.168 : Str = CallByName List.60 List.67 List.68;
let List.167 : [C {}, C Str] = Ok List.168;
ret List.167;
procedure List.2 (List.72, List.73):
let List.245 : U64 = CallByName List.6 List.72;
let List.241 : Int1 = CallByName Num.22 List.73 List.245;
if List.241 then
let List.243 : Str = CallByName List.60 List.72 List.73;
let List.242 : [C {}, C Str] = Ok List.243;
ret List.242;
else
let List.165 : {} = Struct {};
let List.164 : [C {}, C Str] = Err List.165;
ret List.164;
let List.240 : {} = Struct {};
let List.239 : [C {}, C Str] = Err List.240;
ret List.239;
procedure List.5 (#Attr.2, #Attr.3):
let List.172 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3;
ret List.172;
let List.247 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3;
ret List.247;
procedure List.6 (#Attr.2):
let List.174 : U64 = lowlevel ListLen #Attr.2;
ret List.174;
let List.249 : U64 = lowlevel ListLen #Attr.2;
ret List.249;
procedure List.60 (#Attr.2, #Attr.3):
let List.173 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.173;
let List.248 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.248;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.273 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View File

@ -1,28 +1,28 @@
procedure List.2 (List.67, List.68):
let List.170 : U64 = CallByName List.6 List.67;
let List.166 : Int1 = CallByName Num.22 List.68 List.170;
if List.166 then
let List.168 : Str = CallByName List.60 List.67 List.68;
let List.167 : [C {}, C Str] = Ok List.168;
ret List.167;
procedure List.2 (List.72, List.73):
let List.245 : U64 = CallByName List.6 List.72;
let List.241 : Int1 = CallByName Num.22 List.73 List.245;
if List.241 then
let List.243 : Str = CallByName List.60 List.72 List.73;
let List.242 : [C {}, C Str] = Ok List.243;
ret List.242;
else
let List.165 : {} = Struct {};
let List.164 : [C {}, C Str] = Err List.165;
ret List.164;
let List.240 : {} = Struct {};
let List.239 : [C {}, C Str] = Err List.240;
ret List.239;
procedure List.5 (#Attr.2, #Attr.3):
inc #Attr.2;
let List.172 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3;
let List.247 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3;
decref #Attr.2;
ret List.172;
ret List.247;
procedure List.6 (#Attr.2):
let List.174 : U64 = lowlevel ListLen #Attr.2;
ret List.174;
let List.249 : U64 = lowlevel ListLen #Attr.2;
ret List.249;
procedure List.60 (#Attr.2, #Attr.3):
let List.173 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.173;
let List.248 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.248;
procedure Num.22 (#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):
let List.167 : List I64 = lowlevel ListSortWith { xs: `#Attr.#arg1` } #Attr.2 Num.46 #Attr.3;
let List.242 : List I64 = lowlevel ListSortWith { xs: `#Attr.#arg1` } #Attr.2 Num.46 #Attr.3;
let Bool.14 : Int1 = lowlevel ListIsUnique #Attr.2;
if Bool.14 then
ret List.167;
ret List.242;
else
decref #Attr.2;
ret List.167;
ret List.242;
procedure List.54 (List.111):
let List.165 : {} = Struct {};
let List.164 : List I64 = CallByName List.28 List.111 List.165;
ret List.164;
procedure List.54 (List.160):
let List.240 : {} = Struct {};
let List.239 : List I64 = CallByName List.28 List.160 List.240;
ret List.239;
procedure Num.46 (#Attr.2, #Attr.3):
let Num.273 : U8 = lowlevel NumCompare #Attr.2 #Attr.3;

View File

@ -1,43 +1,43 @@
procedure List.2 (List.67, List.68):
let List.184 : U64 = CallByName List.6 List.67;
let List.180 : Int1 = CallByName Num.22 List.68 List.184;
if List.180 then
let List.182 : I64 = CallByName List.60 List.67 List.68;
let List.181 : [C {}, C I64] = Ok List.182;
ret List.181;
procedure List.2 (List.72, List.73):
let List.259 : U64 = CallByName List.6 List.72;
let List.255 : Int1 = CallByName Num.22 List.73 List.259;
if List.255 then
let List.257 : I64 = CallByName List.60 List.72 List.73;
let List.256 : [C {}, C I64] = Ok List.257;
ret List.256;
else
let List.179 : {} = Struct {};
let List.178 : [C {}, C I64] = Err List.179;
ret List.178;
let List.254 : {} = Struct {};
let List.253 : [C {}, C I64] = Err List.254;
ret List.253;
procedure List.3 (List.76, List.77, List.78):
let List.168 : {List I64, I64} = CallByName List.57 List.76 List.77 List.78;
let List.167 : List I64 = StructAtIndex 0 List.168;
inc List.167;
dec List.168;
ret List.167;
procedure List.3 (List.81, List.82, List.83):
let List.243 : {List I64, I64} = CallByName List.57 List.81 List.82 List.83;
let List.242 : List I64 = StructAtIndex 0 List.243;
inc List.242;
dec List.243;
ret List.242;
procedure List.57 (List.73, List.74, List.75):
let List.190 : U64 = CallByName List.6 List.73;
let List.187 : Int1 = CallByName Num.22 List.74 List.190;
if List.187 then
let List.188 : {List I64, I64} = CallByName List.61 List.73 List.74 List.75;
ret List.188;
procedure List.57 (List.78, List.79, List.80):
let List.265 : U64 = CallByName List.6 List.78;
let List.262 : Int1 = CallByName Num.22 List.79 List.265;
if List.262 then
let List.263 : {List I64, I64} = CallByName List.61 List.78 List.79 List.80;
ret List.263;
else
let List.186 : {List I64, I64} = Struct {List.73, List.75};
ret List.186;
let List.261 : {List I64, I64} = Struct {List.78, List.80};
ret List.261;
procedure List.6 (#Attr.2):
let List.191 : U64 = lowlevel ListLen #Attr.2;
ret List.191;
let List.266 : U64 = lowlevel ListLen #Attr.2;
ret List.266;
procedure List.60 (#Attr.2, #Attr.3):
let List.192 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.192;
let List.267 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.267;
procedure List.61 (#Attr.2, #Attr.3, #Attr.4):
let List.189 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.189;
let List.264 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.264;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View File

@ -1,43 +1,43 @@
procedure List.2 (List.67, List.68):
let List.184 : U64 = CallByName List.6 List.67;
let List.180 : Int1 = CallByName Num.22 List.68 List.184;
if List.180 then
let List.182 : I64 = CallByName List.60 List.67 List.68;
let List.181 : [C {}, C I64] = Ok List.182;
ret List.181;
procedure List.2 (List.72, List.73):
let List.259 : U64 = CallByName List.6 List.72;
let List.255 : Int1 = CallByName Num.22 List.73 List.259;
if List.255 then
let List.257 : I64 = CallByName List.60 List.72 List.73;
let List.256 : [C {}, C I64] = Ok List.257;
ret List.256;
else
let List.179 : {} = Struct {};
let List.178 : [C {}, C I64] = Err List.179;
ret List.178;
let List.254 : {} = Struct {};
let List.253 : [C {}, C I64] = Err List.254;
ret List.253;
procedure List.3 (List.76, List.77, List.78):
let List.168 : {List I64, I64} = CallByName List.57 List.76 List.77 List.78;
let List.167 : List I64 = StructAtIndex 0 List.168;
inc List.167;
dec List.168;
ret List.167;
procedure List.3 (List.81, List.82, List.83):
let List.243 : {List I64, I64} = CallByName List.57 List.81 List.82 List.83;
let List.242 : List I64 = StructAtIndex 0 List.243;
inc List.242;
dec List.243;
ret List.242;
procedure List.57 (List.73, List.74, List.75):
let List.190 : U64 = CallByName List.6 List.73;
let List.187 : Int1 = CallByName Num.22 List.74 List.190;
if List.187 then
let List.188 : {List I64, I64} = CallByName List.61 List.73 List.74 List.75;
ret List.188;
procedure List.57 (List.78, List.79, List.80):
let List.265 : U64 = CallByName List.6 List.78;
let List.262 : Int1 = CallByName Num.22 List.79 List.265;
if List.262 then
let List.263 : {List I64, I64} = CallByName List.61 List.78 List.79 List.80;
ret List.263;
else
let List.186 : {List I64, I64} = Struct {List.73, List.75};
ret List.186;
let List.261 : {List I64, I64} = Struct {List.78, List.80};
ret List.261;
procedure List.6 (#Attr.2):
let List.191 : U64 = lowlevel ListLen #Attr.2;
ret List.191;
let List.266 : U64 = lowlevel ListLen #Attr.2;
ret List.266;
procedure List.60 (#Attr.2, #Attr.3):
let List.192 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.192;
let List.267 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.267;
procedure List.61 (#Attr.2, #Attr.3, #Attr.4):
let List.189 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.189;
let List.264 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4;
ret List.264;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;

View File

@ -465,8 +465,8 @@ mod test_reporting {
List.isEmpty
List.set
List.iterate
List.get
List.keepIf
"#
),
)