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

@ -1086,6 +1086,23 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(list_type(flex(TVAR1))),
);
// find : List elem, (elem -> Bool) -> Result elem [ NotFound ]*
{
let not_found = SolvedType::TagUnion(
vec![(TagName::Global("NotFound".into()), vec![])],
Box::new(SolvedType::Wildcard),
);
let (elem, cvar) = (TVAR1, TVAR2);
add_top_level_function_type!(
Symbol::LIST_FIND,
vec![
list_type(flex(elem)),
closure(vec![flex(elem)], cvar, Box::new(bool_type())),
],
Box::new(result_type(flex(elem), not_found)),
)
}
// Dict module
// len : Dict * * -> Nat