aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorRobin Voetter <robin@voetter.nl>2021-12-18 04:42:13 +0100
committerRobin Voetter <robin@voetter.nl>2021-12-21 01:41:51 +0100
commitf3d635b6683ba4a53f82ae8087b1cf78552abac5 (patch)
treebd038a7404df4e79170915e07528694768f44f7c /src/value.zig
parent28bcd7dbdda7fb2c2fe80dbdb5981479a04e973a (diff)
downloadzig-f3d635b6683ba4a53f82ae8087b1cf78552abac5.tar.gz
zig-f3d635b6683ba4a53f82ae8087b1cf78552abac5.zip
stage2: @addWithOverflow
Diffstat (limited to 'src/value.zig')
-rw-r--r--src/value.zig79
1 files changed, 57 insertions, 22 deletions
diff --git a/src/value.zig b/src/value.zig
index e3d315b6e4..085883f7af 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1969,20 +1969,18 @@ pub const Value = extern union {
return @divFloor(@floatToInt(std.math.big.Limb, std.math.log2(w_value)), @typeInfo(std.math.big.Limb).Int.bits) + 1;
}
- /// Supports both floats and ints; handles undefined.
- pub fn numberAddWrap(
+ pub const OverflowArithmeticResult = struct {
+ overflowed: bool,
+ wrapped_result: Value,
+ };
+
+ pub fn intAddWithOverflow(
lhs: Value,
rhs: Value,
ty: Type,
arena: Allocator,
target: Target,
- ) !Value {
- if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
-
- if (ty.isAnyFloat()) {
- return floatAdd(lhs, rhs, ty, arena);
- }
-
+ ) !OverflowArithmeticResult {
const info = ty.intInfo(target);
var lhs_space: Value.BigIntSpace = undefined;
@@ -1994,8 +1992,30 @@ pub const Value = extern union {
std.math.big.int.calcTwosCompLimbCount(info.bits),
);
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
- result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
- return fromBigInt(arena, result_bigint.toConst());
+ const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
+ const result = try fromBigInt(arena, result_bigint.toConst());
+ return OverflowArithmeticResult{
+ .overflowed = overflowed,
+ .wrapped_result = result,
+ };
+ }
+
+ /// Supports both floats and ints; handles undefined.
+ pub fn numberAddWrap(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
+ if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
+
+ if (ty.isAnyFloat()) {
+ return floatAdd(lhs, rhs, ty, arena);
+ }
+
+ const overflow_result = try intAddWithOverflow(lhs, rhs, ty, arena, target);
+ return overflow_result.wrapped_result;
}
fn fromBigInt(arena: Allocator, big_int: BigIntConst) !Value {
@@ -2040,20 +2060,13 @@ pub const Value = extern union {
return fromBigInt(arena, result_bigint.toConst());
}
- /// Supports both floats and ints; handles undefined.
- pub fn numberSubWrap(
+ pub fn intSubWithOverflow(
lhs: Value,
rhs: Value,
ty: Type,
arena: Allocator,
target: Target,
- ) !Value {
- if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
-
- if (ty.isAnyFloat()) {
- return floatSub(lhs, rhs, ty, arena);
- }
-
+ ) !OverflowArithmeticResult {
const info = ty.intInfo(target);
var lhs_space: Value.BigIntSpace = undefined;
@@ -2065,8 +2078,30 @@ pub const Value = extern union {
std.math.big.int.calcTwosCompLimbCount(info.bits),
);
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
- result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
- return fromBigInt(arena, result_bigint.toConst());
+ const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
+ const wrapped_result = try fromBigInt(arena, result_bigint.toConst());
+ return OverflowArithmeticResult{
+ .overflowed = overflowed,
+ .wrapped_result = wrapped_result,
+ };
+ }
+
+ /// Supports both floats and ints; handles undefined.
+ pub fn numberSubWrap(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: Allocator,
+ target: Target,
+ ) !Value {
+ if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
+
+ if (ty.isAnyFloat()) {
+ return floatSub(lhs, rhs, ty, arena);
+ }
+
+ const overflow_result = try intSubWithOverflow(lhs, rhs, ty, arena, target);
+ return overflow_result.wrapped_result;
}
/// Supports integers only; asserts neither operand is undefined.