diff --git a/src/data_types/big_int.rs b/src/data_types/big_int.rs index bfab22f..66b3111 100644 --- a/src/data_types/big_int.rs +++ b/src/data_types/big_int.rs @@ -1,6 +1,135 @@ -use num_bigint::BigInt; +use num_bigint::{BigInt, BigUint, ToBigInt}; -#[derive(Debug)] +use super::{bool::JsBool, string::JsString}; + +#[derive(Debug, Clone)] pub struct JsBigInt { pub value: BigInt -} \ No newline at end of file +} + +// Implements https://tc39.es/ecma262/2023/#table-numeric-type-ops +impl JsBigInt { + pub fn unary_minus(&self) -> JsBigInt { + JsBigInt{ + value: &self.value * -1 + } + } + + pub fn bitwise_not(&self) -> JsBigInt { + JsBigInt{ + value: !&self.value + } + } + + pub fn exponentiate(&self, x: &JsBigInt) -> JsBigInt { + let (_, digits) = x.value.to_u32_digits(); + JsBigInt{ + value: self.value.pow(*digits.first().expect("Exponent bigint didn't have any digits")) + } + } + + pub fn multiply(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value * &x.value + } + } + + pub fn divide(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value / &x.value + } + } + + pub fn add(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value + &x.value + } + } + + pub fn pre_add(&mut self) -> JsBigInt { + self.value += 1; + self.clone() + } + + pub fn post_add(&mut self) -> JsBigInt { + let old = self.clone(); + self.value += 1; + old + } + + pub fn subtract(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value - &x.value + } + } + + pub fn pre_subtract(&mut self) -> JsBigInt { + self.value -= 1; + self.clone() + } + + pub fn post_subtract(&mut self) -> JsBigInt { + let old = self.clone(); + self.value -= 1; + old + } + + pub fn left_shift(&self, x: &JsBigInt) -> JsBigInt { + let (_, digits) = x.value.to_u32_digits(); + JsBigInt{ + value: &self.value << *digits.first().expect("Shift amount bigint didn't have any digits") + } + } + + pub fn right_shift_signed(&self, x: &JsBigInt) -> JsBigInt { + let (_, digits) = x.value.to_u32_digits(); + JsBigInt{ + value: &self.value >> *digits.first().expect("Shift amount bigint didn't have any digits") + } + } + + pub fn right_shift_unsigned(&self, x: &JsBigInt) -> JsBigInt { + let (_, digits) = x.value.to_u32_digits(); + let (_, old_bytes) = self.value.to_bytes_be(); + let u = BigUint::from_bytes_be(&old_bytes); + JsBigInt{ + value: (u >> *digits.first().expect("Shift amount bigint didn't have any digits")).to_bigint().expect("Failed to convert BigUInt to BigInt") + } + } + + pub fn less_than(&self, x: &JsBigInt) -> JsBool { + JsBool { value: self.value < x.value } + } + + pub fn equal(&self, x: &JsBigInt) -> JsBool { + JsBool { value: self.value == x.value } + } + + pub fn same_value(&self, x: &JsBigInt) -> JsBool { + JsBool { value: std::ptr::eq(self, x) } + } + + pub fn bitwise_and(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value & &x.value + } + } + + pub fn bitwise_xor(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value ^ &x.value + } + } + + pub fn bitwise_or(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value | &x.value + } + } + + pub fn to_string(&self) -> JsString { + JsString { + value: self.value.to_string().into() + } + } +} diff --git a/src/data_types/mod.rs b/src/data_types/mod.rs index e326412..1094bef 100644 --- a/src/data_types/mod.rs +++ b/src/data_types/mod.rs @@ -1,5 +1,6 @@ use self::{big_int::JsBigInt, bool::JsBool, number::JsNumber, object::JsObject, string::JsString, symbol::JsSymbol}; +// All Js primitive objects are wrappers around a single value pub mod bool; pub mod string; pub mod symbol;