feat: adds Num.mulWrap and Num.mulChecked

This commit is contained in:
Celso Bonutti Filho 2020-12-23 13:42:18 -03:00
parent d3d3497b46
commit f3bd5368f0
7 changed files with 162 additions and 4 deletions

View file

@ -85,6 +85,8 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
NUM_SUB_WRAP => num_sub_wrap,
NUM_SUB_CHECKED => num_sub_checked,
NUM_MUL => num_mul,
NUM_MUL_WRAP => num_mul_wrap,
NUM_MUL_CHECKED => num_mul_checked,
NUM_GT => num_gt,
NUM_GTE => num_gte,
NUM_LT => num_lt,
@ -573,6 +575,100 @@ fn num_mul(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_binop(symbol, var_store, LowLevel::NumMul)
}
/// Num.mulWrap : Int, Int -> Int
fn num_mul_wrap(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_binop(symbol, var_store, LowLevel::NumMulWrap)
}
/// Num.mulChecked : Num a, Num a -> Result (Num a) [ Overflow ]*
fn num_mul_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bool_var = var_store.fresh();
let num_var_1 = var_store.fresh();
let num_var_2 = var_store.fresh();
let num_var_3 = var_store.fresh();
let ret_var = var_store.fresh();
let record_var = var_store.fresh();
// let arg_3 = RunLowLevel NumMulChecked arg_1 arg_2
//
// if arg_3.b then
// # overflow
// Err Overflow
// else
// # all is well
// Ok arg_3.a
let cont = If {
branch_var: ret_var,
cond_var: bool_var,
branches: vec![(
// if-condition
no_region(
// arg_3.b
Access {
record_var,
ext_var: var_store.fresh(),
field: "b".into(),
field_var: var_store.fresh(),
loc_expr: Box::new(no_region(Var(Symbol::ARG_3))),
},
),
// overflow!
no_region(tag(
"Err",
vec![tag("Overflow", Vec::new(), var_store)],
var_store,
)),
)],
final_else: Box::new(
// all is well
no_region(
// Ok arg_3.a
tag(
"Ok",
vec![
// arg_3.a
Access {
record_var,
ext_var: var_store.fresh(),
field: "a".into(),
field_var: num_var_3,
loc_expr: Box::new(no_region(Var(Symbol::ARG_3))),
},
],
var_store,
),
),
),
};
// arg_3 = RunLowLevel NumMulChecked arg_1 arg_2
let def = crate::def::Def {
loc_pattern: no_region(Pattern::Identifier(Symbol::ARG_3)),
loc_expr: no_region(RunLowLevel {
op: LowLevel::NumMulChecked,
args: vec![
(num_var_1, Var(Symbol::ARG_1)),
(num_var_2, Var(Symbol::ARG_2)),
],
ret_var: record_var,
}),
expr_var: record_var,
pattern_vars: SendMap::default(),
annotation: None,
};
let body = LetNonRec(Box::new(def), Box::new(no_region(cont)), ret_var);
defn(
symbol,
vec![(num_var_1, Symbol::ARG_1), (num_var_2, Symbol::ARG_2)],
var_store,
body,
ret_var,
)
}
/// Num.isGt : Num a, Num a -> Bool
fn num_gt(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_num_other_binop(symbol, var_store, LowLevel::NumGt)