mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 16:21:11 +00:00
Merge branch 'trunk' into add-num-log
This commit is contained in:
commit
51e7720658
10 changed files with 180 additions and 71 deletions
|
@ -8,8 +8,8 @@ To build the compiler, you need these installed:
|
||||||
* `libunwind` (macOS should already have this one installed)
|
* `libunwind` (macOS should already have this one installed)
|
||||||
* `libc++-dev`
|
* `libc++-dev`
|
||||||
* Python 2.7 (Windows only), `python-is-python3` (Ubuntu)
|
* Python 2.7 (Windows only), `python-is-python3` (Ubuntu)
|
||||||
* [Zig](https://ziglang.org/) 0.7.1 or greater
|
* [Zig](https://ziglang.org/), see below for version
|
||||||
* a particular version of LLVM (see below)
|
* LLVM, see below for version
|
||||||
|
|
||||||
To run the test suite (via `cargo test`), you additionally need to install:
|
To run the test suite (via `cargo test`), you additionally need to install:
|
||||||
|
|
||||||
|
@ -24,12 +24,14 @@ MacOS systems should already have `libunwind`, but other systems will need to in
|
||||||
Some systems may already have `libc++-dev` on them, but if not, you may need to install it. (On Ubuntu, this can be done with `sudo apt-get install libc++-dev`.)
|
Some systems may already have `libc++-dev` on them, but if not, you may need to install it. (On Ubuntu, this can be done with `sudo apt-get install libc++-dev`.)
|
||||||
|
|
||||||
### Zig
|
### Zig
|
||||||
|
**version: 0.7.x**
|
||||||
|
|
||||||
If you're on MacOS, you can install with `brew install zig`
|
If you're on MacOS, you can install with `brew install zig`
|
||||||
If you're on Ubuntu and use Snap, you can install with `snap install zig --classic --beta`
|
If you're on Ubuntu and use Snap, you can install with `snap install zig --classic --beta`
|
||||||
For any other OS, checkout the [Zig installation page](https://github.com/ziglang/zig/wiki/Install-Zig-from-a-Package-Manager)
|
For any other OS, checkout the [Zig installation page](https://github.com/ziglang/zig/wiki/Install-Zig-from-a-Package-Manager)
|
||||||
|
|
||||||
### LLVM
|
### LLVM
|
||||||
|
**version: 10.0.x**
|
||||||
|
|
||||||
For Ubuntu and Debian, you can use the `Automatic installation script` at [apt.llvm.org](https://apt.llvm.org):
|
For Ubuntu and Debian, you can use the `Automatic installation script` at [apt.llvm.org](https://apt.llvm.org):
|
||||||
```
|
```
|
||||||
|
|
|
@ -736,6 +736,15 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// product : List (Num a) -> Num a
|
||||||
|
add_type(
|
||||||
|
Symbol::LIST_PRODUCT,
|
||||||
|
top_level_function(
|
||||||
|
vec![list_type(num_type(flex(TVAR1)))],
|
||||||
|
Box::new(num_type(flex(TVAR1))),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
// walk : List elem, (elem -> accum -> accum), accum -> accum
|
// walk : List elem, (elem -> accum -> accum), accum -> accum
|
||||||
add_type(
|
add_type(
|
||||||
Symbol::LIST_WALK,
|
Symbol::LIST_WALK,
|
||||||
|
|
|
@ -77,6 +77,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
|
||||||
LIST_CONCAT => list_concat,
|
LIST_CONCAT => list_concat,
|
||||||
LIST_CONTAINS => list_contains,
|
LIST_CONTAINS => list_contains,
|
||||||
LIST_SUM => list_sum,
|
LIST_SUM => list_sum,
|
||||||
|
LIST_PRODUCT => list_product,
|
||||||
LIST_PREPEND => list_prepend,
|
LIST_PREPEND => list_prepend,
|
||||||
LIST_JOIN => list_join,
|
LIST_JOIN => list_join,
|
||||||
LIST_MAP => list_map,
|
LIST_MAP => list_map,
|
||||||
|
@ -218,6 +219,7 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Def> {
|
||||||
Symbol::LIST_CONCAT => list_concat,
|
Symbol::LIST_CONCAT => list_concat,
|
||||||
Symbol::LIST_CONTAINS => list_contains,
|
Symbol::LIST_CONTAINS => list_contains,
|
||||||
Symbol::LIST_SUM => list_sum,
|
Symbol::LIST_SUM => list_sum,
|
||||||
|
Symbol::LIST_PRODUCT => list_product,
|
||||||
Symbol::LIST_PREPEND => list_prepend,
|
Symbol::LIST_PREPEND => list_prepend,
|
||||||
Symbol::LIST_JOIN => list_join,
|
Symbol::LIST_JOIN => list_join,
|
||||||
Symbol::LIST_MAP => list_map,
|
Symbol::LIST_MAP => list_map,
|
||||||
|
@ -413,8 +415,8 @@ fn lowlevel_4(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
||||||
/// Num.maxInt : Int
|
/// Num.maxInt : Int
|
||||||
fn num_max_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_max_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let int_var = var_store.fresh();
|
let int_var = var_store.fresh();
|
||||||
let int_percision_var = var_store.fresh();
|
let int_precision_var = var_store.fresh();
|
||||||
let body = Int(int_var, int_percision_var, i64::MAX.into());
|
let body = Int(int_var, int_precision_var, i64::MAX.into());
|
||||||
|
|
||||||
Def {
|
Def {
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -428,8 +430,8 @@ fn num_max_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
/// Num.minInt : Int
|
/// Num.minInt : Int
|
||||||
fn num_min_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_min_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let int_var = var_store.fresh();
|
let int_var = var_store.fresh();
|
||||||
let int_percision_var = var_store.fresh();
|
let int_precision_var = var_store.fresh();
|
||||||
let body = Int(int_var, int_percision_var, i64::MIN.into());
|
let body = Int(int_var, int_precision_var, i64::MIN.into());
|
||||||
|
|
||||||
Def {
|
Def {
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -1133,50 +1135,36 @@ fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let bool_var = var_store.fresh();
|
let bool_var = var_store.fresh();
|
||||||
let float_var = var_store.fresh();
|
let float_var = var_store.fresh();
|
||||||
let unbound_zero_var = var_store.fresh();
|
let unbound_zero_var = var_store.fresh();
|
||||||
let percision_var = var_store.fresh();
|
let precision_var = var_store.fresh();
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
|
|
||||||
let body = If {
|
let body = If {
|
||||||
branch_var: ret_var,
|
branch_var: ret_var,
|
||||||
cond_var: bool_var,
|
cond_var: bool_var,
|
||||||
branches: vec![(
|
branches: vec![(
|
||||||
// if-condition
|
no_region(RunLowLevel {
|
||||||
no_region(
|
op: LowLevel::NumGte,
|
||||||
// Num.neq denominator 0
|
args: vec![
|
||||||
RunLowLevel {
|
(float_var, Var(Symbol::ARG_1)),
|
||||||
op: LowLevel::NotEq,
|
(float_var, Float(unbound_zero_var, precision_var, 0.0)),
|
||||||
args: vec![
|
],
|
||||||
(float_var, Var(Symbol::ARG_1)),
|
ret_var: bool_var,
|
||||||
(float_var, Float(unbound_zero_var, percision_var, 0.0)),
|
}),
|
||||||
],
|
|
||||||
ret_var: bool_var,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
// denominator was not zero
|
|
||||||
no_region(
|
|
||||||
// Ok (Float.#divUnchecked numerator denominator)
|
|
||||||
tag(
|
|
||||||
"Ok",
|
|
||||||
vec![
|
|
||||||
// Num.#divUnchecked numerator denominator
|
|
||||||
RunLowLevel {
|
|
||||||
op: LowLevel::NumSqrtUnchecked,
|
|
||||||
args: vec![(float_var, Var(Symbol::ARG_1))],
|
|
||||||
ret_var: float_var,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
var_store,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)],
|
|
||||||
final_else: Box::new(
|
|
||||||
// denominator was zero
|
|
||||||
no_region(tag(
|
no_region(tag(
|
||||||
"Err",
|
"Ok",
|
||||||
vec![tag("DivByZero", Vec::new(), var_store)],
|
vec![RunLowLevel {
|
||||||
|
op: LowLevel::NumSqrtUnchecked,
|
||||||
|
args: vec![(float_var, Var(Symbol::ARG_1))],
|
||||||
|
ret_var: float_var,
|
||||||
|
}],
|
||||||
var_store,
|
var_store,
|
||||||
)),
|
)),
|
||||||
),
|
)],
|
||||||
|
final_else: Box::new(no_region(tag(
|
||||||
|
"Err",
|
||||||
|
vec![tag("SqrtOfNegative", Vec::new(), var_store)],
|
||||||
|
var_store,
|
||||||
|
))),
|
||||||
};
|
};
|
||||||
|
|
||||||
defn(
|
defn(
|
||||||
|
@ -1433,8 +1421,8 @@ fn num_int_cast(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
/// Num.maxI128: I128
|
/// Num.maxI128: I128
|
||||||
fn num_max_i128(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_max_i128(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let int_var = var_store.fresh();
|
let int_var = var_store.fresh();
|
||||||
let int_percision_var = var_store.fresh();
|
let int_precision_var = var_store.fresh();
|
||||||
let body = Int(int_var, int_percision_var, i128::MAX);
|
let body = Int(int_var, int_precision_var, i128::MAX);
|
||||||
|
|
||||||
let std = roc_builtins::std::types();
|
let std = roc_builtins::std::types();
|
||||||
let solved = std.get(&symbol).unwrap();
|
let solved = std.get(&symbol).unwrap();
|
||||||
|
@ -2164,22 +2152,12 @@ fn list_walk_backwards(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
|
||||||
/// List.sum : List (Num a) -> Num a
|
/// List.sum : List (Num a) -> Num a
|
||||||
fn list_sum(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn list_sum(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let list_var = var_store.fresh();
|
lowlevel_1(symbol, LowLevel::ListSum, var_store)
|
||||||
let result_var = var_store.fresh();
|
}
|
||||||
|
|
||||||
let body = RunLowLevel {
|
/// List.product : List (Num a) -> Num a
|
||||||
op: LowLevel::ListSum,
|
fn list_product(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
args: vec![(list_var, Var(Symbol::ARG_1))],
|
lowlevel_1(symbol, LowLevel::ListProduct, var_store)
|
||||||
ret_var: result_var,
|
|
||||||
};
|
|
||||||
|
|
||||||
defn(
|
|
||||||
symbol,
|
|
||||||
vec![(list_var, Symbol::ARG_1)],
|
|
||||||
var_store,
|
|
||||||
body,
|
|
||||||
result_var,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List.keepIf : List elem, (elem -> Bool) -> List elem
|
/// List.keepIf : List elem, (elem -> Bool) -> List elem
|
||||||
|
@ -2709,7 +2687,7 @@ fn num_div_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let bool_var = var_store.fresh();
|
let bool_var = var_store.fresh();
|
||||||
let num_var = var_store.fresh();
|
let num_var = var_store.fresh();
|
||||||
let unbound_zero_var = var_store.fresh();
|
let unbound_zero_var = var_store.fresh();
|
||||||
let percision_var = var_store.fresh();
|
let precision_var = var_store.fresh();
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
|
|
||||||
let body = If {
|
let body = If {
|
||||||
|
@ -2723,7 +2701,7 @@ fn num_div_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
op: LowLevel::NotEq,
|
op: LowLevel::NotEq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(num_var, Var(Symbol::ARG_2)),
|
(num_var, Var(Symbol::ARG_2)),
|
||||||
(num_var, Float(unbound_zero_var, percision_var, 0.0)),
|
(num_var, Float(unbound_zero_var, precision_var, 0.0)),
|
||||||
],
|
],
|
||||||
ret_var: bool_var,
|
ret_var: bool_var,
|
||||||
},
|
},
|
||||||
|
@ -2772,7 +2750,7 @@ fn num_div_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let bool_var = var_store.fresh();
|
let bool_var = var_store.fresh();
|
||||||
let num_var = var_store.fresh();
|
let num_var = var_store.fresh();
|
||||||
let unbound_zero_var = var_store.fresh();
|
let unbound_zero_var = var_store.fresh();
|
||||||
let unbound_zero_percision_var = var_store.fresh();
|
let unbound_zero_precision_var = var_store.fresh();
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
|
|
||||||
let body = If {
|
let body = If {
|
||||||
|
@ -2788,7 +2766,7 @@ fn num_div_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
(num_var, Var(Symbol::ARG_2)),
|
(num_var, Var(Symbol::ARG_2)),
|
||||||
(
|
(
|
||||||
num_var,
|
num_var,
|
||||||
Int(unbound_zero_var, unbound_zero_percision_var, 0),
|
Int(unbound_zero_var, unbound_zero_precision_var, 0),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
ret_var: bool_var,
|
ret_var: bool_var,
|
||||||
|
@ -2843,7 +2821,7 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let list_var = var_store.fresh();
|
let list_var = var_store.fresh();
|
||||||
let len_var = var_store.fresh();
|
let len_var = var_store.fresh();
|
||||||
let zero_var = var_store.fresh();
|
let zero_var = var_store.fresh();
|
||||||
let zero_percision_var = var_store.fresh();
|
let zero_precision_var = var_store.fresh();
|
||||||
let list_elem_var = var_store.fresh();
|
let list_elem_var = var_store.fresh();
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
|
|
||||||
|
@ -2858,7 +2836,7 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
RunLowLevel {
|
RunLowLevel {
|
||||||
op: LowLevel::NotEq,
|
op: LowLevel::NotEq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(len_var, Int(zero_var, zero_percision_var, 0)),
|
(len_var, Int(zero_var, zero_precision_var, 0)),
|
||||||
(
|
(
|
||||||
len_var,
|
len_var,
|
||||||
RunLowLevel {
|
RunLowLevel {
|
||||||
|
@ -2882,7 +2860,7 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
op: LowLevel::ListGetUnsafe,
|
op: LowLevel::ListGetUnsafe,
|
||||||
args: vec![
|
args: vec![
|
||||||
(list_var, Var(Symbol::ARG_1)),
|
(list_var, Var(Symbol::ARG_1)),
|
||||||
(len_var, Int(zero_var, zero_percision_var, 0)),
|
(len_var, Int(zero_var, zero_precision_var, 0)),
|
||||||
],
|
],
|
||||||
ret_var: list_elem_var,
|
ret_var: list_elem_var,
|
||||||
},
|
},
|
||||||
|
@ -2924,7 +2902,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let list_var = var_store.fresh();
|
let list_var = var_store.fresh();
|
||||||
let len_var = var_store.fresh();
|
let len_var = var_store.fresh();
|
||||||
let num_var = var_store.fresh();
|
let num_var = var_store.fresh();
|
||||||
let num_percision_var = var_store.fresh();
|
let num_precision_var = var_store.fresh();
|
||||||
let list_elem_var = var_store.fresh();
|
let list_elem_var = var_store.fresh();
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
|
|
||||||
|
@ -2939,7 +2917,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
RunLowLevel {
|
RunLowLevel {
|
||||||
op: LowLevel::NotEq,
|
op: LowLevel::NotEq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(len_var, Int(num_var, num_percision_var, 0)),
|
(len_var, Int(num_var, num_precision_var, 0)),
|
||||||
(
|
(
|
||||||
len_var,
|
len_var,
|
||||||
RunLowLevel {
|
RunLowLevel {
|
||||||
|
@ -2978,7 +2956,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
ret_var: len_var,
|
ret_var: len_var,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(arg_var, Int(num_var, num_percision_var, 1)),
|
(arg_var, Int(num_var, num_precision_var, 1)),
|
||||||
],
|
],
|
||||||
ret_var: len_var,
|
ret_var: len_var,
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,8 +7,8 @@ use crate::llvm::build_hash::generic_hash;
|
||||||
use crate::llvm::build_list::{
|
use crate::llvm::build_list::{
|
||||||
allocate_list, empty_list, empty_polymorphic_list, list_append, list_concat, list_contains,
|
allocate_list, empty_list, empty_polymorphic_list, list_append, list_concat, list_contains,
|
||||||
list_get_unsafe, list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len, list_map,
|
list_get_unsafe, list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len, list_map,
|
||||||
list_map2, list_map3, list_map_with_index, list_prepend, list_repeat, list_reverse, list_set,
|
list_map2, list_map3, list_map_with_index, list_prepend, list_product, list_repeat,
|
||||||
list_single, list_sum, list_walk, list_walk_backwards,
|
list_reverse, list_set, list_single, list_sum, list_walk, list_walk_backwards,
|
||||||
};
|
};
|
||||||
use crate::llvm::build_str::{
|
use crate::llvm::build_str::{
|
||||||
str_concat, str_count_graphemes, str_ends_with, str_from_float, str_from_int, str_from_utf8,
|
str_concat, str_count_graphemes, str_ends_with, str_from_float, str_from_int, str_from_utf8,
|
||||||
|
@ -3937,6 +3937,13 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
list_sum(env, parent, list, layout)
|
list_sum(env, parent, list, layout)
|
||||||
}
|
}
|
||||||
|
ListProduct => {
|
||||||
|
debug_assert_eq!(args.len(), 1);
|
||||||
|
|
||||||
|
let list = load_symbol(scope, &args[0]);
|
||||||
|
|
||||||
|
list_product(env, parent, list, layout)
|
||||||
|
}
|
||||||
ListAppend => {
|
ListAppend => {
|
||||||
// List.append : List elem, elem -> List elem
|
// List.append : List elem, elem -> List elem
|
||||||
debug_assert_eq!(args.len(), 2);
|
debug_assert_eq!(args.len(), 2);
|
||||||
|
|
|
@ -788,6 +788,81 @@ pub fn list_sum<'a, 'ctx, 'env>(
|
||||||
builder.build_load(accum_alloca, "load_final_acum")
|
builder.build_load(accum_alloca, "load_final_acum")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// List.product : List (Num a) -> Num a
|
||||||
|
pub fn list_product<'a, 'ctx, 'env>(
|
||||||
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
parent: FunctionValue<'ctx>,
|
||||||
|
list: BasicValueEnum<'ctx>,
|
||||||
|
default_layout: &Layout<'a>,
|
||||||
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let ctx = env.context;
|
||||||
|
let builder = env.builder;
|
||||||
|
|
||||||
|
let list_wrapper = list.into_struct_value();
|
||||||
|
let len = list_len(env.builder, list_wrapper);
|
||||||
|
|
||||||
|
let accum_type = basic_type_from_layout(env.arena, ctx, default_layout, env.ptr_bytes);
|
||||||
|
let accum_alloca = builder.build_alloca(accum_type, "alloca_walk_right_accum");
|
||||||
|
|
||||||
|
let default: BasicValueEnum = match accum_type {
|
||||||
|
BasicTypeEnum::IntType(int_type) => int_type.const_int(1, false).into(),
|
||||||
|
BasicTypeEnum::FloatType(float_type) => float_type.const_float(1.0).into(),
|
||||||
|
_ => unreachable!(""),
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.build_store(accum_alloca, default);
|
||||||
|
|
||||||
|
let then_block = ctx.append_basic_block(parent, "then");
|
||||||
|
let cont_block = ctx.append_basic_block(parent, "branchcont");
|
||||||
|
|
||||||
|
let condition = builder.build_int_compare(
|
||||||
|
IntPredicate::UGT,
|
||||||
|
len,
|
||||||
|
ctx.i64_type().const_zero(),
|
||||||
|
"list_non_empty",
|
||||||
|
);
|
||||||
|
|
||||||
|
builder.build_conditional_branch(condition, then_block, cont_block);
|
||||||
|
|
||||||
|
builder.position_at_end(then_block);
|
||||||
|
|
||||||
|
let elem_ptr_type = get_ptr_type(&accum_type, AddressSpace::Generic);
|
||||||
|
let list_ptr = load_list_ptr(builder, list_wrapper, elem_ptr_type);
|
||||||
|
|
||||||
|
let walk_right_loop = |_, elem: BasicValueEnum<'ctx>| {
|
||||||
|
// load current accumulator
|
||||||
|
let current = builder.build_load(accum_alloca, "retrieve_accum");
|
||||||
|
|
||||||
|
let new_current = build_num_binop(
|
||||||
|
env,
|
||||||
|
parent,
|
||||||
|
current,
|
||||||
|
default_layout,
|
||||||
|
elem,
|
||||||
|
default_layout,
|
||||||
|
roc_module::low_level::LowLevel::NumMul,
|
||||||
|
);
|
||||||
|
|
||||||
|
builder.build_store(accum_alloca, new_current);
|
||||||
|
};
|
||||||
|
|
||||||
|
incrementing_elem_loop(
|
||||||
|
builder,
|
||||||
|
ctx,
|
||||||
|
parent,
|
||||||
|
list_ptr,
|
||||||
|
len,
|
||||||
|
"#index",
|
||||||
|
walk_right_loop,
|
||||||
|
);
|
||||||
|
|
||||||
|
builder.build_unconditional_branch(cont_block);
|
||||||
|
|
||||||
|
builder.position_at_end(cont_block);
|
||||||
|
|
||||||
|
builder.build_load(accum_alloca, "load_final_acum")
|
||||||
|
}
|
||||||
|
|
||||||
/// List.walk : List elem, (elem -> accum -> accum), accum -> accum
|
/// List.walk : List elem, (elem -> accum -> accum), accum -> accum
|
||||||
pub fn list_walk<'a, 'ctx, 'env>(
|
pub fn list_walk<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
|
|
@ -34,6 +34,7 @@ pub enum LowLevel {
|
||||||
ListWalk,
|
ListWalk,
|
||||||
ListWalkBackwards,
|
ListWalkBackwards,
|
||||||
ListSum,
|
ListSum,
|
||||||
|
ListProduct,
|
||||||
ListKeepOks,
|
ListKeepOks,
|
||||||
ListKeepErrs,
|
ListKeepErrs,
|
||||||
DictSize,
|
DictSize,
|
||||||
|
|
|
@ -914,6 +914,7 @@ define_builtins! {
|
||||||
23 LIST_MAP_WITH_INDEX: "mapWithIndex"
|
23 LIST_MAP_WITH_INDEX: "mapWithIndex"
|
||||||
24 LIST_MAP2: "map2"
|
24 LIST_MAP2: "map2"
|
||||||
25 LIST_MAP3: "map3"
|
25 LIST_MAP3: "map3"
|
||||||
|
26 LIST_PRODUCT: "product"
|
||||||
}
|
}
|
||||||
5 RESULT: "Result" => {
|
5 RESULT: "Result" => {
|
||||||
0 RESULT_RESULT: "Result" imported // the Result.Result type alias
|
0 RESULT_RESULT: "Result" imported // the Result.Result type alias
|
||||||
|
|
|
@ -657,7 +657,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
|
||||||
ListContains => arena.alloc_slice_copy(&[borrowed, irrelevant]),
|
ListContains => arena.alloc_slice_copy(&[borrowed, irrelevant]),
|
||||||
ListWalk => arena.alloc_slice_copy(&[owned, irrelevant, owned]),
|
ListWalk => arena.alloc_slice_copy(&[owned, irrelevant, owned]),
|
||||||
ListWalkBackwards => arena.alloc_slice_copy(&[owned, irrelevant, owned]),
|
ListWalkBackwards => arena.alloc_slice_copy(&[owned, irrelevant, owned]),
|
||||||
ListSum => arena.alloc_slice_copy(&[borrowed]),
|
ListSum | ListProduct => arena.alloc_slice_copy(&[borrowed]),
|
||||||
|
|
||||||
// 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
|
||||||
|
|
|
@ -1760,6 +1760,13 @@ fn list_sum() {
|
||||||
assert_evals_to!("List.sum [ 1.1, 2.2, 3.3 ]", 6.6, f64);
|
assert_evals_to!("List.sum [ 1.1, 2.2, 3.3 ]", 6.6, f64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn list_product() {
|
||||||
|
assert_evals_to!("List.product []", 1, i64);
|
||||||
|
assert_evals_to!("List.product [ 1, 2, 3 ]", 6, i64);
|
||||||
|
assert_evals_to!("List.product [ 1.1, 2.2, 3.3 ]", 1.1 * 2.2 * 3.3, f64);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn list_keep_oks() {
|
fn list_keep_oks() {
|
||||||
assert_evals_to!("List.keepOks [] (\\x -> x)", 0, i64);
|
assert_evals_to!("List.keepOks [] (\\x -> x)", 0, i64);
|
||||||
|
|
|
@ -389,6 +389,35 @@ mod gen_num {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn f64_sqrt_zero() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
when Num.sqrt 0 is
|
||||||
|
Ok val -> val
|
||||||
|
Err _ -> -1
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0.0,
|
||||||
|
f64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn f64_sqrt_negative() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
when Num.sqrt -1 is
|
||||||
|
Err _ -> 42
|
||||||
|
Ok val -> val
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
42.0,
|
||||||
|
f64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f64_round_old() {
|
fn f64_round_old() {
|
||||||
assert_evals_to!("Num.round 3.6", 4, i64);
|
assert_evals_to!("Num.round 3.6", 4, i64);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue