Fix trig ops

This commit is contained in:
Richard Feldman 2020-06-23 18:21:07 -04:00
parent 1c98248b91
commit 3309270747
2 changed files with 74 additions and 77 deletions

View File

@ -65,6 +65,7 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Def> {
Symbol::NUM_SIN => num_sin,
Symbol::NUM_COS => num_cos,
Symbol::NUM_TAN => num_tan,
Symbol::NUM_DIV_FLOAT => num_div_float,
Symbol::NUM_DIV_INT => num_div_int,
Symbol::NUM_ABS => num_abs,
Symbol::NUM_NEG => num_neg,
@ -81,8 +82,6 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Def> {
/// Bool.isEq : val, val -> Bool
fn bool_eq(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let bool_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::Eq,
@ -103,8 +102,6 @@ fn bool_eq(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Bool.isNotEq : val, val -> Bool
fn bool_neq(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let bool_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::NotEq,
@ -125,8 +122,6 @@ fn bool_neq(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Bool.or : val, val -> Bool
fn bool_or(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let body = RunLowLevel {
op: LowLevel::Or,
args: vec![
@ -146,8 +141,6 @@ fn bool_or(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Bool.not : Bool -> Bool
fn bool_not(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let body = RunLowLevel {
op: LowLevel::Not,
args: vec![(var_store.fresh(), Var(Symbol::BOOL_BINOP_LHS))],
@ -159,8 +152,6 @@ fn bool_not(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Bool.and : val, val -> Bool
fn bool_and(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let body = RunLowLevel {
op: LowLevel::And,
args: vec![
@ -179,8 +170,6 @@ fn bool_and(symbol: Symbol, var_store: &mut VarStore) -> Def {
}
fn num_binop(symbol: Symbol, var_store: &mut VarStore, op: LowLevel) -> Def {
use crate::expr::Expr::*;
let body = RunLowLevel {
op,
args: vec![
@ -230,13 +219,11 @@ fn num_lte(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.sin : Float -> Float
fn num_sin(symbol: Symbol, var_store: &mut VarStore) -> Def {
let arg_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::NumSin,
args: vec![
(var_store.fresh(), Var(Symbol::ARG_1)),
(var_store.fresh(), Num(var_store.fresh(), 0)),
],
ret_var: var_store.fresh(),
args: vec![(arg_var, Var(Symbol::ARG_1))],
ret_var: arg_var,
};
defn(symbol, vec![Symbol::ARG_1], var_store, body)
@ -244,13 +231,11 @@ fn num_sin(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.cos : Float -> Float
fn num_cos(symbol: Symbol, var_store: &mut VarStore) -> Def {
let arg_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::NumCos,
args: vec![
(var_store.fresh(), Var(Symbol::ARG_1)),
(var_store.fresh(), Num(var_store.fresh(), 0)),
],
ret_var: var_store.fresh(),
args: vec![(arg_var, Var(Symbol::ARG_1))],
ret_var: arg_var,
};
defn(symbol, vec![Symbol::ARG_1], var_store, body)
@ -258,33 +243,28 @@ fn num_cos(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.tan : Float -> Float
fn num_tan(symbol: Symbol, var_store: &mut VarStore) -> Def {
let float_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::NumDivUnchecked,
args: vec![
(
var_store.fresh(),
float_var,
RunLowLevel {
op: LowLevel::NumSin,
args: vec![
(var_store.fresh(), Var(Symbol::ARG_1)),
(var_store.fresh(), Num(var_store.fresh(), 0)),
],
ret_var: var_store.fresh(),
args: vec![(float_var, Var(Symbol::ARG_1))],
ret_var: float_var,
},
),
(
var_store.fresh(),
float_var,
RunLowLevel {
op: LowLevel::NumCos,
args: vec![
(var_store.fresh(), Var(Symbol::ARG_1)),
(var_store.fresh(), Num(var_store.fresh(), 0)),
],
ret_var: var_store.fresh(),
args: vec![(float_var, Var(Symbol::ARG_1))],
ret_var: float_var,
},
),
],
ret_var: var_store.fresh(),
ret_var: float_var,
};
defn(symbol, vec![Symbol::ARG_1], var_store, body)
@ -321,8 +301,6 @@ fn num_is_negative(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.isPositive : Float -> Bool
fn num_is_positive(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let body = RunLowLevel {
op: LowLevel::NumGt,
args: vec![
@ -337,8 +315,6 @@ fn num_is_positive(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.isOdd : Int -> Bool
fn num_is_odd(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let bool_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::Eq,
@ -364,8 +340,6 @@ fn num_is_odd(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.isEven : Int -> Bool
fn num_is_even(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let bool_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::Eq,
@ -391,8 +365,6 @@ fn num_is_even(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.sqrt : Float -> Result Float [ SqrtOfNegative ]*
fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let body = RunLowLevel {
op: LowLevel::NumSqrt,
args: vec![(var_store.fresh(), Var(Symbol::ARG_1))],
@ -404,8 +376,6 @@ fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.round : Float -> Int
fn num_round(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let body = RunLowLevel {
op: LowLevel::NumRound,
args: vec![(var_store.fresh(), Var(Symbol::ARG_1))],
@ -450,8 +420,6 @@ fn list_len(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// List.get : List elem, Int -> Result elem [ OutOfBounds ]*
fn list_get(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let arg_list = Symbol::ARG_1;
let arg_index = Symbol::ARG_2;
@ -517,8 +485,6 @@ fn list_get(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// List.set : List elem, Int, elem -> List elem
fn list_set(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let arg_list = Symbol::ARG_1;
let arg_index = Symbol::ARG_2;
let arg_elem = Symbol::ARG_3;
@ -578,8 +544,6 @@ fn list_set(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.rem : Int, Int -> Int
fn num_rem(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let bool_var = var_store.fresh();
let body = If {
branch_var: var_store.fresh(),
@ -629,8 +593,6 @@ fn num_rem(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.neg : Num a -> Num a
fn num_neg(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let body = RunLowLevel {
op: LowLevel::NumNeg,
args: vec![(var_store.fresh(), Var(Symbol::ARG_1))],
@ -642,8 +604,6 @@ fn num_neg(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Num.abs : Num a -> Num a
fn num_abs(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let body = If {
branch_var: var_store.fresh(),
cond_var: var_store.fresh(),
@ -677,10 +637,60 @@ fn num_abs(symbol: Symbol, var_store: &mut VarStore) -> Def {
defn(symbol, vec![Symbol::ARG_1], var_store, body)
}
/// Num.div : Float, Float -> Result Float [ DivByZero ]*
fn num_div_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bool_var = var_store.fresh();
let body = If {
branch_var: var_store.fresh(),
cond_var: var_store.fresh(),
branches: vec![(
// if-condition
no_region(
// Num.neq denominator 0
RunLowLevel {
op: LowLevel::NotEq,
args: vec![
(bool_var, Var(Symbol::ARG_1)),
(bool_var, Float(var_store.fresh(), 0.0)),
],
ret_var: var_store.fresh(),
},
),
// denominator was not zero
no_region(
// Ok (Float.#divUnsafe numerator denominator)
tag(
"Ok",
vec![
// Num.#divUnsafe numerator denominator
RunLowLevel {
op: LowLevel::NumDivUnchecked,
args: vec![
(var_store.fresh(), Var(Symbol::ARG_1)),
(var_store.fresh(), Var(Symbol::ARG_2)),
],
ret_var: var_store.fresh(),
},
],
var_store,
),
),
)],
final_else: Box::new(
// denominator was zero
no_region(tag(
"Err",
vec![tag("DivByZero", Vec::new(), var_store)],
var_store,
)),
),
};
defn(symbol, vec![Symbol::ARG_1, Symbol::ARG_2], var_store, body)
}
/// Num.div : Int, Int -> Result Int [ DivByZero ]*
fn num_div_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
let bool_var = var_store.fresh();
let body = If {
branch_var: var_store.fresh(),
@ -733,8 +743,6 @@ fn num_div_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// List.first : List elem -> Result elem [ ListWasEmpty ]*
fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
use crate::expr::Expr::*;
// Perform a bounds check. If it passes, delegate to List.getUnsafe.
let body = If {
// TODO Use "when" instead of "if" so that we can have False be the first branch.
@ -810,7 +818,6 @@ fn tag(name: &'static str, args: Vec<Expr>, var_store: &mut VarStore) -> Expr {
#[inline(always)]
fn defn(fn_name: Symbol, args: Vec<Symbol>, var_store: &mut VarStore, body: Expr) -> Def {
use crate::expr::Expr::*;
use crate::pattern::Pattern::*;
let closure_args = args

View File

@ -1399,7 +1399,7 @@ fn run_low_level<'a, 'ctx, 'env>(
BasicValueEnum::IntValue(answer)
}
NumAbs | NumNeg | NumRound | NumSqrt => {
NumAbs | NumNeg | NumRound | NumSqrt | NumSin | NumCos => {
debug_assert_eq!(args.len(), 1);
let arg = build_expr(env, layout_ids, scope, parent, &args[0].0);
@ -1429,8 +1429,8 @@ fn run_low_level<'a, 'ctx, 'env>(
}
}
}
NumAdd | NumSub | NumMul | NumLt | NumLte | NumGt | NumGte | NumSin | NumCos
| NumRemUnchecked | NumDivUnchecked => {
NumAdd | NumSub | NumMul | NumLt | NumLte | NumGt | NumGte | NumRemUnchecked
| NumDivUnchecked => {
debug_assert_eq!(args.len(), 2);
let lhs_arg = build_expr(env, layout_ids, scope, parent, &args[0].0);
@ -1634,9 +1634,9 @@ fn build_int_binop<'a, 'ctx, 'env>(
fn build_float_binop<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
lhs: FloatValue<'ctx>,
lhs_layout: &Layout<'a>,
_lhs_layout: &Layout<'a>,
rhs: FloatValue<'ctx>,
rhs_layout: &Layout<'a>,
_rhs_layout: &Layout<'a>,
op: LowLevel,
) -> BasicValueEnum<'ctx> {
use inkwell::FloatPredicate::*;
@ -1654,18 +1654,6 @@ fn build_float_binop<'a, 'ctx, 'env>(
NumLte => bd.build_float_compare(OLE, lhs, rhs, "float_lte").into(),
NumRemUnchecked => bd.build_float_rem(lhs, rhs, "rem_float").into(),
NumDivUnchecked => bd.build_float_div(lhs, rhs, "div_float").into(),
// Float-specific ops
NumSin => call_intrinsic(
LLVM_SIN_F64,
env,
&[(lhs.into(), lhs_layout), (rhs.into(), rhs_layout)],
),
NumCos => call_intrinsic(
LLVM_COS_F64,
env,
&[(lhs.into(), lhs_layout), (rhs.into(), rhs_layout)],
),
_ => {
unreachable!("Unrecognized int binary operation: {:?}", op);
}
@ -1708,6 +1696,8 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
NumAbs => call_intrinsic(LLVM_FABS_F64, env, &[(arg.into(), arg_layout)]),
NumSqrt => call_intrinsic(LLVM_SQRT_F64, env, &[(arg.into(), arg_layout)]),
NumRound => call_intrinsic(LLVM_LROUND_I64_F64, env, &[(arg.into(), arg_layout)]),
NumSin => call_intrinsic(LLVM_SIN_F64, env, &[(arg.into(), arg_layout)]),
NumCos => call_intrinsic(LLVM_COS_F64, env, &[(arg.into(), arg_layout)]),
_ => {
unreachable!("Unrecognized int unary operation: {:?}", op);
}