mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 19:58:18 +00:00
Add basic Dec operations
This commit is contained in:
parent
0827123c88
commit
ecb89da7b8
6 changed files with 190 additions and 22 deletions
|
@ -24,19 +24,19 @@ pub const RocDec = extern struct {
|
|||
}
|
||||
|
||||
// TODO: There's got to be a better way to do this other than converting to Str
|
||||
pub fn fromF64(num: f64) RocDec {
|
||||
pub fn fromF64(num: f64) ?RocDec {
|
||||
var digit_bytes: [19]u8 = undefined; // Max f64 digits + '.' + '-'
|
||||
|
||||
var fbs = std.io.fixedBufferStream(digit_bytes[0..]);
|
||||
std.fmt.formatFloatDecimal(num, .{}, fbs.writer()) catch
|
||||
@panic("TODO runtime exception failing to print float!");
|
||||
return null;
|
||||
|
||||
var dec = RocDec.fromStr(RocStr.init(&digit_bytes, fbs.pos));
|
||||
|
||||
if (dec) |d| {
|
||||
return d;
|
||||
} else {
|
||||
@panic("TODO runtime exception failing convert f64 to RocDec");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,6 +208,14 @@ pub const RocDec = extern struct {
|
|||
return RocStr.init(&str_bytes, str_len);
|
||||
}
|
||||
|
||||
pub fn eq(self: RocDec, other: RocDec) bool {
|
||||
return self.num == other.num;
|
||||
}
|
||||
|
||||
pub fn neq(self: RocDec, other: RocDec) bool {
|
||||
return self.num != other.num;
|
||||
}
|
||||
|
||||
pub fn negate(self: RocDec) ?RocDec {
|
||||
var negated = math.negate(self.num) catch null;
|
||||
return if (negated) |n| .{ .num = n } else null;
|
||||
|
@ -672,7 +680,7 @@ test "fromU64" {
|
|||
|
||||
test "fromF64" {
|
||||
var dec = RocDec.fromF64(25.5);
|
||||
try expectEqual(RocDec{ .num = 25500000000000000000 }, dec);
|
||||
try expectEqual(RocDec{ .num = 25500000000000000000 }, dec.?);
|
||||
}
|
||||
|
||||
test "fromStr: empty" {
|
||||
|
@ -979,10 +987,34 @@ test "div: 10 / 3" {
|
|||
|
||||
// exports
|
||||
|
||||
pub fn fromF64(arg: f64) callconv(.C) i128 {
|
||||
return @call(.{ .modifier = always_inline }, RocDec.fromF64, .{arg}).num;
|
||||
pub fn fromF64C(arg: f64) callconv(.C) i128 {
|
||||
return if (@call(.{ .modifier = always_inline }, RocDec.fromF64, .{arg})) |dec| dec.num else @panic("TODO runtime exception failing convert f64 to RocDec");
|
||||
}
|
||||
|
||||
pub fn add(arg1: RocDec, arg2: RocDec) callconv(.C) i128 {
|
||||
pub fn eqC(arg1: RocDec, arg2: RocDec) callconv(.C) bool {
|
||||
return @call(.{ .modifier = always_inline }, RocDec.eq, .{ arg1, arg2 });
|
||||
}
|
||||
|
||||
pub fn neqC(arg1: RocDec, arg2: RocDec) callconv(.C) bool {
|
||||
return @call(.{ .modifier = always_inline }, RocDec.neq, .{ arg1, arg2 });
|
||||
}
|
||||
|
||||
pub fn negateC(arg: RocDec) callconv(.C) i128 {
|
||||
return if (@call(.{ .modifier = always_inline }, RocDec.negate, .{arg})) |dec| dec.num else @panic("TODO overflow for negating RocDec");
|
||||
}
|
||||
|
||||
pub fn addC(arg1: RocDec, arg2: RocDec) callconv(.C) i128 {
|
||||
return @call(.{ .modifier = always_inline }, RocDec.add, .{ arg1, arg2 }).num;
|
||||
}
|
||||
|
||||
pub fn subC(arg1: RocDec, arg2: RocDec) callconv(.C) i128 {
|
||||
return @call(.{ .modifier = always_inline }, RocDec.sub, .{ arg1, arg2 }).num;
|
||||
}
|
||||
|
||||
pub fn mulC(arg1: RocDec, arg2: RocDec) callconv(.C) i128 {
|
||||
return @call(.{ .modifier = always_inline }, RocDec.mul, .{ arg1, arg2 }).num;
|
||||
}
|
||||
|
||||
pub fn divC(arg1: RocDec, arg2: RocDec) callconv(.C) i128 {
|
||||
return @call(.{ .modifier = always_inline }, RocDec.div, .{ arg1, arg2 }).num;
|
||||
}
|
||||
|
|
|
@ -6,8 +6,14 @@ const testing = std.testing;
|
|||
const dec = @import("dec.zig");
|
||||
|
||||
comptime {
|
||||
exportDecFn(dec.fromF64, "from_f64");
|
||||
exportDecFn(dec.add, "add");
|
||||
exportDecFn(dec.fromF64C, "from_f64");
|
||||
exportDecFn(dec.eqC, "eq");
|
||||
exportDecFn(dec.neqC, "neq");
|
||||
exportDecFn(dec.negateC, "negate");
|
||||
exportDecFn(dec.addC, "add");
|
||||
exportDecFn(dec.subC, "sub");
|
||||
exportDecFn(dec.mulC, "mul");
|
||||
exportDecFn(dec.divC, "div");
|
||||
}
|
||||
|
||||
// List Module
|
||||
|
@ -113,8 +119,9 @@ fn exportDecFn(comptime func: anytype, comptime func_name: []const u8) void {
|
|||
exportBuiltinFn(func, "dec." ++ func_name);
|
||||
}
|
||||
|
||||
// Cusotm panic function, as builtin Zig version errors during LLVM verification
|
||||
pub fn panic(message: []const u8, stacktrace: ?*std.builtin.StackTrace) noreturn {
|
||||
std.debug.print("{s}", .{message});
|
||||
std.debug.print("{s}: {?}", .{ message, stacktrace });
|
||||
unreachable;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,5 +67,10 @@ pub const LIST_CONCAT: &str = "roc_builtins.list.concat";
|
|||
pub const LIST_SET: &str = "roc_builtins.list.set";
|
||||
|
||||
pub const DEC_FROM_F64: &str = "roc_builtins.dec.from_f64";
|
||||
pub const DEC_EQ: &str = "roc_builtins.dec.eq";
|
||||
pub const DEC_NEQ: &str = "roc_builtins.dec.neq";
|
||||
pub const DEC_NEGATE: &str = "roc_builtins.dec.negate";
|
||||
pub const DEC_ADD: &str = "roc_builtins.dec.add";
|
||||
pub const DEC_FROM_STR: &str = "roc_builtins.dec.from_str";
|
||||
pub const DEC_SUB: &str = "roc_builtins.dec.sub";
|
||||
pub const DEC_MUL: &str = "roc_builtins.dec.mul";
|
||||
pub const DEC_DIV: &str = "roc_builtins.dec.div";
|
||||
|
|
|
@ -5547,7 +5547,12 @@ fn build_dec_binop<'a, 'ctx, 'env>(
|
|||
|
||||
match op {
|
||||
NumAdd => call_bitcode_fn(env, &[lhs, rhs], &bitcode::DEC_ADD),
|
||||
_ => panic!("TODO: Add RocDec function for op"),
|
||||
NumSub => call_bitcode_fn(env, &[lhs, rhs], &bitcode::DEC_SUB),
|
||||
NumMul => call_bitcode_fn(env, &[lhs, rhs], &bitcode::DEC_MUL),
|
||||
NumDivUnchecked => call_bitcode_fn(env, &[lhs, rhs], &bitcode::DEC_DIV),
|
||||
_ => {
|
||||
unreachable!("Unrecognized int binary operation: {:?}", op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::llvm::bitcode::call_bitcode_fn;
|
||||
use crate::llvm::build::Env;
|
||||
use crate::llvm::build::{cast_block_of_memory_to_tag, complex_bitcast, FAST_CALL_CONV};
|
||||
use crate::llvm::build_list::{list_len, load_list_ptr};
|
||||
|
@ -9,6 +10,7 @@ use inkwell::values::{
|
|||
BasicValue, BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue,
|
||||
};
|
||||
use inkwell::{AddressSpace, FloatPredicate, IntPredicate};
|
||||
use roc_builtins::bitcode;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
|
||||
|
||||
|
@ -96,7 +98,7 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
|
|||
|
||||
Builtin::Usize => int_cmp(IntPredicate::EQ, "eq_usize"),
|
||||
|
||||
Builtin::Decimal => panic!("TODO: eq decimal"),
|
||||
Builtin::Decimal => call_bitcode_fn(env, &[lhs_val, rhs_val], &bitcode::DEC_EQ),
|
||||
Builtin::Float128 => float_cmp(FloatPredicate::OEQ, "eq_f128"),
|
||||
Builtin::Float64 => float_cmp(FloatPredicate::OEQ, "eq_f64"),
|
||||
Builtin::Float32 => float_cmp(FloatPredicate::OEQ, "eq_f32"),
|
||||
|
@ -242,7 +244,7 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
|
|||
|
||||
Builtin::Usize => int_cmp(IntPredicate::NE, "neq_usize"),
|
||||
|
||||
Builtin::Decimal => panic!("TODO: negate decimal"),
|
||||
Builtin::Decimal => call_bitcode_fn(env, &[lhs_val, rhs_val], &bitcode::DEC_NEQ),
|
||||
Builtin::Float128 => float_cmp(FloatPredicate::ONE, "neq_f128"),
|
||||
Builtin::Float64 => float_cmp(FloatPredicate::ONE, "neq_f64"),
|
||||
Builtin::Float32 => float_cmp(FloatPredicate::ONE, "neq_f32"),
|
||||
|
|
|
@ -336,19 +336,14 @@ mod gen_num {
|
|||
x : Dec
|
||||
x = 2.1
|
||||
|
||||
y : Dec
|
||||
y = 3.1
|
||||
|
||||
z : Dec
|
||||
z = x + y
|
||||
|
||||
z
|
||||
x
|
||||
"#
|
||||
),
|
||||
5200000000000000000,
|
||||
2100000000000000000,
|
||||
i128
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f64_float_alias() {
|
||||
assert_evals_to!(
|
||||
|
@ -564,6 +559,27 @@ mod gen_num {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_add_dec() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : Dec
|
||||
x = 2.1
|
||||
|
||||
y : Dec
|
||||
y = 3.1
|
||||
|
||||
z : Dec
|
||||
z = x + y
|
||||
|
||||
z
|
||||
"#
|
||||
),
|
||||
5200000000000000000,
|
||||
i128
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn gen_add_f64() {
|
||||
assert_evals_to!(
|
||||
|
@ -607,6 +623,26 @@ mod gen_num {
|
|||
f64
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn gen_div_dec() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : Dec
|
||||
x = 10
|
||||
|
||||
y : Dec
|
||||
y = 3
|
||||
|
||||
when x / y is
|
||||
Ok val -> val
|
||||
Err _ -> -1
|
||||
"#
|
||||
),
|
||||
3333333333333333333,
|
||||
i128
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_int_eq() {
|
||||
|
@ -634,6 +670,44 @@ mod gen_num {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_dec_eq() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : Dec
|
||||
x = 4
|
||||
|
||||
y : Dec
|
||||
y = 4
|
||||
|
||||
x == y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_dec_neq() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : Dec
|
||||
x = 4
|
||||
|
||||
y : Dec
|
||||
y = 5
|
||||
|
||||
x != y
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_wrap_int_neq() {
|
||||
assert_evals_to!(
|
||||
|
@ -664,6 +738,28 @@ mod gen_num {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_sub_dec() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : Dec
|
||||
x = 1.5
|
||||
|
||||
y : Dec
|
||||
y = 2.4
|
||||
|
||||
z : Dec
|
||||
z = 3
|
||||
|
||||
x - y - z
|
||||
"#
|
||||
),
|
||||
-3900000000000000000,
|
||||
i128
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_sub_f64() {
|
||||
assert_evals_to!(
|
||||
|
@ -690,6 +786,27 @@ mod gen_num {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_mul_dec() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : Dec
|
||||
x = 2
|
||||
|
||||
y : Dec
|
||||
y = 4
|
||||
|
||||
z : Dec
|
||||
z = 6
|
||||
|
||||
x * y * z
|
||||
"#
|
||||
),
|
||||
48000000000000000000,
|
||||
i128
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn gen_mul_i64() {
|
||||
assert_evals_to!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue