Add Num.log and wire it up

This commit is contained in:
Ju Liu 2021-03-28 15:02:45 +01:00
parent 47ddfd2639
commit 928249df2a
6 changed files with 130 additions and 59 deletions

View file

@ -430,6 +430,20 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
), ),
); );
// log : Float a -> Float a
let log_of_negative = SolvedType::TagUnion(
vec![(TagName::Global("LogOfNegative".into()), vec![])],
Box::new(SolvedType::Wildcard),
);
add_type(
Symbol::NUM_LOG,
top_level_function(
vec![float_type(flex(TVAR1))],
Box::new(result_type(float_type(flex(TVAR1)), log_of_negative)),
),
);
// round : Float a -> Int b // round : Float a -> Int b
add_type( add_type(
Symbol::NUM_ROUND, Symbol::NUM_ROUND,

View file

@ -138,6 +138,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
NUM_REM => num_rem, NUM_REM => num_rem,
NUM_IS_MULTIPLE_OF => num_is_multiple_of, NUM_IS_MULTIPLE_OF => num_is_multiple_of,
NUM_SQRT => num_sqrt, NUM_SQRT => num_sqrt,
NUM_LOG => num_log,
NUM_ROUND => num_round, NUM_ROUND => num_round,
NUM_IS_ODD => num_is_odd, NUM_IS_ODD => num_is_odd,
NUM_IS_EVEN => num_is_even, NUM_IS_EVEN => num_is_even,
@ -274,6 +275,7 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Def> {
Symbol::NUM_REM => num_rem, Symbol::NUM_REM => num_rem,
Symbol::NUM_IS_MULTIPLE_OF => num_is_multiple_of, Symbol::NUM_IS_MULTIPLE_OF => num_is_multiple_of,
Symbol::NUM_SQRT => num_sqrt, Symbol::NUM_SQRT => num_sqrt,
Symbol::NUM_LOG => num_log,
Symbol::NUM_ROUND => num_round, Symbol::NUM_ROUND => num_round,
Symbol::NUM_IS_ODD => num_is_odd, Symbol::NUM_IS_ODD => num_is_odd,
Symbol::NUM_IS_EVEN => num_is_even, Symbol::NUM_IS_EVEN => num_is_even,
@ -1186,6 +1188,52 @@ fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
) )
} }
/// Num.log : Float -> Result Float [ LogOfNegative ]*
fn num_log(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bool_var = var_store.fresh();
let float_var = var_store.fresh();
let unbound_zero_var = var_store.fresh();
let precision_var = var_store.fresh();
let ret_var = var_store.fresh();
let body = If {
branch_var: ret_var,
cond_var: bool_var,
branches: vec![(
no_region(RunLowLevel {
op: LowLevel::NumGt,
args: vec![
(float_var, Var(Symbol::ARG_1)),
(float_var, Float(unbound_zero_var, precision_var, 0.0)),
],
ret_var: bool_var,
}),
no_region(tag(
"Ok",
vec![RunLowLevel {
op: LowLevel::NumLogUnchecked,
args: vec![(float_var, Var(Symbol::ARG_1))],
ret_var: float_var,
}],
var_store,
)),
)],
final_else: Box::new(no_region(tag(
"Err",
vec![tag("LogOfNegative", Vec::new(), var_store)],
var_store,
))),
};
defn(
symbol,
vec![(float_var, Symbol::ARG_1)],
var_store,
body,
ret_var,
)
}
/// Num.round : Float -> Int /// Num.round : Float -> Int
fn num_round(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_round(symbol: Symbol, var_store: &mut VarStore) -> Def {
let float_var = var_store.fresh(); let float_var = var_store.fresh();

View file

@ -337,6 +337,12 @@ fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) {
f64_type.fn_type(&[f64_type.into()], false), f64_type.fn_type(&[f64_type.into()], false),
); );
add_intrinsic(
module,
LLVM_LOG_F64,
f64_type.fn_type(&[f64_type.into()], false),
);
add_intrinsic( add_intrinsic(
module, module,
LLVM_LROUND_I64_F64, LLVM_LROUND_I64_F64,
@ -455,6 +461,7 @@ fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) {
static LLVM_MEMSET_I64: &str = "llvm.memset.p0i8.i64"; static LLVM_MEMSET_I64: &str = "llvm.memset.p0i8.i64";
static LLVM_MEMSET_I32: &str = "llvm.memset.p0i8.i32"; static LLVM_MEMSET_I32: &str = "llvm.memset.p0i8.i32";
static LLVM_SQRT_F64: &str = "llvm.sqrt.f64"; static LLVM_SQRT_F64: &str = "llvm.sqrt.f64";
static LLVM_LOG_F64: &str = "llvm.log.f64";
static LLVM_LROUND_I64_F64: &str = "llvm.lround.i64.f64"; static LLVM_LROUND_I64_F64: &str = "llvm.lround.i64.f64";
static LLVM_FABS_F64: &str = "llvm.fabs.f64"; static LLVM_FABS_F64: &str = "llvm.fabs.f64";
static LLVM_SIN_F64: &str = "llvm.sin.f64"; static LLVM_SIN_F64: &str = "llvm.sin.f64";
@ -3962,8 +3969,8 @@ fn run_low_level<'a, 'ctx, 'env>(
list_join(env, inplace, parent, list, outer_list_layout) list_join(env, inplace, parent, list, outer_list_layout)
} }
NumAbs | NumNeg | NumRound | NumSqrtUnchecked | NumSin | NumCos | NumCeiling | NumFloor NumAbs | NumNeg | NumRound | NumSqrtUnchecked | NumLogUnchecked | NumSin | NumCos
| NumToFloat | NumIsFinite | NumAtan | NumAcos | NumAsin => { | NumCeiling | NumFloor | NumToFloat | NumIsFinite | NumAtan | NumAcos | NumAsin => {
debug_assert_eq!(args.len(), 1); debug_assert_eq!(args.len(), 1);
let (arg, arg_layout) = load_symbol_and_layout(scope, &args[0]); let (arg, arg_layout) = load_symbol_and_layout(scope, &args[0]);
@ -5272,6 +5279,7 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
NumNeg => bd.build_float_neg(arg, "negate_float").into(), NumNeg => bd.build_float_neg(arg, "negate_float").into(),
NumAbs => env.call_intrinsic(LLVM_FABS_F64, &[arg.into()]), NumAbs => env.call_intrinsic(LLVM_FABS_F64, &[arg.into()]),
NumSqrtUnchecked => env.call_intrinsic(LLVM_SQRT_F64, &[arg.into()]), NumSqrtUnchecked => env.call_intrinsic(LLVM_SQRT_F64, &[arg.into()]),
NumLogUnchecked => env.call_intrinsic(LLVM_LOG_F64, &[arg.into()]),
NumRound => env.call_intrinsic(LLVM_LROUND_I64_F64, &[arg.into()]), NumRound => env.call_intrinsic(LLVM_LROUND_I64_F64, &[arg.into()]),
NumSin => env.call_intrinsic(LLVM_SIN_F64, &[arg.into()]), NumSin => env.call_intrinsic(LLVM_SIN_F64, &[arg.into()]),
NumCos => env.call_intrinsic(LLVM_COS_F64, &[arg.into()]), NumCos => env.call_intrinsic(LLVM_COS_F64, &[arg.into()]),

View file

@ -71,6 +71,7 @@ pub enum LowLevel {
NumSin, NumSin,
NumCos, NumCos,
NumSqrtUnchecked, NumSqrtUnchecked,
NumLogUnchecked,
NumRound, NumRound,
NumToFloat, NumToFloat,
NumPow, NumPow,

View file

@ -804,59 +804,60 @@ define_builtins! {
43 NUM_MOD_INT: "modInt" 43 NUM_MOD_INT: "modInt"
44 NUM_MOD_FLOAT: "modFloat" 44 NUM_MOD_FLOAT: "modFloat"
45 NUM_SQRT: "sqrt" 45 NUM_SQRT: "sqrt"
46 NUM_ROUND: "round" 46 NUM_LOG: "log"
47 NUM_COMPARE: "compare" 47 NUM_ROUND: "round"
48 NUM_POW: "pow" 48 NUM_COMPARE: "compare"
49 NUM_CEILING: "ceiling" 49 NUM_POW: "pow"
50 NUM_POW_INT: "powInt" 50 NUM_CEILING: "ceiling"
51 NUM_FLOOR: "floor" 51 NUM_POW_INT: "powInt"
52 NUM_ADD_WRAP: "addWrap" 52 NUM_FLOOR: "floor"
53 NUM_ADD_CHECKED: "addChecked" 53 NUM_ADD_WRAP: "addWrap"
54 NUM_ATAN: "atan" 54 NUM_ADD_CHECKED: "addChecked"
55 NUM_ACOS: "acos" 55 NUM_ATAN: "atan"
56 NUM_ASIN: "asin" 56 NUM_ACOS: "acos"
57 NUM_AT_SIGNED128: "@Signed128" 57 NUM_ASIN: "asin"
58 NUM_SIGNED128: "Signed128" imported 58 NUM_AT_SIGNED128: "@Signed128"
59 NUM_AT_SIGNED64: "@Signed64" 59 NUM_SIGNED128: "Signed128" imported
60 NUM_SIGNED64: "Signed64" imported 60 NUM_AT_SIGNED64: "@Signed64"
61 NUM_AT_SIGNED32: "@Signed32" 61 NUM_SIGNED64: "Signed64" imported
62 NUM_SIGNED32: "Signed32" imported 62 NUM_AT_SIGNED32: "@Signed32"
63 NUM_AT_SIGNED16: "@Signed16" 63 NUM_SIGNED32: "Signed32" imported
64 NUM_SIGNED16: "Signed16" imported 64 NUM_AT_SIGNED16: "@Signed16"
65 NUM_AT_SIGNED8: "@Signed8" 65 NUM_SIGNED16: "Signed16" imported
66 NUM_SIGNED8: "Signed8" imported 66 NUM_AT_SIGNED8: "@Signed8"
67 NUM_AT_UNSIGNED128: "@Unsigned128" 67 NUM_SIGNED8: "Signed8" imported
68 NUM_UNSIGNED128: "Unsigned128" imported 68 NUM_AT_UNSIGNED128: "@Unsigned128"
69 NUM_AT_UNSIGNED64: "@Unsigned64" 69 NUM_UNSIGNED128: "Unsigned128" imported
70 NUM_UNSIGNED64: "Unsigned64" imported 70 NUM_AT_UNSIGNED64: "@Unsigned64"
71 NUM_AT_UNSIGNED32: "@Unsigned32" 71 NUM_UNSIGNED64: "Unsigned64" imported
72 NUM_UNSIGNED32: "Unsigned32" imported 72 NUM_AT_UNSIGNED32: "@Unsigned32"
73 NUM_AT_UNSIGNED16: "@Unsigned16" 73 NUM_UNSIGNED32: "Unsigned32" imported
74 NUM_UNSIGNED16: "Unsigned16" imported 74 NUM_AT_UNSIGNED16: "@Unsigned16"
75 NUM_AT_UNSIGNED8: "@Unsigned8" 75 NUM_UNSIGNED16: "Unsigned16" imported
76 NUM_UNSIGNED8: "Unsigned8" imported 76 NUM_AT_UNSIGNED8: "@Unsigned8"
77 NUM_AT_BINARY64: "@Binary64" 77 NUM_UNSIGNED8: "Unsigned8" imported
78 NUM_BINARY64: "Binary64" imported 78 NUM_AT_BINARY64: "@Binary64"
79 NUM_AT_BINARY32: "@Binary32" 79 NUM_BINARY64: "Binary64" imported
80 NUM_BINARY32: "Binary32" imported 80 NUM_AT_BINARY32: "@Binary32"
81 NUM_BITWISE_AND: "bitwiseAnd" 81 NUM_BINARY32: "Binary32" imported
82 NUM_BITWISE_XOR: "bitwiseXor" 82 NUM_BITWISE_AND: "bitwiseAnd"
83 NUM_BITWISE_OR: "bitwiseOr" 83 NUM_BITWISE_XOR: "bitwiseXor"
84 NUM_SHIFT_LEFT: "shiftLeftBy" 84 NUM_BITWISE_OR: "bitwiseOr"
85 NUM_SHIFT_RIGHT: "shiftRightBy" 85 NUM_SHIFT_LEFT: "shiftLeftBy"
86 NUM_SHIFT_RIGHT_ZERO_FILL: "shiftRightZfBy" 86 NUM_SHIFT_RIGHT: "shiftRightBy"
87 NUM_SUB_WRAP: "subWrap" 87 NUM_SHIFT_RIGHT_ZERO_FILL: "shiftRightZfBy"
88 NUM_SUB_CHECKED: "subChecked" 88 NUM_SUB_WRAP: "subWrap"
89 NUM_MUL_WRAP: "mulWrap" 89 NUM_SUB_CHECKED: "subChecked"
90 NUM_MUL_CHECKED: "mulChecked" 90 NUM_MUL_WRAP: "mulWrap"
91 NUM_INT: "Int" imported 91 NUM_MUL_CHECKED: "mulChecked"
92 NUM_FLOAT: "Float" imported 92 NUM_INT: "Int" imported
93 NUM_AT_NATURAL: "@Natural" 93 NUM_FLOAT: "Float" imported
94 NUM_NATURAL: "Natural" imported 94 NUM_AT_NATURAL: "@Natural"
95 NUM_NAT: "Nat" imported 95 NUM_NATURAL: "Natural" imported
96 NUM_INT_CAST: "intCast" 96 NUM_NAT: "Nat" imported
97 NUM_MAX_I128: "maxI128" 97 NUM_INT_CAST: "intCast"
98 NUM_IS_MULTIPLE_OF: "isMultipleOf" 98 NUM_MAX_I128: "maxI128"
99 NUM_IS_MULTIPLE_OF: "isMultipleOf"
} }
2 BOOL: "Bool" => { 2 BOOL: "Bool" => {

View file

@ -671,10 +671,9 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
| NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy | NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy
| NumShiftRightZfBy => arena.alloc_slice_copy(&[irrelevant, irrelevant]), | NumShiftRightZfBy => arena.alloc_slice_copy(&[irrelevant, irrelevant]),
NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumRound | NumCeiling | NumFloor NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumLogUnchecked | NumRound
| NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin | NumIntCast => { | NumCeiling | NumFloor | NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin
arena.alloc_slice_copy(&[irrelevant]) | NumIntCast => arena.alloc_slice_copy(&[irrelevant]),
}
StrStartsWith | StrEndsWith => arena.alloc_slice_copy(&[owned, borrowed]), StrStartsWith | StrEndsWith => arena.alloc_slice_copy(&[owned, borrowed]),
StrFromUtf8 => arena.alloc_slice_copy(&[owned]), StrFromUtf8 => arena.alloc_slice_copy(&[owned]),
StrToBytes => arena.alloc_slice_copy(&[owned]), StrToBytes => arena.alloc_slice_copy(&[owned]),