Implement List.find

`List.find : List elem, (elem -> Bool) -> Result elem [ NotFound ]*`
behaves as follows:

```
>>> List.find [1, 2, 3] (\n -> n > 2)
Ok 2
>>> List.find [1, 2, 3] (\n -> n > 4)
Err NotFound
```

We implement this as builtin in two phases. First, we call out to a
pure-llvm-lowlevel `ListFindUnsafe` that returns a record indicating
whether a satisfying element was found, and the value of that element
(the value is all null bytes if the element wasn't found). Then, we lift
that record to a `Result` via a standard construction of the can AST.

Closes #1909
This commit is contained in:
ayazhafiz 2021-11-07 20:56:46 -05:00
parent 35df58c18f
commit f65b174ab5
16 changed files with 417 additions and 8 deletions

View file

@ -2281,7 +2281,7 @@ fn list_join_map() {
RocStr::from_slice("cyrus".as_bytes()),
]),
RocList<RocStr>
);
)
}
#[test]
@ -2294,5 +2294,64 @@ fn list_join_map_empty() {
),
RocList::from_slice(&[]),
RocList<RocStr>
)
}
#[test]
fn list_find() {
assert_evals_to!(
indoc!(
r#"
when List.find ["a", "bc", "def"] (\s -> Str.countGraphemes s > 1) is
Ok v -> v
Err _ -> "not found"
"#
),
RocStr::from_slice(b"bc"),
RocStr
);
}
#[test]
fn list_find_not_found() {
assert_evals_to!(
indoc!(
r#"
when List.find ["a", "bc", "def"] (\s -> Str.countGraphemes s > 5) is
Ok v -> v
Err _ -> "not found"
"#
),
RocStr::from_slice(b"not found"),
RocStr
);
}
#[test]
fn list_find_empty_typed_list() {
assert_evals_to!(
indoc!(
r#"
when List.find [] (\s -> Str.countGraphemes s > 5) is
Ok v -> v
Err _ -> "not found"
"#
),
RocStr::from_slice(b"not found"),
RocStr
);
}
#[test]
#[ignore = "Fails because monomorphization can't be done if we don't have a concrete element type!"]
fn list_find_empty_layout() {
assert_evals_to!(
indoc!(
r#"
List.find [] (\_ -> True)
"#
),
0,
i64
);
}