diff --git a/nanvm-lib/src/big_numbers/big_float.rs b/nanvm-lib/src/big_numbers/big_float.rs index 3a924ac8..77e01ade 100644 --- a/nanvm-lib/src/big_numbers/big_float.rs +++ b/nanvm-lib/src/big_numbers/big_float.rs @@ -1,73 +1,96 @@ -use crate::{big_numbers::big_int::Sign, common::cast::Cast}; - -use super::{big_int::BigInt, big_uint::BigUint}; - -#[derive(Debug, PartialEq, Clone, Eq, Default)] -pub struct BigFloat { - pub significand: BigInt, +use std::{cmp::Ordering, ops::Deref}; + +use crate::{ + js::js_bigint::{ + div_mod, from_u64, is_zero, mul, pow_u64, shl, shl_on_u64, shr_on_u64, zero, JsBigint, + JsBigintMutRef, Sign, + }, + mem::manager::Manager, +}; + +#[derive(Debug)] +pub struct BigFloat { + pub manager: M, + pub significand: JsBigintMutRef, + pub sign: Sign, pub exp: i64, pub non_zero_reminder: bool, } -impl BigFloat { - pub const ZERO: BigFloat = BigFloat { - significand: BigInt::ZERO, +pub fn float_zero(manager: M) -> BigFloat { + BigFloat { + manager, + significand: zero(manager), + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; + } +} +impl BigFloat { fn increase_significand(&mut self, precision: u64) { - if self.significand.is_zero() { + if is_zero(self.significand.deref()) { return; } - let min_significand = &BigUint::one() << &BigUint::from_u64(precision); - self.increase_significand_to(&min_significand); + let min_significand = shl( + self.manager, + from_u64(self.manager, Sign::Positive, 1).deref(), + from_u64(self.manager, Sign::Positive, precision).deref(), + ); + self.increase_significand_to(min_significand.deref()); } - fn increase_significand_to(&mut self, min_significand: &BigUint) { - if self.significand.is_zero() { + fn increase_significand_to(&mut self, min_significand: &JsBigint) { + if is_zero(self.significand.deref()) { return; } loop { - if self.significand.value >= *min_significand { - return; + match self.significand.deref().compare(min_significand) { + Ordering::Greater | Ordering::Equal => return, + _ => {} } - self.significand.value = &self.significand.value << &BigUint::one(); + self.significand = shl_on_u64(self.manager, self.significand.deref(), 1); self.exp -= 1; } } fn decrease_significand(&mut self, precision: u64) { - if self.significand.is_zero() { + if is_zero(self.significand.deref()) { return; } - let max_significand = &BigUint::one() << &BigUint::from_u64(precision); + let max_significand = shl( + self.manager, + from_u64(self.manager, Sign::Positive, 1).deref(), + from_u64(self.manager, Sign::Positive, precision).deref(), + ); loop { - if self.significand.value < max_significand { + if self.significand.deref().compare(max_significand.deref()) == Ordering::Less { break; } - let last_bit = self.significand.value.get_last_bit(); + let last_bit = self.significand.get_last_bit(); if last_bit == 1 { self.non_zero_reminder = true; } - self.significand.value = &self.significand.value >> &BigUint::one(); + self.significand = shr_on_u64(self.manager, self.significand.deref(), 1); self.exp += 1; } } } -impl BigFloat<10> { - pub fn to_bin(self, precision: u8) -> BigFloat<2> { - if self.significand.is_zero() { - return BigFloat::ZERO; +impl BigFloat<10, M> { + pub fn to_bin(self, precision: u8) -> BigFloat<2, M> { + if is_zero(self.significand.deref()) { + return float_zero(self.manager); } if self.exp == 0 { - let mut result: BigFloat<2> = BigFloat { + let mut result: BigFloat<2, M> = BigFloat { + manager: self.manager, significand: self.significand, + sign: self.sign, exp: self.exp, non_zero_reminder: self.non_zero_reminder, }; @@ -76,11 +99,17 @@ impl BigFloat<10> { return result; } - let five = BigUint { value: [5].cast() }; + let five = from_u64(self.manager, Sign::Positive, 5); if self.exp > 0 { - let new_sign = &self.significand * &five.pow_u64(self.exp as u64).to_big_int(); - let mut result: BigFloat<2> = BigFloat { + let new_sign = mul( + self.manager, + self.significand.deref(), + pow_u64(self.manager, five.deref(), self.exp as u64).deref(), + ); + let mut result: BigFloat<2, M> = BigFloat { + manager: self.manager, significand: new_sign, + sign: self.sign, exp: self.exp, non_zero_reminder: self.non_zero_reminder, }; @@ -89,26 +118,40 @@ impl BigFloat<10> { return result; } - let p = five.pow_u64(-self.exp as u64); - let mut bf10 = self.clone(); - let min_significand = &BigUint::one() << &BigUint::from_u64(precision as u64); - bf10.increase_significand_to(&(&p * &min_significand)); + let p = pow_u64(self.manager, five.deref(), -self.exp as u64); + let mut bf10: BigFloat<10, M> = BigFloat { + manager: self.manager, + significand: self.significand, + sign: self.sign, + exp: self.exp, + non_zero_reminder: self.non_zero_reminder, + }; + let min_significand = shl( + self.manager, + from_u64(self.manager, Sign::Positive, 1).deref(), + from_u64(self.manager, Sign::Positive, precision as u64).deref(), + ); + bf10.increase_significand_to( + (mul(self.manager, p.deref(), min_significand.deref())).deref(), + ); - let (q, r) = bf10.significand.div_mod(&p.to_big_int()); - let mut result: BigFloat<2> = BigFloat { + let (q, r) = div_mod(self.manager, bf10.significand.deref(), p.deref()); + let mut result: BigFloat<2, M> = BigFloat { + manager: self.manager, significand: q, + sign: self.sign, exp: bf10.exp, - non_zero_reminder: self.non_zero_reminder || !r.is_zero(), + non_zero_reminder: self.non_zero_reminder || !is_zero(r.deref()), }; result.decrease_significand(precision as u64); result } } -impl BigFloat<2> { +impl BigFloat<2, M> { fn get_frac_round(self) -> u64 { - let mut last_bit = self.significand.value.get_last_bit(); - let mut frac = self.significand.value.value[0] >> 1; + let mut last_bit = self.significand.get_last_bit(); + let mut frac = self.significand.items()[0] >> 1; if last_bit == 1 && !self.non_zero_reminder { last_bit = frac & 1; @@ -132,15 +175,21 @@ impl BigFloat<2> { const INF_BITS: u64 = 2047 << 52; let mut bits: u64 = 0; - if self.significand.sign == Sign::Negative { + if self.sign == Sign::Negative { bits |= 1 << 63; } - if self.significand.is_zero() { + if is_zero(self.significand.deref()) { return bits; } - let mut value = self.clone(); + let mut value = BigFloat { + manager: self.manager, + significand: self.significand, + sign: self.sign, + exp: self.exp, + non_zero_reminder: self.non_zero_reminder, + }; value.increase_significand(PRECISION + 1); value.decrease_significand(PRECISION + 2); @@ -184,11 +233,13 @@ mod test { use wasm_bindgen_test::wasm_bindgen_test; use crate::{ - big_numbers::{ - big_int::{BigInt, Sign}, - big_uint::BigUint, + big_numbers::big_float::float_zero, + js::{ + any::Any, + js_bigint::{from_u64, new_bigint, zero, JsBigintRef, Sign}, + type_::Type, }, - common::cast::Cast, + mem::global::{Global, GLOBAL}, }; use super::BigFloat; @@ -196,337 +247,423 @@ mod test { #[test] #[wasm_bindgen_test] fn test_zero() { - let res = BigFloat::ZERO.to_bin(64); - assert_eq!(res, BigFloat::ZERO); + type A = Any; + type BigintRef = JsBigintRef; + + let res = float_zero(GLOBAL).to_bin(64); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert!(o.items().is_empty()); + } + assert_eq!(res.exp, 0); + assert!(!res.non_zero_reminder); let res = BigFloat { - significand: BigInt::ZERO, + manager: GLOBAL, + significand: zero(GLOBAL), + sign: Sign::Positive, exp: 10, non_zero_reminder: false, } .to_bin(64); - assert_eq!(res, BigFloat::ZERO); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert!(o.items().is_empty()); + } + assert_eq!(res.exp, 0); + assert!(!res.non_zero_reminder); let res = BigFloat { - significand: BigInt::ZERO, + manager: GLOBAL, + significand: zero(GLOBAL), + sign: Sign::Positive, exp: -10, non_zero_reminder: false, } .to_bin(64); - assert_eq!(res, BigFloat::ZERO); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert!(o.items().is_empty()); + } + assert_eq!(res.exp, 0); + assert!(!res.non_zero_reminder); } #[test] #[wasm_bindgen_test] fn test_integer() { - let a = BigFloat { - significand: BigInt::from_i64(100), + type A = Any; + type BigintRef = JsBigintRef; + + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 100), + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let res = a.to_bin(7); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(100), - exp: 0, - non_zero_reminder: false - } - ); + } + .to_bin(7); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[100]); + } + assert_eq!(res.exp, 0); + assert!(!res.non_zero_reminder); - let a = BigFloat { - significand: BigInt::from_i64(1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 1), + sign: Sign::Positive, exp: 1, non_zero_reminder: false, - }; - let res = a.to_bin(64); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_u64(10 << 60), - exp: -60, - non_zero_reminder: false - } - ); + } + .to_bin(64); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[10 << 60]); + } + assert_eq!(res.exp, -60); + assert!(!res.non_zero_reminder); - let a = BigFloat { - significand: BigInt::from_i64(100), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 100), + sign: Sign::Positive, exp: 2, non_zero_reminder: false, - }; - let res = a.to_bin(64); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_u64(10000 << 50), - exp: -50, - non_zero_reminder: false - } - ); + } + .to_bin(64); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[10000 << 50]); + } + assert_eq!(res.exp, -50); + assert!(!res.non_zero_reminder); - let a = BigFloat { - significand: BigInt::from_i64(128), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 128), + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let res = a.to_bin(9); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(256), - exp: -1, - non_zero_reminder: false - } - ); + } + .to_bin(9); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[256]); + } + assert_eq!(res.exp, -1); + assert!(!res.non_zero_reminder); } #[test] #[wasm_bindgen_test] fn test_integer_rounding() { - let a = BigFloat { - significand: BigInt::from_i64(128), + type A = Any; + type BigintRef = JsBigintRef; + + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 128), + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let res = a.to_bin(4); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(8), - exp: 4, - non_zero_reminder: false - } - ); + } + .to_bin(4); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[8]); + } + assert_eq!(res.exp, 4); + assert!(!res.non_zero_reminder); - let a = BigFloat { - significand: BigInt::from_i64(129), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 129), + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let res = a.to_bin(4); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(8), - exp: 4, - non_zero_reminder: true - } - ); + } + .to_bin(4); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[8]); + } + assert_eq!(res.exp, 4); + assert!(res.non_zero_reminder); } #[test] #[wasm_bindgen_test] fn test_float() { - let a = BigFloat { - significand: BigInt::from_i64(100), + type A = Any; + type BigintRef = JsBigintRef; + + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 100), + sign: Sign::Positive, exp: -1, non_zero_reminder: false, - }; - let res = a.to_bin(5); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(20), - exp: -1, - non_zero_reminder: false - } - ); + } + .to_bin(5); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[20]); + } + assert_eq!(res.exp, -1); + assert!(!res.non_zero_reminder); - let a = BigFloat { - significand: BigInt::from_i64(100), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 100), + sign: Sign::Positive, exp: -1, non_zero_reminder: false, - }; - let res = a.to_bin(64); - assert_eq!( - res, - BigFloat { - significand: BigInt { - sign: Sign::Positive, - value: BigUint { - value: [(1 << 63) + (1 << 61)].cast() - } - }, - exp: -60, - non_zero_reminder: false - } - ); + } + .to_bin(64); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[(1 << 63) + (1 << 61)]); + } + assert_eq!(res.exp, -60); + assert!(!res.non_zero_reminder); - let a = BigFloat { - significand: BigInt { - sign: Sign::Positive, - value: BigUint { - value: [0, 1].cast(), - }, - }, + let res = BigFloat { + manager: GLOBAL, + significand: new_bigint(GLOBAL, Sign::Positive, [0, 1]), + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let res = a.to_bin(53); - assert_eq!( - res, - BigFloat { - significand: BigInt { - sign: Sign::Positive, - value: BigUint { - value: [1 << 52].cast() - } - }, - exp: 12, - non_zero_reminder: false - } - ); + } + .to_bin(53); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[1 << 52]); + } + assert_eq!(res.exp, 12); + assert!(!res.non_zero_reminder); } #[test] #[wasm_bindgen_test] fn test_rounding() { - let a = BigFloat { - significand: BigInt::from_i64(0b1000_0001), + type A = Any; + type BigintRef = JsBigintRef; + + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b1000_0001), + sign: Sign::Positive, exp: -1, non_zero_reminder: false, - }; - let res = a.to_bin(5); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(0b11001), - exp: -1, - non_zero_reminder: true - } - ); + } + .to_bin(5); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[0b11001]); + } + assert_eq!(res.exp, -1); + assert!(res.non_zero_reminder); - let a = BigFloat { - significand: BigInt::from_i64(0b1000_0001), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b1000_0001), + sign: Sign::Positive, exp: -1, non_zero_reminder: false, - }; - let res = a.to_bin(4); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(0b1100), - exp: 0, - non_zero_reminder: true - } - ); + } + .to_bin(4); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[0b1100]); + } + assert_eq!(res.exp, 0); + assert!(res.non_zero_reminder); - let a = BigFloat { - significand: BigInt::from_i64(0b1000_0001), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b1000_0001), + sign: Sign::Positive, exp: -1, non_zero_reminder: false, - }; - let res = a.to_bin(3); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(0b110), - exp: 1, - non_zero_reminder: true - } - ); + } + .to_bin(3); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[0b110]); + } + assert_eq!(res.exp, 1); + assert!(res.non_zero_reminder); } #[test] #[wasm_bindgen_test] fn test_rounding_half() { - let a = BigFloat { - significand: BigInt::from_i64(0b101_1010), + type A = Any; + type BigintRef = JsBigintRef; + + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b101_1010), + sign: Sign::Positive, exp: -1, non_zero_reminder: false, - }; - let res = a.to_bin(3); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(0b100), - exp: 1, - non_zero_reminder: true - } - ); + } + .to_bin(3); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[0b100]); + } + assert_eq!(res.exp, 1); + assert!(res.non_zero_reminder); - let a = BigFloat { - significand: BigInt::from_i64(0b101_1011), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b101_1011), + sign: Sign::Positive, exp: -1, non_zero_reminder: false, - }; - let res = a.to_bin(3); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(0b100), - exp: 1, - non_zero_reminder: true - } - ); + } + .to_bin(3); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[0b100]); + } + assert_eq!(res.exp, 1); + assert!(res.non_zero_reminder); - let a = BigFloat { - significand: BigInt::from_i64(0b110_1101), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b110_1101), + sign: Sign::Positive, exp: -1, non_zero_reminder: false, - }; - let res = a.to_bin(3); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(0b101), - exp: 1, - non_zero_reminder: true - } - ); + } + .to_bin(3); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[0b101]); + } + assert_eq!(res.exp, 1); + assert!(res.non_zero_reminder); - let a = BigFloat { - significand: BigInt::from_i64(0b110_1110), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b110_1110), + sign: Sign::Positive, exp: -1, non_zero_reminder: false, - }; - let res = a.to_bin(3); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(0b101), - exp: 1, - non_zero_reminder: true - } - ); + } + .to_bin(3); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[0b101]); + } + assert_eq!(res.exp, 1); + assert!(res.non_zero_reminder); - let a = BigFloat { - significand: BigInt::from_i64(0b1001_0110), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b1001_0110), + sign: Sign::Positive, exp: -1, non_zero_reminder: false, - }; - let res = a.to_bin(3); - assert_eq!( - res, - BigFloat { - significand: BigInt::from_i64(0b111), - exp: 1, - non_zero_reminder: true - } - ); + } + .to_bin(3); + let any = A::move_from(res.significand.to_ref()); + assert_eq!(any.get_type(), Type::Bigint); + { + let o = any.try_move::().unwrap(); + assert_eq!(o.sign(), Sign::Positive); + assert_eq!(o.items(), &[0b111]); + } + assert_eq!(res.exp, 1); + assert!(res.non_zero_reminder); } #[test] #[wasm_bindgen_test] fn test_zero_to_f64() { - let a = BigFloat { - significand: BigInt::ZERO, + type A = Any; + type BigintRef = JsBigintRef; + + let res = BigFloat { + manager: GLOBAL, + significand: zero(GLOBAL), + sign: Sign::Positive, exp: 100, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 0.0); assert!(res.is_sign_positive()); - let a = BigFloat { - significand: BigInt { - sign: Sign::Negative, - value: BigUint::ZERO, - }, + let res = BigFloat { + manager: GLOBAL, + significand: zero(GLOBAL), + sign: Sign::Negative, exp: 100, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 0.0); assert!(res.is_sign_negative()); } @@ -534,144 +671,185 @@ mod test { #[test] #[wasm_bindgen_test] fn test_normal_to_f64() { - let a = BigFloat { - significand: BigInt::from_u64(1), + type A = Any; + type BigintRef = JsBigintRef; + + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 1), + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 1.0); - let a = BigFloat { - significand: BigInt::from_i64(-3), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 3), + sign: Sign::Negative, exp: -1, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, -1.5); - let a = BigFloat { - significand: BigInt::from_i64(1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 1), + sign: Sign::Positive, exp: -1022, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 2.0f64.powf(-1022.0)); assert!(res.is_normal()); - let a = BigFloat { - significand: BigInt::from_u64(1 << 59), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 1 << 59), + sign: Sign::Positive, exp: -1022 - 59, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 2.0f64.powf(-1022.0)); assert!(res.is_normal()); - let a = BigFloat { - significand: BigInt::from_u64((1 << 60) - 1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, (1 << 60) - 1), + sign: Sign::Positive, exp: -1022 - 60, - non_zero_reminder: true, - }; - let res = a.to_f64(); + non_zero_reminder: false, + } + .to_f64(); assert_eq!(res, 2.0f64.powf(-1022.0)); assert!(res.is_normal()); - let a = BigFloat { - significand: BigInt::from_i64(1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 1), + sign: Sign::Positive, exp: 1023, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 2.0f64.powf(1023.0)); - let a = BigFloat { - significand: BigInt::from_u64((1 << 52) - 1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, (1 << 52) - 1), + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 4503599627370495f64); - let a = BigFloat { - significand: BigInt::from_u64((1 << 53) - 1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, (1 << 53) - 1), + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 9007199254740991f64); } #[test] #[wasm_bindgen_test] fn test_normal_to_f64_rounding() { - let a = BigFloat { - significand: BigInt::from_u64((1 << 54) - 1), //111111111111111111111111111111111111111111111111111111 + type A = Any; + type BigintRef = JsBigintRef; + + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, (1 << 54) - 1), //111111111111111111111111111111111111111111111111111111 + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 18014398509481984f64); - let a = BigFloat { - significand: BigInt::from_u64((1 << 54) - 2), //111111111111111111111111111111111111111111111111111110 + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, (1 << 54) - 2), //111111111111111111111111111111111111111111111111111110 + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 18014398509481982f64); - let a = BigFloat { - significand: BigInt::from_u64((1 << 54) - 3), //111111111111111111111111111111111111111111111111111101 + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, (1 << 54) - 3), //111111111111111111111111111111111111111111111111111101 + sign: Sign::Positive, exp: 0, non_zero_reminder: true, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 18014398509481982f64); - let a = BigFloat { - significand: BigInt::from_u64((1 << 54) - 3), //111111111111111111111111111111111111111111111111111101 + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, (1 << 54) - 3), //111111111111111111111111111111111111111111111111111101 + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 18014398509481980f64); - let a = BigFloat { - significand: BigInt::from_u64((1 << 54) - 1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, (1 << 54) - 1), + sign: Sign::Positive, exp: 969, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert!(res.is_normal()); - let a = BigFloat { - significand: BigInt::from_u64((1 << 54) - 1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, (1 << 54) - 1), + sign: Sign::Positive, exp: 970, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert!(res.is_infinite()); } #[test] #[wasm_bindgen_test] fn test_infinity_to_f64() { - let a = BigFloat { - significand: BigInt::from_i64(1), + type A = Any; + type BigintRef = JsBigintRef; + + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 1), + sign: Sign::Positive, exp: 1024, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert!(res.is_infinite()); assert!(res.is_sign_positive()); - let a = BigFloat { - significand: BigInt::from_i64(-1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 1), + sign: Sign::Negative, exp: 1024, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert!(res.is_infinite()); assert!(res.is_sign_negative()); } @@ -679,130 +857,160 @@ mod test { #[test] #[wasm_bindgen_test] fn test_subnormal_to_f64() { - let a = BigFloat { - significand: BigInt::from_u64(1), + type A = Any; + type BigintRef = JsBigintRef; + + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 1), + sign: Sign::Positive, exp: -1023, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 2.0f64.powf(-1023.0)); assert!(res.is_subnormal()); - let a = BigFloat { - significand: BigInt::from_i64(-1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 1), + sign: Sign::Negative, exp: -1023, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, -(2.0f64.powf(-1023.0))); assert!(res.is_subnormal()); - let a = BigFloat { - significand: BigInt::from_u64(1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 1), + sign: Sign::Positive, exp: -1074, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res.to_bits(), 1); assert_eq!(res, 2.0f64.powf(-1074.0)); assert!(res.is_subnormal()); - let a = BigFloat { - significand: BigInt::from_u64(1), + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 1), + sign: Sign::Positive, exp: -1075, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res, 0.0); } #[test] #[wasm_bindgen_test] fn test_subnormal_to_f64_rounding() { - //0.0 => 0 - let a = BigFloat { - significand: BigInt::from_u64(0b100), + type A = Any; + type BigintRef = JsBigintRef; + + // 0.0 => 0 + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b100), + sign: Sign::Positive, exp: -1075, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res.to_bits(), 0b10); assert_eq!(res, 2.0f64.powf(-1073.0)); assert!(res.is_subnormal()); - //0.0+ => 0 - let a = BigFloat { - significand: BigInt::from_u64(0b100), + // 0.0+ => 0 + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b100), + sign: Sign::Positive, exp: -1075, non_zero_reminder: true, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res.to_bits(), 0b10); assert_eq!(res, 2.0f64.powf(-1073.0)); assert!(res.is_subnormal()); - //0.1 => 0 - let a = BigFloat { - significand: BigInt::from_u64(0b101), + // 0.1 => 0 + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b101), + sign: Sign::Positive, exp: -1075, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res.to_bits(), 0b10); assert_eq!(res, 2.0f64.powf(-1073.0)); assert!(res.is_subnormal()); - //0.1+ => 1 - let a = BigFloat { - significand: BigInt::from_u64(0b101), + // 0.1+ => 1 + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b101), + sign: Sign::Positive, exp: -1075, non_zero_reminder: true, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res.to_bits(), 0b11); assert_eq!(res, 1.5f64 * 2.0f64.powf(-1073.0)); assert!(res.is_subnormal()); - //1.0 => 1 - let a = BigFloat { - significand: BigInt::from_u64(0b110), + // 1.0 => 1 + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b110), + sign: Sign::Positive, exp: -1075, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res.to_bits(), 0b11); assert_eq!(res, 1.5f64 * 2.0f64.powf(-1073.0)); assert!(res.is_subnormal()); - //1.0+ => 1 - let a = BigFloat { - significand: BigInt::from_u64(0b110), + // 1.0+ => 1 + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b110), + sign: Sign::Positive, exp: -1075, - non_zero_reminder: false, - }; - let res = a.to_f64(); + non_zero_reminder: true, + } + .to_f64(); assert_eq!(res.to_bits(), 0b11); assert_eq!(res, 1.5f64 * 2.0f64.powf(-1073.0)); assert!(res.is_subnormal()); - //1.1 => 2 - let a = BigFloat { - significand: BigInt::from_u64(0b111), + // 1.1 => 2 + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b111), + sign: Sign::Positive, exp: -1075, non_zero_reminder: false, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res.to_bits(), 0b100); assert_eq!(res, 2.0f64.powf(-1072.0)); assert!(res.is_subnormal()); - //1.1+ => 2 - let a = BigFloat { - significand: BigInt::from_u64(0b111), + // 1.1+ => 2 + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, 0b111), + sign: Sign::Positive, exp: -1075, non_zero_reminder: true, - }; - let res = a.to_f64(); + } + .to_f64(); assert_eq!(res.to_bits(), 0b100); assert_eq!(res, 2.0f64.powf(-1072.0)); assert!(res.is_subnormal()); @@ -818,13 +1026,18 @@ mod test { test(18014398509481985); fn test(n: u64) { - let big_float = BigFloat { - significand: BigInt::from_u64(n), + type A = Any; + type BigintRef = JsBigintRef; + + let res = BigFloat { + manager: GLOBAL, + significand: from_u64(GLOBAL, Sign::Positive, n), + sign: Sign::Positive, exp: 0, non_zero_reminder: false, - }; - let f64 = big_float.to_f64(); - assert_eq!(f64, n as f64); + } + .to_f64(); + assert_eq!(res, n as f64); } } } diff --git a/nanvm-lib/src/js/js_bigint.rs b/nanvm-lib/src/js/js_bigint.rs index 9b1e1225..ab1aea98 100644 --- a/nanvm-lib/src/js/js_bigint.rs +++ b/nanvm-lib/src/js/js_bigint.rs @@ -15,12 +15,13 @@ use crate::{ use super::{bitset::BIGINT, ref_cast::RefCast}; -#[derive(Debug, PartialEq, Clone, Eq)] +#[derive(Debug, PartialEq, Clone, Copy, Eq)] pub enum Sign { Positive = 1, Negative = -1, } +#[derive(Debug)] pub struct JsBigintHeader { len: isize, } @@ -125,6 +126,23 @@ pub fn is_zero(value: &JsBigint) -> bool { value.items().is_empty() } +impl JsBigint { + pub fn compare(&self, other: &Self) -> Ordering { + match self.header_len().cmp(&other.header_len()) { + Ordering::Equal => cmp_vec(self.items(), other.items()), + Ordering::Less => Ordering::Less, + Ordering::Greater => Ordering::Greater, + } + } + + pub fn get_last_bit(&self) -> u64 { + if is_zero(self) { + return 0; + } + self.items()[0] & 1 + } +} + pub fn negative(m: M, value: &JsBigint) -> JsBigintMutRef { if is_zero(value) { return zero(m); @@ -210,7 +228,7 @@ pub fn div_mod( let mut result: Vec = default(); loop { if cmp_vec(&a, b) == Ordering::Less { - return (new_bigint(m, sign.clone(), result), new_bigint(m, sign, a)); + return (new_bigint(m, sign, result), new_bigint(m, sign, a)); } let a_high_digit = a.len() - 1; let b_high_digit = b.len() - 1; @@ -356,6 +374,13 @@ pub fn shr(m: M, lhs: &JsBigint, rhs: &JsBigint) -> JsBigintMutRef bool { + if lhs.sign() != rhs.sign() { + return false; + } + return cmp_vec(lhs.items(), rhs.items()) == Ordering::Equal; +} + fn to_twos_complement(value: &JsBigint) -> TwosComplement { TwosComplement { sign: value.sign(), @@ -449,7 +474,7 @@ fn twos_complement_zip<'a>( } impl JsBigint { - fn sign(&self) -> Sign { + pub fn sign(&self) -> Sign { if self.header.len < 0 { Sign::Negative } else { @@ -522,7 +547,7 @@ fn cmp_vec(lhs: &[u64], rhs: &[u64]) -> Ordering { Ordering::Equal } -fn shl_on_u64(m: M, lhs: &JsBigint, rhs: u64) -> JsBigintMutRef { +pub fn shl_on_u64(m: M, lhs: &JsBigint, rhs: u64) -> JsBigintMutRef { let mut vec = lhs.items().to_vec(); let shift_mod = rhs & ((1 << 6) - 1); if shift_mod > 0 { @@ -547,7 +572,7 @@ fn shl_on_u64(m: M, lhs: &JsBigint, rhs: u64) -> JsBigintMutRef(m: M, lhs: &JsBigint, rhs: u64) -> JsBigintMutRef { +pub fn shr_on_u64(m: M, lhs: &JsBigint, rhs: u64) -> JsBigintMutRef { let number_to_remove = (rhs / 64) as usize; if number_to_remove >= lhs.items().len() { return shr_on_big(m, lhs.sign()); @@ -586,7 +611,7 @@ fn shr_on_big(m: M, sign: Sign) -> JsBigintMutRef { #[cfg(test)] mod test { - use std::ops::Deref; + use std::{cmp::Ordering, ops::Deref}; use wasm_bindgen_test::wasm_bindgen_test; @@ -736,6 +761,37 @@ mod test { } } + #[test] + #[wasm_bindgen_test] + fn test_cmp() { + type A = Any; + type BigintRef = JsBigintRef; + + let a_ref = from_u64(Global(), Sign::Positive, 1); + let b_ref = from_u64(Global(), Sign::Positive, 1); + let a = a_ref.deref(); + let b = b_ref.deref(); + assert_eq!(a.compare(b), Ordering::Equal); + + let a_ref = from_u64(Global(), Sign::Positive, 1); + let b_ref = from_u64(Global(), Sign::Positive, 2); + let a = a_ref.deref(); + let b = b_ref.deref(); + assert_eq!(a.compare(b), Ordering::Less); + + let a_ref = from_u64(Global(), Sign::Positive, 1); + let b_ref = from_u64(Global(), Sign::Negative, 2); + let a = a_ref.deref(); + let b = b_ref.deref(); + assert_eq!(a.compare(b), Ordering::Greater); + + let a_ref = new_bigint(Global(), Sign::Positive, [1, 2]); + let b_ref = new_bigint(Global(), Sign::Positive, [2, 1]); + let a = a_ref.deref(); + let b = b_ref.deref(); + assert_eq!(a.compare(b), Ordering::Greater); + } + #[test] #[wasm_bindgen_test] fn test_shl_zero() { diff --git a/nanvm-lib/src/mem/flexible_array/mod.rs b/nanvm-lib/src/mem/flexible_array/mod.rs index b2fd0d1f..8468d4ce 100644 --- a/nanvm-lib/src/mem/flexible_array/mod.rs +++ b/nanvm-lib/src/mem/flexible_array/mod.rs @@ -12,6 +12,7 @@ use self::header::FlexibleArrayHeader; use super::{field_layout::FieldLayout, object::Object}; #[repr(transparent)] +#[derive(Debug)] pub struct FlexibleArray { pub header: T, _0: PhantomData, diff --git a/nanvm-lib/src/parser/analyzer.rs b/nanvm-lib/src/parser/analyzer.rs index 5af5a26c..057d853c 100644 --- a/nanvm-lib/src/parser/analyzer.rs +++ b/nanvm-lib/src/parser/analyzer.rs @@ -1,7 +1,7 @@ use super::shared::DataType; use crate::ast::Module; use crate::common::default::default; -use crate::mem::manager::Dealloc; +use crate::mem::manager::{Dealloc, Manager}; use crate::tokenizer::{create_transition_maps, JsonToken, TokenizerState, TransitionMaps}; #[derive(Default)] @@ -21,17 +21,17 @@ pub struct AnalyzerResults { pub diagnostics: Vec, } -pub struct AnalyzerState { +pub struct AnalyzerState { parameters: AnalyzerParameters, - tokenizer_state: TokenizerState, - tokenizer_maps: TransitionMaps, + tokenizer_state: TokenizerState, + tokenizer_maps: TransitionMaps, diagnostics_len: usize, // TODO: add line number, column number tracking fields (needed for diagnostics). - module: Module, + module: Module, diagnostics: Vec, } -impl AnalyzerState { +impl AnalyzerState { /// Creates a new analyzer staring state. The caller should check `diagnostics` for errors /// immediately after creation (since `parameters` value can be inconsistent). pub fn new(parameters: AnalyzerParameters) -> Self { @@ -48,8 +48,11 @@ impl AnalyzerState { /// Updates analyzer state with a next input character; the result is the increment in the count /// of `diagnostics`. It's up to the caller to check what was added at the end of `diagnostics` /// - are there any fatal errors, from the point of view of the current parsing session? - pub fn push_mut(&mut self, c: char) -> usize { - for token in self.tokenizer_state.push_mut(c, &self.tokenizer_maps) { + pub fn push_mut(&mut self, manager: M, c: char) -> usize { + for token in self + .tokenizer_state + .push_mut(manager, c, &self.tokenizer_maps) + { self.process_token(token); } let prior_diagnostics_len = self.diagnostics_len; @@ -58,7 +61,7 @@ impl AnalyzerState { } /// Completes the analysis. - pub fn end(self) -> AnalyzerResults { + pub fn end(self) -> AnalyzerResults { // TODO: in case the current state is not a valid end state, add an error to self.diagnostics. AnalyzerResults { module: self.module, @@ -66,5 +69,5 @@ impl AnalyzerState { } } - fn process_token(&mut self, _token: JsonToken) {} + fn process_token(&mut self, _token: JsonToken) {} } diff --git a/nanvm-lib/src/parser/any_state.rs b/nanvm-lib/src/parser/any_state.rs index 00d78627..59716bb4 100644 --- a/nanvm-lib/src/parser/any_state.rs +++ b/nanvm-lib/src/parser/any_state.rs @@ -70,7 +70,7 @@ impl AnyState { pub fn parse( self, manager: M, - token: JsonToken, + token: JsonToken, ) -> ( /*any_result:*/ AnyResult, /*module_name:*/ Option, @@ -95,7 +95,7 @@ impl AnyState { pub fn parse_for_module( self, manager: M, - token: JsonToken, + token: JsonToken, ) -> ( /*json_state:*/ JsonState, /*module_name:*/ Option, @@ -123,7 +123,7 @@ impl AnyState { } } - pub fn parse_import_begin(self, token: JsonToken) -> AnyResult { + pub fn parse_import_begin(self, token: JsonToken) -> AnyResult { match token { JsonToken::OpeningParenthesis => AnyResult::Continue(AnyState { status: ParsingStatus::ImportValue, @@ -133,7 +133,7 @@ impl AnyState { } } - pub fn parse_import_end(self, token: JsonToken) -> AnyResult { + pub fn parse_import_end(self, token: JsonToken) -> AnyResult { match token { JsonToken::ClosingParenthesis => self.end_import(), _ => AnyResult::Error(ParseError::WrongRequireStatement), @@ -142,7 +142,7 @@ impl AnyState { fn parse_import_value( self, - token: JsonToken, + token: JsonToken, ) -> ( /*any_result:*/ AnyResult, /*module_name:*/ Option, @@ -189,7 +189,7 @@ impl AnyState { } } - pub fn parse_value(self, manager: M, token: JsonToken) -> AnyResult { + pub fn parse_value(self, manager: M, token: JsonToken) -> AnyResult { match token { JsonToken::ArrayBegin => self.begin_array(), JsonToken::ObjectBegin => self.begin_object(), @@ -258,7 +258,7 @@ impl AnyState { } } - pub fn parse_array_comma(self, manager: M, token: JsonToken) -> AnyResult { + pub fn parse_array_comma(self, manager: M, token: JsonToken) -> AnyResult { match token { JsonToken::ArrayBegin => self.begin_array(), JsonToken::ObjectBegin => self.begin_object(), @@ -276,7 +276,7 @@ impl AnyState { } } - pub fn parse_array_begin(self, manager: M, token: JsonToken) -> AnyResult { + pub fn parse_array_begin(self, manager: M, token: JsonToken) -> AnyResult { match token { JsonToken::ArrayBegin => self.begin_array(), JsonToken::ArrayEnd => self.end_array(manager), @@ -291,7 +291,7 @@ impl AnyState { } } - pub fn parse_array_value(self, manager: M, token: JsonToken) -> AnyResult { + pub fn parse_array_value(self, manager: M, token: JsonToken) -> AnyResult { match token { JsonToken::ArrayEnd => self.end_array(manager), JsonToken::Comma => AnyResult::Continue(AnyState { @@ -329,7 +329,7 @@ impl AnyState { } } - pub fn parse_object_begin(self, manager: M, token: JsonToken) -> AnyResult { + pub fn parse_object_begin(self, manager: M, token: JsonToken) -> AnyResult { match token { JsonToken::String(s) => self.push_key(s), JsonToken::Id(s) if self.data_type.is_djs() => self.push_key(s), @@ -338,7 +338,7 @@ impl AnyState { } } - pub fn parse_object_next(self, manager: M, token: JsonToken) -> AnyResult { + pub fn parse_object_next(self, manager: M, token: JsonToken) -> AnyResult { match token { JsonToken::ObjectEnd => self.end_object(manager), JsonToken::Comma => AnyResult::Continue(AnyState { @@ -349,7 +349,7 @@ impl AnyState { } } - pub fn parse_object_comma(self, manager: M, token: JsonToken) -> AnyResult { + pub fn parse_object_comma(self, manager: M, token: JsonToken) -> AnyResult { match token { JsonToken::String(s) => self.push_key(s), JsonToken::ObjectEnd => self.end_object(manager), @@ -357,7 +357,7 @@ impl AnyState { } } - pub fn parse_object_key(self, token: JsonToken) -> AnyResult { + pub fn parse_object_key(self, token: JsonToken) -> AnyResult { match token { JsonToken::Colon => AnyResult::Continue(AnyState { status: ParsingStatus::ObjectColon, diff --git a/nanvm-lib/src/parser/const_state.rs b/nanvm-lib/src/parser/const_state.rs index 62c2f7d8..9f9b0576 100644 --- a/nanvm-lib/src/parser/const_state.rs +++ b/nanvm-lib/src/parser/const_state.rs @@ -11,7 +11,7 @@ pub struct ConstState { } impl ConstState { - pub fn parse(self, manager: M, token: JsonToken) -> JsonState { + pub fn parse(self, manager: M, token: JsonToken) -> JsonState { match token { JsonToken::Semicolon => todo!(), _ => { diff --git a/nanvm-lib/src/parser/json_state.rs b/nanvm-lib/src/parser/json_state.rs index fb096950..af16605c 100644 --- a/nanvm-lib/src/parser/json_state.rs +++ b/nanvm-lib/src/parser/json_state.rs @@ -18,12 +18,12 @@ impl JsonState { pub fn push( self, manager: M, - token: JsonToken, + token: JsonToken, ) -> ( /*json_state:*/ JsonState, /*import:*/ Option<(/*id:*/ String, /*module:*/ String)>, ) { - if token == JsonToken::NewLine { + if let JsonToken::NewLine = token { return match self { JsonState::ParseRoot(state) => state.parse(manager, token), _ => (self, None), diff --git a/nanvm-lib/src/parser/parser.rs b/nanvm-lib/src/parser/parser.rs index 3dd9cf21..ef2584d4 100644 --- a/nanvm-lib/src/parser/parser.rs +++ b/nanvm-lib/src/parser/parser.rs @@ -36,10 +36,10 @@ impl<'a, M: Manager, I: Io> Context<'a, M, I> { } } -fn const_state_parse( +fn const_state_parse( const_state: ConstState, context: &mut Context, - token: JsonToken, + token: JsonToken, ) -> JsonState { match token { JsonToken::Semicolon => todo!(), @@ -64,10 +64,10 @@ fn const_state_parse( } } -fn any_state_parse_for_module( +fn any_state_parse_for_module( any_state: AnyState, context: &mut Context, - token: JsonToken, + token: JsonToken, ) -> JsonState { let result = any_state_parse(any_state, context, token); match result { @@ -80,10 +80,10 @@ fn any_state_parse_for_module( } } -fn any_state_parse_import_value( +fn any_state_parse_import_value( any_state: AnyState, context: &mut Context, - token: JsonToken, + token: JsonToken, ) -> AnyResult { match token { JsonToken::String(s) => { @@ -102,7 +102,7 @@ fn any_state_parse_import_value( let read_result = context.io.read_to_string(current_path.as_str()); match read_result { Ok(s) => { - let tokens = tokenize(s); + let tokens = tokenize(context.manager, s); let res = parse_with_tokens(context, tokens.into_iter()); match res { Ok(r) => { @@ -127,10 +127,10 @@ fn any_state_parse_import_value( } } -fn any_state_parse( +fn any_state_parse( any_state: AnyState, context: &mut Context, - token: JsonToken, + token: JsonToken, ) -> AnyResult { match any_state.status { ParsingStatus::Initial | ParsingStatus::ObjectColon => { @@ -149,10 +149,10 @@ fn any_state_parse( } } -fn root_state_parse( +fn root_state_parse( root_state: RootState, context: &mut Context, - token: JsonToken, + token: JsonToken, ) -> JsonState { let (json_state, import) = root_state.parse(context.manager, token); match import { @@ -175,7 +175,7 @@ fn root_state_parse( let read_result = context.io.read_to_string(current_path.as_str()); match read_result { Ok(s) => { - let tokens = tokenize(s); + let tokens = tokenize(context.manager, s); let res = parse_with_tokens(context, tokens.into_iter()); match res { Ok(r) => { @@ -202,12 +202,12 @@ fn root_state_parse( } } -fn json_state_push( +fn json_state_push( json_state: JsonState, context: &mut Context, - token: JsonToken, + token: JsonToken, ) -> JsonState { - if token == JsonToken::NewLine { + if let JsonToken::NewLine = token { return match json_state { JsonState::ParseRoot(state) => root_state_parse(state, context, token), _ => json_state, @@ -222,23 +222,23 @@ fn json_state_push( } } -pub fn parse( +pub fn parse( context: &mut Context, ) -> Result, ParseError> { context.module_cache.progress.insert(context.path.clone()); let read_result = context.io.read_to_string(context.path.as_str()); match read_result { Ok(s) => { - let tokens = tokenize(s); + let tokens = tokenize(context.manager, s); parse_with_tokens(context, tokens.into_iter()) } Err(_) => Err(ParseError::CannotReadFile), } } -pub fn parse_with_tokens( +pub fn parse_with_tokens( context: &mut Context, - iter: impl Iterator, + iter: impl Iterator>, ) -> Result, ParseError> { let mut state = JsonState::ParseRoot(RootState { status: RootStatus::Initial, @@ -258,14 +258,13 @@ mod test { use wasm_bindgen_test::wasm_bindgen_test; use crate::{ - big_numbers::{ - big_int::{BigInt, Sign}, - big_uint::BigUint, - }, common::default::default, js::{ - js_array::JsArrayRef, js_bigint::JsBigintRef, js_object::JsObjectRef, - js_string::JsStringRef, type_::Type, + js_array::JsArrayRef, + js_bigint::{from_u64, new_bigint, JsBigintRef, Sign}, + js_object::JsObjectRef, + js_string::JsStringRef, + type_::Type, }, mem::{global::GLOBAL, local::Local, manager::Manager}, tokenizer::{tokenize, ErrorType, JsonToken}, @@ -287,9 +286,9 @@ mod test { Context::new(manager, io, default(), module_cache) } - fn parse_with_virtual_io( + fn parse_with_virtual_io( manager: M, - iter: impl Iterator, + iter: impl Iterator>, ) -> Result, ParseError> { parse_with_tokens( &mut create_test_context(manager, &virtual_io(), &mut default()), @@ -297,14 +296,6 @@ mod test { ) } - fn test_local() { - let local = Local::default(); - let _ = parse_with_tokens( - &mut create_test_context(&local, &virtual_io(), &mut default()), - [].into_iter(), - ); - } - fn test_global() { let _ = { let global = GLOBAL; @@ -319,9 +310,8 @@ mod test { #[wasm_bindgen_test] fn test_json() { let json_str = include_str!("../../test/test-json.json"); - let tokens = tokenize(json_str.to_owned()); - let local = Local::default(); - let result = parse_with_virtual_io(&local, tokens.into_iter()); + let tokens = tokenize(GLOBAL, json_str.to_owned()); + let result = parse_with_virtual_io(GLOBAL, tokens.into_iter()); assert!(result.is_ok()); assert_eq!(result.unwrap().data_type, DataType::Json); } @@ -330,16 +320,14 @@ mod test { #[wasm_bindgen_test] fn test_djs() { let json_str = include_str!("../../test/test-djs.d.cjs"); - let tokens = tokenize(json_str.to_owned()); - let local = Local::default(); - let result = parse_with_virtual_io(&local, tokens.into_iter()); + let tokens = tokenize(GLOBAL, json_str.to_owned()); + let result = parse_with_virtual_io(GLOBAL, tokens.into_iter()); assert!(result.is_ok()); assert_eq!(result.unwrap().data_type, DataType::Cjs); let json_str = include_str!("../../test/test-djs.d.mjs"); - let tokens = tokenize(json_str.to_owned()); - let local = Local::default(); - let result = parse_with_virtual_io(&local, tokens.into_iter()); + let tokens = tokenize(GLOBAL, json_str.to_owned()); + let result = parse_with_virtual_io(GLOBAL, tokens.into_iter()); assert!(result.is_ok()); assert_eq!(result.unwrap().data_type, DataType::Mjs); } @@ -347,13 +335,12 @@ mod test { #[test] #[wasm_bindgen_test] fn test_const() { - let local = Local::default(); - test_const_with_manager(&local); + test_const_with_manager(GLOBAL); } - fn test_const_with_manager(manager: M) { + fn test_const_with_manager(manager: M) { let json_str = include_str!("../../test/test-const.d.cjs"); - let tokens = tokenize(json_str.to_owned()); + let tokens = tokenize(manager, json_str.to_owned()); let result = parse_with_virtual_io(manager, tokens.into_iter()); assert!(result.is_ok()); let result_unwrap = result @@ -368,12 +355,12 @@ mod test { assert_eq!(item1.try_move(), Ok(2.0)); let json_str = include_str!("../../test/test-const-error.d.cjs.txt"); - let tokens = tokenize(json_str.to_owned()); + let tokens = tokenize(manager, json_str.to_owned()); let result = parse_with_virtual_io(manager, tokens.into_iter()); assert!(result.is_err()); let json_str = include_str!("../../test/test-const-error-new-line.d.cjs.txt"); - let tokens = tokenize(json_str.to_owned()); + let tokens = tokenize(manager, json_str.to_owned()); let result = parse_with_virtual_io(manager, tokens.into_iter()); assert!(result.is_err()); assert_eq!(result.unwrap_err(), ParseError::NewLineExpected); @@ -382,13 +369,12 @@ mod test { #[test] #[wasm_bindgen_test] fn test_stack() { - let local = Local::default(); - test_stack_with_manager(&local); + test_stack_with_manager(GLOBAL); } - fn test_stack_with_manager(manager: M) { + fn test_stack_with_manager(manager: M) { let json_str = include_str!("../../test/test-stack.d.cjs"); - let tokens = tokenize(json_str.to_owned()); + let tokens = tokenize(manager, json_str.to_owned()); let result = parse_with_virtual_io(manager, tokens.into_iter()); assert!(result.is_ok()); let result_unwrap = result @@ -412,11 +398,10 @@ mod test { #[test] #[wasm_bindgen_test] fn test_import() { - let local = Local::default(); - test_import_with_manager(&local); + test_import_with_manager(GLOBAL); } - fn test_import_with_manager(manager: M) { + fn test_import_with_manager(manager: M) { let io: VirtualIo = VirtualIo::new(&[]); let main = include_str!("../../test/test_import_main.d.cjs"); @@ -481,11 +466,10 @@ mod test { #[test] #[wasm_bindgen_test] fn test_cache() { - let local = Local::default(); - test_cache_with_manager(&local); + test_cache_with_manager(GLOBAL); } - fn test_cache_with_manager(manager: M) { + fn test_cache_with_manager(manager: M) { let io: VirtualIo = VirtualIo::new(&[]); let main = include_str!("../../test/test_cache_main.d.cjs"); @@ -560,11 +544,10 @@ mod test { #[test] #[wasm_bindgen_test] fn test_circular_error() { - let local = Local::default(); - test_circular_error_with_manager(&local); + test_circular_error_with_manager(GLOBAL); } - fn test_circular_error_with_manager(manager: M) { + fn test_circular_error_with_manager(manager: M) { let io: VirtualIo = VirtualIo::new(&[]); let main = include_str!("../../test/test_circular_1.d.cjs.txt"); @@ -613,11 +596,10 @@ mod test { #[test] #[wasm_bindgen_test] fn test_import_error() { - let local = Local::default(); - test_import_error_with_manager(&local); + test_import_error_with_manager(GLOBAL); } - fn test_import_error_with_manager(manager: M) { + fn test_import_error_with_manager(manager: M) { let io: VirtualIo = VirtualIo::new(&[]); let main = include_str!("../../test/test_import_error.d.cjs.txt"); @@ -668,17 +650,15 @@ mod test { #[test] #[wasm_bindgen_test] fn test_trailing_comma() { - let local = Local::default(); let json_str = include_str!("../../test/test-trailing-comma.d.cjs"); - let tokens = tokenize(json_str.to_owned()); - let result = parse_with_virtual_io(&local, tokens.into_iter()); + let tokens = tokenize(GLOBAL, json_str.to_owned()); + let result = parse_with_virtual_io(GLOBAL, tokens.into_iter()); assert!(result.is_ok()); } #[test] #[wasm_bindgen_test] fn test_check_sizes() { - let local = Local::default(); { let tokens = [ JsonToken::ObjectBegin, @@ -689,11 +669,11 @@ mod test { JsonToken::ObjectEnd, ]; { - let result = parse_with_virtual_io(&local, tokens.into_iter()); + let result = parse_with_virtual_io(GLOBAL, tokens.into_iter()); assert!(result.is_ok()); let _result_unwrap = result.unwrap(); } - assert_eq!(local.size(), 0); + //assert_eq!(GLOBAL.size(), 0); } } @@ -711,7 +691,7 @@ mod test { JsonToken::ObjectEnd, ]; { - let result = parse_with_virtual_io(&local, tokens.into_iter()); + let result = parse_with_virtual_io(GLOBAL, tokens.into_iter()); assert!(result.is_ok()); let result_unwrap = result.unwrap().any; let _result_unwrap = result_unwrap.try_move::>(); @@ -723,9 +703,8 @@ mod test { #[test] #[wasm_bindgen_test] fn test_data_type() { - let local = Local::default(); let tokens = [JsonToken::Id(String::from("null"))]; - let result = parse_with_virtual_io(&local, tokens.into_iter()); + let result = parse_with_virtual_io(GLOBAL, tokens.into_iter()); assert!(result.is_ok()); assert_eq!(result.unwrap().data_type, DataType::Json); } @@ -733,17 +712,15 @@ mod test { #[test] #[wasm_bindgen_test] fn test_export_block() { - let local = Local::default(); let tokens = [ JsonToken::Id(String::from("export")), JsonToken::Id(String::from("default")), JsonToken::Id(String::from("null")), ]; - let result = parse_with_virtual_io(&local, tokens.into_iter()); + let result = parse_with_virtual_io(GLOBAL, tokens.into_iter()); assert!(result.is_ok()); assert_eq!(result.unwrap().data_type, DataType::Mjs); - let local = Local::default(); let tokens = [ JsonToken::Id(String::from("module")), JsonToken::Dot, @@ -751,7 +728,7 @@ mod test { JsonToken::Equals, JsonToken::Id(String::from("null")), ]; - let result = parse_with_virtual_io(&local, tokens.into_iter()); + let result = parse_with_virtual_io(GLOBAL, tokens.into_iter()); assert!(result.is_ok()); assert_eq!(result.unwrap().data_type, DataType::Cjs); } @@ -759,7 +736,6 @@ mod test { #[test] #[wasm_bindgen_test] fn test_id_in_objects() { - let local = Local::default(); let tokens = [ JsonToken::Id(String::from("export")), JsonToken::Id(String::from("default")), @@ -769,7 +745,7 @@ mod test { JsonToken::Number(0.0), JsonToken::ObjectEnd, ]; - let result = parse_with_virtual_io(&local, tokens.into_iter()); + let result = parse_with_virtual_io(GLOBAL, tokens.into_iter()); assert!(result.is_ok()); let result_unwrap = result.unwrap().any.try_move::>().unwrap(); let items = result_unwrap.items(); @@ -778,7 +754,6 @@ mod test { assert_eq!(key0_items, [0x6b, 0x65, 0x79]); assert_eq!(value0.try_move(), Ok(0.0)); - let local = Local::default(); let tokens = [ JsonToken::ObjectBegin, JsonToken::Id(String::from("key")), @@ -786,23 +761,17 @@ mod test { JsonToken::Number(0.0), JsonToken::ObjectEnd, ]; - let result = parse_with_virtual_io(&local, tokens.into_iter()); + let result = parse_with_virtual_io(GLOBAL, tokens.into_iter()); assert!(result.is_err()); } - #[test] - #[wasm_bindgen_test] - fn test_valid_local() { - test_valid_with_manager(&Local::default()); - } - #[test] #[wasm_bindgen_test] fn test_valid_global() { test_valid_with_manager(GLOBAL); } - fn test_valid_with_manager(manager: M) { + fn test_valid_with_manager(manager: M) { let tokens = [JsonToken::Id(String::from("null"))]; let result = parse_with_virtual_io(manager, tokens.into_iter()); assert!(result.is_ok()); @@ -832,12 +801,7 @@ mod test { let items = result.items(); assert_eq!(items, [0x61, 0x62, 0x63]); - let tokens = [JsonToken::BigInt(BigInt { - sign: Sign::Positive, - value: BigUint { - value: [1].to_vec(), - }, - })]; + let tokens = [JsonToken::BigInt(from_u64(manager, Sign::Positive, 1))]; let result = parse_with_virtual_io(manager, tokens.into_iter()); assert!(result.is_ok()); let result = result.unwrap().any.try_move::>(); @@ -847,12 +811,11 @@ mod test { let items = result.items(); assert_eq!(items, [0x1]); - let tokens = [JsonToken::BigInt(BigInt { - sign: Sign::Negative, - value: BigUint { - value: [2, 3].to_vec(), - }, - })]; + let tokens = [JsonToken::BigInt(new_bigint( + manager, + Sign::Negative, + [2, 3], + ))]; let result = parse_with_virtual_io(manager, tokens.into_iter()); assert!(result.is_ok()); let result = result.unwrap().any.try_move::>(); @@ -974,19 +937,13 @@ mod test { } } - #[test] - #[wasm_bindgen_test] - fn test_invalid_local() { - test_invalid_with_manager(&Local::default()); - } - #[test] #[wasm_bindgen_test] fn test_invalid_global() { test_invalid_with_manager(GLOBAL); } - fn test_invalid_with_manager(manager: M) { + fn test_invalid_with_manager(manager: M) { let tokens = []; let result = parse_with_virtual_io(manager, tokens.into_iter()); assert!(result.is_err()); diff --git a/nanvm-lib/src/parser/root_state.rs b/nanvm-lib/src/parser/root_state.rs index 38dcf1e1..1b6c1224 100644 --- a/nanvm-lib/src/parser/root_state.rs +++ b/nanvm-lib/src/parser/root_state.rs @@ -27,7 +27,7 @@ impl RootState { pub fn parse( self, manager: M, - token: JsonToken, + token: JsonToken, ) -> ( /*json_state:*/ JsonState, /*import:*/ Option<(/*id:*/ String, /*module:*/ String)>, diff --git a/nanvm-lib/src/parser/shared.rs b/nanvm-lib/src/parser/shared.rs index 6546d2be..d42d2d57 100644 --- a/nanvm-lib/src/parser/shared.rs +++ b/nanvm-lib/src/parser/shared.rs @@ -152,8 +152,8 @@ fn try_id_to_any( } } -impl JsonToken { - pub fn try_to_any( +impl JsonToken { + pub fn try_to_any>( self, manager: M, consts: &BTreeMap>, @@ -162,7 +162,7 @@ impl JsonToken { JsonToken::Number(f) => Some(Any::move_from(f)), JsonToken::String(s) => Some(Any::move_from(to_js_string(manager, s))), JsonToken::Id(s) => try_id_to_any(&s, manager, consts), - JsonToken::BigInt(b) => Some(Any::move_from(to_js_bigint(manager, b))), + JsonToken::BigInt(b) => Some(Any::move_from(b.to_ref())), _ => None, } } diff --git a/nanvm-lib/src/tokenizer/mod.rs b/nanvm-lib/src/tokenizer/mod.rs index 10777a83..e27a88b0 100644 --- a/nanvm-lib/src/tokenizer/mod.rs +++ b/nanvm-lib/src/tokenizer/mod.rs @@ -1,17 +1,19 @@ -use std::{collections::VecDeque, mem::take, ops::RangeInclusive}; +use std::{ + collections::VecDeque, + mem::take, + ops::{Deref, RangeInclusive}, +}; use crate::{ - big_numbers::{ - big_float::BigFloat, - big_int::{BigInt, Sign}, - big_uint::BigUint, - }, + big_numbers::big_float::BigFloat, common::{cast::Cast, default::default}, + js::js_bigint::{add, equals, from_u64, mul, negative, JsBigintMutRef, Sign}, + mem::manager::{Dealloc, Manager}, range_map::{from_one, from_range, merge, merge_list, RangeMap, State}, }; -#[derive(Debug, PartialEq)] -pub enum JsonToken { +#[derive(Debug)] +pub enum JsonToken { String(String), Number(f64), ObjectBegin, @@ -23,7 +25,7 @@ pub enum JsonToken { Equals, Dot, ErrorToken(ErrorType), - BigInt(BigInt), + BigInt(JsBigintMutRef), Id(String), NewLine, Semicolon, @@ -31,6 +33,19 @@ pub enum JsonToken { ClosingParenthesis, } +impl PartialEq for JsonToken { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::String(l0), Self::String(r0)) => l0 == r0, + (Self::Number(l0), Self::Number(r0)) => l0 == r0, + (Self::ErrorToken(l0), Self::ErrorToken(r0)) => l0 == r0, + (Self::BigInt(l0), Self::BigInt(r0)) => equals(l0, r0), + (Self::Id(l0), Self::Id(r0)) => l0 == r0, + _ => core::mem::discriminant(self) == core::mem::discriminant(other), + } + } +} + #[derive(Debug, PartialEq)] pub enum ErrorType { UnexpectedCharacter, @@ -42,7 +57,7 @@ pub enum ErrorType { } #[derive(Default)] -pub enum TokenizerState { +pub enum TokenizerState { #[default] Initial, ParseId(String), @@ -51,13 +66,13 @@ pub enum TokenizerState { ParseUnicodeChar(ParseUnicodeCharState), ParseMinus, ParseZero(Sign), - ParseInt(IntegerState), - ParseFracBegin(IntegerState), - ParseFrac(FloatState), - ParseExpBegin(ExpState), - ParseExpSign(ExpState), - ParseExp(ExpState), - ParseBigInt(IntegerState), + ParseInt(IntState), + ParseFracBegin(IntState), + ParseFrac(FloatState), + ParseExpBegin(ExpState), + ParseExpSign(ExpState), + ParseExp(ExpState), + ParseBigInt(JsBigintMutRef), ParseNewLine, ParseCommentStart, ParseSinglelineComment, @@ -66,46 +81,66 @@ pub enum TokenizerState { ParseOperator(String), } -impl TokenizerState { - fn push(self, c: char, maps: &TransitionMaps) -> (Vec, TokenizerState) { +impl TokenizerState { + fn push + 'static>( + self, + manager: M, + c: char, + maps: &TransitionMaps, + ) -> (Vec>, TokenizerState) { match self { - TokenizerState::Initial => get_next_state((), c, &maps.initial, maps), - TokenizerState::ParseId(s) => get_next_state(s, c, &maps.id, maps), - TokenizerState::ParseString(s) => get_next_state(s, c, &maps.string, maps), - TokenizerState::ParseEscapeChar(s) => get_next_state(s, c, &maps.escape_char, maps), - TokenizerState::ParseUnicodeChar(s) => get_next_state(s, c, &maps.unicode_char, maps), - TokenizerState::ParseZero(s) => get_next_state(s, c, &maps.zero, maps), - TokenizerState::ParseInt(s) => get_next_state(s, c, &maps.int, maps), - TokenizerState::ParseMinus => get_next_state((), c, &maps.minus, maps), - TokenizerState::ParseFracBegin(s) => get_next_state(s, c, &maps.frac_begin, maps), - TokenizerState::ParseFrac(s) => get_next_state(s, c, &maps.frac, maps), - TokenizerState::ParseExpBegin(s) => get_next_state(s, c, &maps.exp_begin, maps), + TokenizerState::Initial => get_next_state(manager, (), c, &maps.initial, maps), + TokenizerState::ParseId(s) => get_next_state(manager, s, c, &maps.id, maps), + TokenizerState::ParseString(s) => get_next_state(manager, s, c, &maps.string, maps), + TokenizerState::ParseEscapeChar(s) => { + get_next_state(manager, s, c, &maps.escape_char, maps) + } + TokenizerState::ParseUnicodeChar(s) => { + get_next_state(manager, s, c, &maps.unicode_char, maps) + } + TokenizerState::ParseZero(s) => get_next_state(manager, s, c, &maps.zero, maps), + TokenizerState::ParseInt(s) => get_next_state(manager, s, c, &maps.int, maps), + TokenizerState::ParseMinus => get_next_state(manager, (), c, &maps.minus, maps), + TokenizerState::ParseFracBegin(s) => { + get_next_state(manager, s, c, &maps.frac_begin, maps) + } + TokenizerState::ParseFrac(s) => get_next_state(manager, s, c, &maps.frac, maps), + TokenizerState::ParseExpBegin(s) => { + get_next_state(manager, s, c, &maps.exp_begin, maps) + } TokenizerState::ParseExpSign(s) | TokenizerState::ParseExp(s) => { - get_next_state(s, c, &maps.exp, maps) + get_next_state(manager, s, c, &maps.exp, maps) + } + TokenizerState::ParseBigInt(s) => get_next_state(manager, s, c, &maps.big_int, maps), + TokenizerState::ParseNewLine => get_next_state(manager, (), c, &maps.new_line, maps), + TokenizerState::ParseCommentStart => { + get_next_state(manager, (), c, &maps.comment_start, maps) } - TokenizerState::ParseBigInt(s) => get_next_state(s, c, &maps.big_int, maps), - TokenizerState::ParseNewLine => get_next_state((), c, &maps.new_line, maps), - TokenizerState::ParseCommentStart => get_next_state((), c, &maps.comment_start, maps), TokenizerState::ParseSinglelineComment => { - get_next_state((), c, &maps.singleline_comment, maps) + get_next_state(manager, (), c, &maps.singleline_comment, maps) } TokenizerState::ParseMultilineComment => { - get_next_state((), c, &maps.multiline_comment, maps) + get_next_state(manager, (), c, &maps.multiline_comment, maps) } TokenizerState::ParseMultilineCommentAsterix => { - get_next_state((), c, &maps.multiline_comment_asterix, maps) + get_next_state(manager, (), c, &maps.multiline_comment_asterix, maps) } - TokenizerState::ParseOperator(s) => get_next_state(s, c, &maps.operator, maps), + TokenizerState::ParseOperator(s) => get_next_state(manager, s, c, &maps.operator, maps), } } - pub fn push_mut(&mut self, c: char, tm: &TransitionMaps) -> Vec { + pub fn push_mut + 'static>( + &mut self, + manager: M, + c: char, + tm: &TransitionMaps, + ) -> Vec> { let tokens; - (tokens, *self) = take(self).push(c, tm); + (tokens, *self) = take(self).push(manager, c, tm); tokens } - fn end(self) -> Vec { + fn end>(self, manager: M) -> Vec> { match self { TokenizerState::Initial | TokenizerState::ParseNewLine @@ -124,10 +159,10 @@ impl TokenizerState { [JsonToken::ErrorToken(ErrorType::CommentClosingExpected)].cast() } TokenizerState::ParseZero(_) => [JsonToken::Number(default())].cast(), - TokenizerState::ParseInt(s) => [s.into_token()].cast(), - TokenizerState::ParseFrac(s) => [s.into_token()].cast(), - TokenizerState::ParseExp(s) => [s.into_token()].cast(), - TokenizerState::ParseBigInt(s) => [s.into_big_int_token()].cast(), + TokenizerState::ParseInt(s) => [int_state_into_number_token(manager, s)].cast(), + TokenizerState::ParseFrac(s) => [float_state_into_token(manager, s)].cast(), + TokenizerState::ParseExp(s) => [exp_state_into_token(manager, s)].cast(), + TokenizerState::ParseBigInt(s) => [JsonToken::BigInt(s)].cast(), TokenizerState::ParseMinus | TokenizerState::ParseFracBegin(_) | TokenizerState::ParseExpBegin(_) @@ -146,13 +181,16 @@ pub struct ParseUnicodeCharState { } impl ParseUnicodeCharState { - fn push(mut self, i: u32) -> (Vec, TokenizerState) { + fn push( + mut self, + i: u32, + ) -> (Vec>, TokenizerState) { let new_unicode = self.unicode | (i << ((3 - self.index) * 4)); match self.index { 3 => { let c = char::from_u32(new_unicode); match c { - Some(c) => continue_string_state(self.s, c), + Some(c) => continue_string_state::(self.s, c), None => ( [JsonToken::ErrorToken(ErrorType::InvalidHex)].cast(), TokenizerState::Initial, @@ -169,142 +207,143 @@ impl ParseUnicodeCharState { } } -pub struct IntegerState { - s: Sign, - b: BigUint, -} - -pub fn bigfloat_to_f64(bf_10: BigFloat<10>) -> f64 { +pub fn bigfloat_to_f64(bf_10: BigFloat<10, M>) -> f64 { let bf_2 = bf_10.to_bin(54); bf_2.to_f64() } -impl BigUint { - fn add_digit(mut self, c: char) -> BigUint { - self = &(&self * &BigUint::from_u64(10)) + &BigUint::from_u64(digit_to_number(c)); - self - } +pub struct IntState { + b: JsBigintMutRef, + s: Sign, } -impl IntegerState { - fn from_difit(sign: Sign, c: char) -> IntegerState { - IntegerState { - s: sign, - b: BigUint::from_u64(digit_to_number(c)), - } +impl JsBigintMutRef { + fn from_digit>(m: M, c: char) -> JsBigintMutRef { + from_u64(m, Sign::Positive, digit_to_number(c)) } - fn add_digit(mut self, c: char) -> IntegerState { - self.b = self.b.add_digit(c); - self + fn add_digit>(self, m: M, c: char) -> JsBigintMutRef { + add( + m, + mul(m, self.deref(), from_u64(m, Sign::Positive, 10).deref()).deref(), + Self::from_digit(m, c).deref(), + ) } +} - fn into_float_state(self) -> FloatState { +impl IntState { + fn into_float_state(self) -> FloatState { FloatState { - s: self.s, b: self.b, + s: self.s, fe: 0, } } - fn into_exp_state(self) -> ExpState { + fn into_exp_state(self) -> ExpState { ExpState { - s: self.s, b: self.b, + s: self.s, fe: 0, es: Sign::Positive, e: 0, } } - fn into_token(self) -> JsonToken { - JsonToken::Number(bigfloat_to_f64(BigFloat { - significand: BigInt { - sign: self.s, - value: self.b, - }, - exp: 0, - non_zero_reminder: false, - })) + fn into_bigint_state>(self, m: M) -> JsBigintMutRef { + match self.s { + Sign::Positive => self.b, + Sign::Negative => negative(m, self.b.deref()), + } } +} - fn into_big_int_token(self) -> JsonToken { - JsonToken::BigInt(BigInt { - sign: self.s, - value: self.b, - }) - } +fn int_state_into_number_token( + manager: M, + state: IntState, +) -> JsonToken { + JsonToken::Number(bigfloat_to_f64(BigFloat { + manager, + significand: state.b, + sign: state.s, + exp: 0, + non_zero_reminder: false, + })) } -pub struct FloatState { +pub struct FloatState { + b: JsBigintMutRef, s: Sign, - b: BigUint, fe: i64, } -impl FloatState { - fn add_digit(mut self, c: char) -> FloatState { - self.b = self.b.add_digit(c); +impl FloatState { + fn add_digit>(mut self, m: M, c: char) -> FloatState { + self.b = self.b.add_digit(m, c); self.fe -= 1; self } - fn into_exp_state(self) -> ExpState { + fn into_exp_state(self) -> ExpState { ExpState { - s: self.s, b: self.b, + s: self.s, fe: self.fe, es: Sign::Positive, e: 0, } } +} - fn into_token(self) -> JsonToken { - JsonToken::Number(bigfloat_to_f64(BigFloat { - significand: BigInt { - sign: self.s, - value: self.b, - }, - exp: self.fe, - non_zero_reminder: false, - })) - } +fn float_state_into_token( + manager: M, + state: FloatState, +) -> JsonToken { + JsonToken::Number(bigfloat_to_f64(BigFloat { + manager, + significand: state.b, + sign: state.s, + exp: state.fe, + non_zero_reminder: false, + })) } -pub struct ExpState { +pub struct ExpState { + b: JsBigintMutRef, s: Sign, - b: BigUint, fe: i64, es: Sign, e: i64, } -impl ExpState { - const fn add_digit(mut self, c: char) -> ExpState { +impl ExpState { + const fn add_digit(mut self, c: char) -> ExpState { self.e = self.e * 10 + digit_to_number(c) as i64; self } +} - fn into_token(self) -> JsonToken { - let exp = self.fe - + match self.es { - Sign::Positive => self.e, - Sign::Negative => -self.e, - }; - JsonToken::Number(bigfloat_to_f64(BigFloat { - significand: BigInt { - sign: self.s, - value: self.b, - }, - exp, - non_zero_reminder: false, - })) - } +fn exp_state_into_token( + manager: M, + state: ExpState, +) -> JsonToken { + let exp = state.fe + + match state.es { + Sign::Positive => state.e, + Sign::Negative => -state.e, + }; + JsonToken::Number(bigfloat_to_f64(BigFloat { + manager, + significand: state.b, + sign: state.s, + exp, + non_zero_reminder: false, + })) } const CP_0: u32 = 0x30; -fn operator_to_token(s: String) -> Option { +fn operator_to_token(s: String) -> Option> { match s.as_str() { "{" => Some(JsonToken::ObjectBegin), "}" => Some(JsonToken::ObjectEnd), @@ -349,14 +388,17 @@ const fn digit_to_number(c: char) -> u64 { c as u64 - CP_0 as u64 } -fn start_number(s: Sign, c: char) -> IntegerState { - IntegerState::from_difit(s, c) +fn start_number(manager: M, s: Sign, c: char) -> IntState { + IntState { + b: JsBigintMutRef::from_digit(manager, c), + s, + } } -fn create_range_map( +fn create_range_map( list: Vec>, - t: Transition, -) -> RangeMap>> { + t: Transition, +) -> RangeMap>> { let mut result = RangeMap { list: default() }; for range in list { result = merge(from_range(range, t), result); @@ -376,37 +418,36 @@ fn set(arr: impl IntoIterator) -> Vec> { result } -type Transition = - fn(state: T, c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +type Transition = TransitionFunc; -struct TransitionMap { - def: Transition, - rm: RangeMap>>, +struct TransitionMap { + def: Transition, + rm: RangeMap>>, } -pub struct TransitionMaps { - initial: TransitionMap<()>, - id: TransitionMap, - string: TransitionMap, - escape_char: TransitionMap, - unicode_char: TransitionMap, - zero: TransitionMap, - int: TransitionMap, - minus: TransitionMap<()>, - frac_begin: TransitionMap, - frac: TransitionMap, - exp_begin: TransitionMap, - exp: TransitionMap, - big_int: TransitionMap, - new_line: TransitionMap<()>, - comment_start: TransitionMap<()>, - singleline_comment: TransitionMap<()>, - multiline_comment: TransitionMap<()>, - multiline_comment_asterix: TransitionMap<()>, - operator: TransitionMap, +pub struct TransitionMaps { + initial: TransitionMap<(), M>, + id: TransitionMap, + string: TransitionMap, + escape_char: TransitionMap, + unicode_char: TransitionMap, + zero: TransitionMap, + int: TransitionMap, M>, + minus: TransitionMap<(), M>, + frac_begin: TransitionMap, M>, + frac: TransitionMap, M>, + exp_begin: TransitionMap, M>, + exp: TransitionMap, M>, + big_int: TransitionMap, M>, + new_line: TransitionMap<(), M>, + comment_start: TransitionMap<(), M>, + singleline_comment: TransitionMap<(), M>, + multiline_comment: TransitionMap<(), M>, + multiline_comment_asterix: TransitionMap<(), M>, + operator: TransitionMap, } -pub fn create_transition_maps() -> TransitionMaps { +pub fn create_transition_maps() -> TransitionMaps { TransitionMaps { initial: create_initial_transitions(), id: create_id_transitions(), @@ -430,57 +471,55 @@ pub fn create_transition_maps() -> TransitionMaps { } } -fn get_next_state( +fn get_next_state( + manager: M, state: T, c: char, - tm: &TransitionMap, - maps: &TransitionMaps, -) -> (Vec, TokenizerState) -where - T: 'static, -{ + tm: &TransitionMap, + maps: &TransitionMaps, +) -> (Vec>, TokenizerState) { let entry = tm.rm.get(c); match &entry.value { - Some(f) => f(state, c, maps), - None => (tm.def)(state, c, maps), + Some(f) => f(manager, state, c, maps), + None => (tm.def)(manager, state, c, maps), } } -fn create_initial_transitions() -> TransitionMap<()> { - type Func = fn(s: (), c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_initial_transitions() -> TransitionMap<(), M> { + type Func = TransitionFunc; TransitionMap { - def: (|_, _, _| { + def: (|_, _, _, _| { ( [JsonToken::ErrorToken(ErrorType::UnexpectedCharacter)].cast(), TokenizerState::Initial, ) - }) as Func, + }) as Func, rm: merge_list( [ - create_range_map(operator_chars_with_dot(), |_, c, _| { + create_range_map(operator_chars_with_dot(), |_, _, c, _| { (default(), TokenizerState::ParseOperator(c.to_string())) }), - from_range('1'..='9', |_, c, _| { + from_range('1'..='9', |manager: M, _, c, _| { ( default(), - TokenizerState::ParseInt(start_number(Sign::Positive, c)), + TokenizerState::ParseInt(start_number(manager, Sign::Positive, c)), ) }), - from_one('"', |_, _, _| { + from_one('"', |_, _, _, _| { (default(), TokenizerState::ParseString(String::default())) }), - from_one('0', |_, _, _| { + from_one('0', |_, _, _, _| { (default(), TokenizerState::ParseZero(Sign::Positive)) }), - from_one('-', |_, _, _| (default(), TokenizerState::ParseMinus)), - create_range_map(id_start(), |_, c, _| { + from_one('-', |_, _, _, _| (default(), TokenizerState::ParseMinus)), + create_range_map(id_start(), |_, _, c, _| { (default(), TokenizerState::ParseId(c.to_string())) }), - from_one('\n', |_, _, _| (default(), TokenizerState::ParseNewLine)), - create_range_map(set([' ', '\t', '\r']), |_, _, _| { + from_one('\n', |_, _, _, _| (default(), TokenizerState::ParseNewLine)), + create_range_map(set([' ', '\t', '\r']), |_, _, _, _| { (default(), TokenizerState::Initial) }), - from_one('/', |_, _, _| { + from_one('/', |_, _, _, _| { (default(), TokenizerState::ParseCommentStart) }), ] @@ -489,56 +528,67 @@ fn create_initial_transitions() -> TransitionMap<()> { } } -fn create_id_transitions() -> TransitionMap { +fn create_id_transitions() -> TransitionMap { TransitionMap { - def: |s, c, maps| { - transfer_state([JsonToken::Id(s)].cast(), TokenizerState::Initial, c, maps) + def: |manager, s, c, maps| { + transfer_state( + manager, + [JsonToken::Id(s)].cast(), + TokenizerState::Initial, + c, + maps, + ) }, - rm: create_range_map(id_char(), |mut s, c, _| { + rm: create_range_map(id_char(), |_, mut s, c, _| { s.push(c); (default(), TokenizerState::ParseId(s)) }), } } -fn create_string_transactions() -> TransitionMap { +fn create_string_transactions() -> TransitionMap { TransitionMap { - def: |mut s, c, _| { + def: |_, mut s, c, _| { s.push(c); (default(), TokenizerState::ParseString(s)) }, rm: merge( - from_one('"', |s, _, _| { + from_one('"', |_, s, _, _| { ([JsonToken::String(s)].cast(), TokenizerState::Initial) }), - from_one('\\', |s, _, _| { + from_one('\\', |_, s, _, _| { (default(), TokenizerState::ParseEscapeChar(s)) }), ), } } -fn continue_string_state(mut s: String, c: char) -> (Vec, TokenizerState) { +fn continue_string_state( + mut s: String, + c: char, +) -> (Vec>, TokenizerState) { s.push(c); (default(), TokenizerState::ParseString(s)) } -fn transfer_state( - mut vec: Vec, - mut state: TokenizerState, +fn transfer_state( + manager: M, + mut vec: Vec>, + mut state: TokenizerState, c: char, - maps: &TransitionMaps, -) -> (Vec, TokenizerState) { + maps: &TransitionMaps, +) -> (Vec>, TokenizerState) { let next_tokens; - (next_tokens, state) = state.push(c, maps); + (next_tokens, state) = state.push(manager, c, maps); vec.extend(next_tokens); (vec, state) } -fn create_escape_char_transactions() -> TransitionMap { +fn create_escape_char_transactions() -> TransitionMap { TransitionMap { - def: |s, c, maps| { + def: |manager, s, c, maps| { transfer_state( + manager, [JsonToken::ErrorToken(ErrorType::UnexpectedCharacter)].cast(), TokenizerState::ParseString(s), c, @@ -547,15 +597,15 @@ fn create_escape_char_transactions() -> TransitionMap { }, rm: merge_list( [ - create_range_map(set(['\"', '\\', '/']), |s, c, _| { - continue_string_state(s, c) + create_range_map(set(['\"', '\\', '/']), |_, s, c, _| { + continue_string_state::(s, c) }), - from_one('b', |s, _, _| continue_string_state(s, '\u{8}')), - from_one('f', |s, _, _| continue_string_state(s, '\u{c}')), - from_one('n', |s, _, _| continue_string_state(s, '\n')), - from_one('r', |s, _, _| continue_string_state(s, '\r')), - from_one('t', |s, _, _| continue_string_state(s, '\t')), - from_one('u', |s, _, _| { + from_one('b', |_, s, _, _| continue_string_state::(s, '\u{8}')), + from_one('f', |_, s, _, _| continue_string_state::(s, '\u{c}')), + from_one('n', |_, s, _, _| continue_string_state::(s, '\n')), + from_one('r', |_, s, _, _| continue_string_state::(s, '\r')), + from_one('t', |_, s, _, _| continue_string_state::(s, '\t')), + from_one('u', |_, s, _, _| { ( default(), TokenizerState::ParseUnicodeChar(ParseUnicodeCharState { @@ -571,15 +621,13 @@ fn create_escape_char_transactions() -> TransitionMap { } } -fn create_unicode_char_transactions() -> TransitionMap { - type Func = fn( - state: ParseUnicodeCharState, - c: char, - maps: &TransitionMaps, - ) -> (Vec, TokenizerState); +fn create_unicode_char_transactions( +) -> TransitionMap { + type Func = TransitionFunc; TransitionMap { - def: |state, c, maps| { + def: |manager, state, c, maps| { transfer_state( + manager, [JsonToken::ErrorToken(ErrorType::InvalidHex)].cast(), TokenizerState::ParseString(state.s), c, @@ -590,15 +638,15 @@ fn create_unicode_char_transactions() -> TransitionMap { [ from_range( '0'..='9', - (|state, c, _| state.push(c as u32 - '0' as u32)) as Func, + (|_, state, c, _| state.push::(c as u32 - '0' as u32)) as Func, ), from_range( 'a'..='f', - (|state, c, _| state.push(c as u32 - ('a' as u32 - 10))) as Func, + (|_, state, c, _| state.push::(c as u32 - ('a' as u32 - 10))) as Func, ), from_range( 'A'..='F', - (|state, c, _| state.push(c as u32 - ('A' as u32 - 10))) as Func, + (|_, state, c, _| state.push::(c as u32 - ('A' as u32 - 10))) as Func, ), ] .cast(), @@ -606,47 +654,48 @@ fn create_unicode_char_transactions() -> TransitionMap { } } -fn create_zero_transactions() -> TransitionMap { - type Func = fn(s: Sign, c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_zero_transactions() -> TransitionMap { + type Func = TransitionFunc; TransitionMap { - def: (|_, c, maps| tokenize_invalid_number(c, maps)) as Func, + def: (|manager, _, c, maps| tokenize_invalid_number(manager, c, maps)) as Func, rm: merge_list( [ from_one( '.', - (|s, _, _| { + (|manager, s, _, _| { ( default(), - TokenizerState::ParseFracBegin(IntegerState { + TokenizerState::ParseFracBegin(IntState { + b: from_u64(manager, Sign::Positive, 0), s, - b: BigUint::ZERO, }), ) - }) as Func, + }) as Func, ), - create_range_map(set(['e', 'E']), |s, _, _| { + create_range_map(set(['e', 'E']), |manager, s, _, _| { ( default(), TokenizerState::ParseExpBegin(ExpState { + b: from_u64(manager, s, 0), s, - b: BigUint::ZERO, fe: 0, es: Sign::Positive, e: 0, }), ) }), - from_one('n', |s, _, _| { - ( - default(), - TokenizerState::ParseBigInt(IntegerState { - s, - b: BigUint::ZERO, - }), - ) - }), - create_range_map(terminal_for_number(), |_, c, maps| { + from_one( + 'n', + (|manager, s, _, _| { + ( + default(), + TokenizerState::ParseBigInt(from_u64(manager, s, 0)), + ) + }) as Func, + ), + create_range_map(terminal_for_number(), |manager, _, c, maps| { transfer_state( + manager, [JsonToken::Number(default())].cast(), TokenizerState::Initial, c, @@ -659,26 +708,44 @@ fn create_zero_transactions() -> TransitionMap { } } -fn create_int_transactions() -> TransitionMap { - type Func = - fn(s: IntegerState, c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_int_transactions() -> TransitionMap, M> { + type Func = TransitionFunc::Dealloc>>; TransitionMap { - def: (|_, c, maps| tokenize_invalid_number(c, maps)) as Func, + def: (|manager, _, c, maps| tokenize_invalid_number(manager, c, maps)) as Func, rm: merge_list( [ from_range( '0'..='9', - (|s, c, _| (default(), TokenizerState::ParseInt(s.add_digit(c)))) as Func, + (|manager, s, c, _| { + ( + default(), + TokenizerState::ParseInt(IntState { + b: s.b.add_digit(manager, c), + s: s.s, + }), + ) + }) as Func, ), - from_one('.', |s, _, _| { + from_one('.', |_, s, _, _| { (default(), TokenizerState::ParseFracBegin(s)) }), - create_range_map(set(['e', 'E']), |s, _, _| { + create_range_map(set(['e', 'E']), |_, s, _, _| { (default(), TokenizerState::ParseExpBegin(s.into_exp_state())) }), - from_one('n', |s, _, _| (default(), TokenizerState::ParseBigInt(s))), - create_range_map(terminal_for_number(), |s, c, maps| { - transfer_state([s.into_token()].cast(), TokenizerState::Initial, c, maps) + from_one('n', |m, s, _, _| { + ( + default(), + TokenizerState::ParseBigInt(s.into_bigint_state(m)), + ) + }), + create_range_map(terminal_for_number(), |manager, s, c, maps| { + transfer_state( + manager, + [int_state_into_number_token(manager, s)].cast(), + TokenizerState::Initial, + c, + maps, + ) }), ] .cast(), @@ -686,39 +753,49 @@ fn create_int_transactions() -> TransitionMap { } } -fn create_frac_begin_transactions() -> TransitionMap { - type Func = - fn(s: IntegerState, c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_frac_begin_transactions() -> TransitionMap, M> +{ + type Func = TransitionFunc::Dealloc>>; TransitionMap { - def: (|_, c, maps| tokenize_invalid_number(c, maps)) as Func, + def: (|manager, _, c, maps| tokenize_invalid_number(manager, c, maps)) as Func, rm: from_range( '0'..='9', - (|s, c, _| { + (|manager, s, c, _| { ( default(), - TokenizerState::ParseFrac(s.into_float_state().add_digit(c)), + TokenizerState::ParseFrac(s.into_float_state().add_digit(manager, c)), ) - }) as Func, + }) as Func, ), } } -fn create_frac_transactions() -> TransitionMap { - type Func = - fn(s: FloatState, c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_frac_transactions() -> TransitionMap, M> { + type Func = TransitionFunc::Dealloc>>; TransitionMap { - def: (|_, c, maps| tokenize_invalid_number(c, maps)) as Func, + def: (|manager, _, c, maps| tokenize_invalid_number(manager, c, maps)) as Func, rm: merge_list( [ from_range( '0'..='9', - (|s, c, _| (default(), TokenizerState::ParseFrac(s.add_digit(c)))) as Func, + (|manager, s, c, _| { + ( + default(), + TokenizerState::ParseFrac(s.add_digit(manager, c)), + ) + }) as Func, ), - create_range_map(set(['e', 'E']), |s, _, _| { + create_range_map(set(['e', 'E']), |_, s, _, _| { (default(), TokenizerState::ParseExpBegin(s.into_exp_state())) }), - create_range_map(terminal_for_number(), |s, c, maps| { - transfer_state([s.into_token()].cast(), TokenizerState::Initial, c, maps) + create_range_map(terminal_for_number(), |manager, s, c, maps| { + transfer_state( + manager, + [float_state_into_token(manager, s)].cast(), + TokenizerState::Initial, + c, + maps, + ) }), ] .cast(), @@ -726,44 +803,52 @@ fn create_frac_transactions() -> TransitionMap { } } -fn create_minus_transactions() -> TransitionMap<()> { - type Func = fn(s: (), c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_minus_transactions() -> TransitionMap<(), M> { + type Func = TransitionFunc; TransitionMap { - def: (|_, c, maps| tokenize_invalid_number(c, maps)) as Func, + def: (|manager, _, c, maps| tokenize_invalid_number(manager, c, maps)) as Func, rm: merge( from_one( '0', - (|_, _, _| (default(), TokenizerState::ParseZero(Sign::Negative))) as Func, + (|_, _, _, _| (default(), TokenizerState::ParseZero(Sign::Negative))) as Func, ), - from_range('1'..='9', |_, c, _| { + from_range('1'..='9', |manager, _, c, _| { ( default(), - TokenizerState::ParseInt(start_number(Sign::Negative, c)), + TokenizerState::ParseInt(start_number(manager, Sign::Negative, c)), ) }), ), } } -fn create_exp_begin_transactions() -> TransitionMap { - type Func = fn(s: ExpState, c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_exp_begin_transactions() -> TransitionMap, M> { + type Func = TransitionFunc::Dealloc>>; TransitionMap { - def: (|_, c, maps| tokenize_invalid_number(c, maps)) as Func, + def: (|manager, _, c, maps| tokenize_invalid_number(manager, c, maps)) as Func, rm: merge_list( [ from_range( '0'..='9', - (|s, c, _| (default(), TokenizerState::ParseExp(s.add_digit(c)))) as Func, + (|_, s, c, _| (default(), TokenizerState::ParseExp(s.add_digit(c)))) as Func, ), - from_one('+', |s, _, _| (default(), TokenizerState::ParseExpSign(s))), - from_one('-', |mut s, _, _| { + from_one('+', |_, s, _, _| { + (default(), TokenizerState::ParseExpSign(s)) + }), + from_one('-', |_, mut s, _, _| { (default(), { s.es = Sign::Negative; TokenizerState::ParseExpSign(s) }) }), - create_range_map(terminal_for_number(), |s, c, maps| { - transfer_state([s.into_token()].cast(), TokenizerState::Initial, c, maps) + create_range_map(terminal_for_number(), |manager, s, c, maps| { + transfer_state( + manager, + [exp_state_into_token(manager, s)].cast(), + TokenizerState::Initial, + c, + maps, + ) }), ] .cast(), @@ -771,35 +856,52 @@ fn create_exp_begin_transactions() -> TransitionMap { } } -fn create_exp_transactions() -> TransitionMap { - type Func = fn(s: ExpState, c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_exp_transactions() -> TransitionMap, M> { + type Func = TransitionFunc::Dealloc>>; TransitionMap { - def: (|_, c, maps| tokenize_invalid_number(c, maps)) as Func, + def: (|manager, _, c, maps| tokenize_invalid_number(manager, c, maps)) as Func, rm: merge( from_range( '0'..='9', - (|s, c, _| (default(), TokenizerState::ParseExp(s.add_digit(c)))) as Func, + (|_, s, c, _| (default(), TokenizerState::ParseExp(s.add_digit(c)))) as Func, ), - create_range_map(terminal_for_number(), |s, c, maps| { - transfer_state([s.into_token()].cast(), TokenizerState::Initial, c, maps) + create_range_map(terminal_for_number(), |manager, s, c, maps| { + transfer_state( + manager, + [exp_state_into_token(manager, s)].cast(), + TokenizerState::Initial, + c, + maps, + ) }), ), } } -fn create_big_int_transactions() -> TransitionMap { - type Func = - fn(s: IntegerState, c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_big_int_transactions( +) -> TransitionMap, M> { + type Func = TransitionFunc::Dealloc>>; TransitionMap { - def: (|_, c, maps| tokenize_invalid_number(c, maps)) as Func, - rm: create_range_map(terminal_for_number(), |s, c, maps| { - transfer_state([s.into_token()].cast(), TokenizerState::Initial, c, maps) + def: (|manager, _, c, maps| tokenize_invalid_number(manager, c, maps)) as Func, + rm: create_range_map(terminal_for_number(), |manager, s, c, maps| { + transfer_state( + manager, + [JsonToken::BigInt(s)].cast(), + TokenizerState::Initial, + c, + maps, + ) }), } } -fn tokenize_invalid_number(c: char, maps: &TransitionMaps) -> (Vec, TokenizerState) { +fn tokenize_invalid_number( + manager: M, + c: char, + maps: &TransitionMaps, +) -> (Vec>, TokenizerState) { transfer_state( + manager, [JsonToken::ErrorToken(ErrorType::InvalidNumber)].cast(), TokenizerState::Initial, c, @@ -807,86 +909,113 @@ fn tokenize_invalid_number(c: char, maps: &TransitionMaps) -> (Vec, T ) } -fn create_new_line_transactions() -> TransitionMap<()> { - type Func = fn(s: (), c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_new_line_transactions() -> TransitionMap<(), M> { + type Func = TransitionFunc; TransitionMap { - def: (|_, c, maps| { + def: (|manager, _, c, maps| { transfer_state( + manager, [JsonToken::NewLine].cast(), TokenizerState::Initial, c, maps, ) - }) as Func, - rm: create_range_map(set(WHITE_SPACE_CHARS), |_, _, _| { + }) as Func, + rm: create_range_map(set(WHITE_SPACE_CHARS), |_, _, _, _| { (default(), TokenizerState::ParseNewLine) }), } } -fn create_comment_start_transactions() -> TransitionMap<()> { - type Func = fn(s: (), c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_comment_start_transactions() -> TransitionMap<(), M> { + type Func = TransitionFunc; TransitionMap { - def: (|_, _, _| { + def: (|_, _, _, _| { ( [JsonToken::ErrorToken(ErrorType::UnexpectedCharacter)].cast(), TokenizerState::Initial, ) - }) as Func, + }) as Func, rm: merge( - from_one('/', |_, _, _| { + from_one('/', |_, _, _, _| { (default(), TokenizerState::ParseSinglelineComment) }), - from_one('*', |_, _, _| { + from_one('*', |_, _, _, _| { (default(), TokenizerState::ParseMultilineComment) }), ), } } -fn create_singleline_comment_transactions() -> TransitionMap<()> { - type Func = fn(s: (), c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +type TransitionFunc = fn( + m: M, + s: S, + c: char, + maps: &TransitionMaps, +) -> ( + Vec::Dealloc>>, + TokenizerState<::Dealloc>, +); + +fn create_singleline_comment_transactions() -> TransitionMap<(), M> { + type Func = TransitionFunc; TransitionMap { - def: (|_, _, _| (default(), TokenizerState::ParseSinglelineComment)) as Func, - rm: create_range_map(set(WHITE_SPACE_CHARS), |_, _, _| { + def: (|_, _, _, _| (default(), TokenizerState::ParseSinglelineComment)) as Func, + rm: create_range_map(set(WHITE_SPACE_CHARS), |_, _, _, _| { (default(), TokenizerState::ParseNewLine) }), } } -fn create_multiline_comment_transactions() -> TransitionMap<()> { - type Func = fn(s: (), c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_multiline_comment_transactions() -> TransitionMap<(), M> { + type Func = fn( + m: M, + s: (), + c: char, + maps: &TransitionMaps, + ) -> ( + Vec::Dealloc>>, + TokenizerState<::Dealloc>, + ); TransitionMap { - def: (|_, _, _| (default(), TokenizerState::ParseMultilineComment)) as Func, - rm: from_one('*', |_, _, _| { + def: (|_, _, _, _| (default(), TokenizerState::ParseMultilineComment)) as Func, + rm: from_one('*', |_, _, _, _| { (default(), TokenizerState::ParseMultilineCommentAsterix) }), } } -fn create_multiline_comment_asterix_transactions() -> TransitionMap<()> { - type Func = fn(s: (), c: char, maps: &TransitionMaps) -> (Vec, TokenizerState); +fn create_multiline_comment_asterix_transactions() -> TransitionMap<(), M> { + type Func = fn( + m: M, + s: (), + c: char, + maps: &TransitionMaps, + ) -> ( + Vec::Dealloc>>, + TokenizerState<::Dealloc>, + ); TransitionMap { - def: (|_, _, _| (default(), TokenizerState::ParseMultilineComment)) as Func, + def: (|_, _, _, _| (default(), TokenizerState::ParseMultilineComment)) as Func, rm: merge( - from_one('/', |_, _, _| (default(), TokenizerState::Initial)), - from_one('*', |_, _, _| { + from_one('/', |_, _, _, _| (default(), TokenizerState::Initial)), + from_one('*', |_, _, _, _| { (default(), TokenizerState::ParseMultilineCommentAsterix) }), ), } } -fn create_operator_transactions() -> TransitionMap { +fn create_operator_transactions() -> TransitionMap { TransitionMap { - def: |s, c, maps| { + def: |manager, s, c, maps| { let token = operator_to_token(s).unwrap(); - transfer_state([token].cast(), TokenizerState::Initial, c, maps) + transfer_state(manager, [token].cast(), TokenizerState::Initial, c, maps) }, - rm: create_range_map(operator_chars_with_dot(), |s, c, maps| { + rm: create_range_map(operator_chars_with_dot(), |manager, s, c, maps| { let mut next_string = s.clone(); next_string.push(c); - match operator_to_token(next_string) { + match operator_to_token::(next_string) { Some(_) => { let mut next_string = s.clone(); next_string.push(c); @@ -894,28 +1023,30 @@ fn create_operator_transactions() -> TransitionMap { } _ => { let token = operator_to_token(s).unwrap(); - transfer_state([token].cast(), TokenizerState::Initial, c, maps) + transfer_state(manager, [token].cast(), TokenizerState::Initial, c, maps) } } }), } } -pub fn tokenize(input: String) -> Vec { - TokenizerStateIterator::new(input.chars()).collect() +pub fn tokenize(manager: M, input: String) -> Vec> { + TokenizerStateIterator::new(manager, input.chars()).collect() } -pub struct TokenizerStateIterator> { +pub struct TokenizerStateIterator, M: Manager> { + manager: M, chars: T, - cache: VecDeque, - state: TokenizerState, - maps: TransitionMaps, + cache: VecDeque>, + state: TokenizerState, + maps: TransitionMaps, end: bool, } -impl> TokenizerStateIterator { - pub fn new(chars: T) -> Self { +impl, M: Manager + 'static> TokenizerStateIterator { + pub fn new(manager: M, chars: T) -> Self { Self { + manager, chars, cache: default(), state: default(), @@ -925,8 +1056,8 @@ impl> TokenizerStateIterator { } } -impl> Iterator for TokenizerStateIterator { - type Item = JsonToken; +impl, M: Manager + 'static> Iterator for TokenizerStateIterator { + type Item = JsonToken; fn next(&mut self) -> Option { loop { @@ -937,10 +1068,12 @@ impl> Iterator for TokenizerStateIterator { return None; } match self.chars.next() { - Some(c) => self.cache.extend(self.state.push_mut(c, &self.maps)), + Some(c) => self + .cache + .extend(self.state.push_mut(self.manager, c, &self.maps)), None => { self.end = true; - self.cache.extend(take(&mut self.state).end()) + self.cache.extend(take(&mut self.state).end(self.manager)) } } } @@ -952,12 +1085,9 @@ mod test { use wasm_bindgen_test::wasm_bindgen_test; use crate::{ - big_numbers::{ - big_float::BigFloat, - big_int::{BigInt, Sign}, - big_uint::BigUint, - }, - common::cast::Cast, + big_numbers::big_float::BigFloat, + js::js_bigint::{from_u64, new_bigint, zero, Sign}, + mem::global::{Global, GLOBAL}, tokenizer::bigfloat_to_f64, }; @@ -966,47 +1096,47 @@ mod test { #[test] #[wasm_bindgen_test] fn test_empty() { - let result = tokenize(String::from("")); + let result = tokenize(GLOBAL, String::from("")); assert_eq!(result.len(), 0); } #[test] #[wasm_bindgen_test] fn test_ops() { - let result = tokenize(String::from("{")); - assert_eq!(&result, &[JsonToken::ObjectBegin]); + let result = tokenize(GLOBAL, String::from("{")); + assert_eq!(result[0], JsonToken::::ObjectBegin); - let result = tokenize(String::from("}")); + let result = tokenize(GLOBAL, String::from("}")); assert_eq!(&result, &[JsonToken::ObjectEnd]); - let result = tokenize(String::from("[")); + let result = tokenize(GLOBAL, String::from("[")); assert_eq!(&result, &[JsonToken::ArrayBegin]); - let result = tokenize(String::from("]")); + let result = tokenize(GLOBAL, String::from("]")); assert_eq!(&result, &[JsonToken::ArrayEnd]); - let result = tokenize(String::from(":")); + let result = tokenize(GLOBAL, String::from(":")); assert_eq!(&result, &[JsonToken::Colon]); - let result = tokenize(String::from(",")); + let result = tokenize(GLOBAL, String::from(",")); assert_eq!(&result, &[JsonToken::Comma]); - let result = tokenize(String::from("=")); + let result = tokenize(GLOBAL, String::from("=")); assert_eq!(&result, &[JsonToken::Equals]); - let result = tokenize(String::from(".")); + let result = tokenize(GLOBAL, String::from(".")); assert_eq!(&result, &[JsonToken::Dot]); - let result = tokenize(String::from(";")); + let result = tokenize(GLOBAL, String::from(";")); assert_eq!(&result, &[JsonToken::Semicolon]); - let result = tokenize(String::from("()")); + let result = tokenize(GLOBAL, String::from("()")); assert_eq!( &result, &[JsonToken::OpeningParenthesis, JsonToken::ClosingParenthesis] ); - let result = tokenize(String::from("[{ :, }]")); + let result = tokenize(GLOBAL, String::from("[{ :, }]")); assert_eq!( &result, &[ @@ -1023,16 +1153,16 @@ mod test { #[test] #[wasm_bindgen_test] fn test_id() { - let result = tokenize(String::from("true")); + let result = tokenize(GLOBAL, String::from("true")); assert_eq!(&result, &[JsonToken::Id(String::from("true"))]); - let result = tokenize(String::from("false")); + let result = tokenize(GLOBAL, String::from("false")); assert_eq!(&result, &[JsonToken::Id(String::from("false"))]); - let result = tokenize(String::from("null")); + let result = tokenize(GLOBAL, String::from("null")); assert_eq!(&result, &[JsonToken::Id(String::from("null"))]); - let result = tokenize(String::from("tru tru")); + let result = tokenize(GLOBAL, String::from("tru tru")); assert_eq!( &result, &[ @@ -1041,36 +1171,36 @@ mod test { ] ); - let result = tokenize(String::from("ABCxyz_0123456789$")); + let result = tokenize(GLOBAL, String::from("ABCxyz_0123456789$")); assert_eq!( &result, &[JsonToken::Id(String::from("ABCxyz_0123456789$")),] ); - let result = tokenize(String::from("_")); + let result = tokenize(GLOBAL, String::from("_")); assert_eq!(&result, &[JsonToken::Id(String::from("_")),]); - let result = tokenize(String::from("$")); + let result = tokenize(GLOBAL, String::from("$")); assert_eq!(&result, &[JsonToken::Id(String::from("$")),]); } #[test] #[wasm_bindgen_test] fn test_whitespace() { - let result = tokenize(String::from(" \t\n\r")); + let result = tokenize(GLOBAL, String::from(" \t\n\r")); assert_eq!(&result, &[]); } #[test] #[wasm_bindgen_test] fn test_string() { - let result = tokenize(String::from("\"\"")); + let result = tokenize(GLOBAL, String::from("\"\"")); assert_eq!(&result, &[JsonToken::String("".to_string())]); - let result = tokenize(String::from("\"value\"")); + let result = tokenize(GLOBAL, String::from("\"value\"")); assert_eq!(&result, &[JsonToken::String("value".to_string())]); - let result = tokenize(String::from("\"value1\" \"value2\"")); + let result = tokenize(GLOBAL, String::from("\"value1\" \"value2\"")); assert_eq!( &result, &[ @@ -1079,20 +1209,20 @@ mod test { ] ); - let result = tokenize(String::from("\"value")); + let result = tokenize(GLOBAL, String::from("\"value")); assert_eq!(&result, &[JsonToken::ErrorToken(ErrorType::MissingQuotes)]); } #[test] #[wasm_bindgen_test] fn test_escaped_characters() { - let result = tokenize(String::from("\"\\b\\f\\n\\r\\t\"")); + let result = tokenize(GLOBAL, String::from("\"\\b\\f\\n\\r\\t\"")); assert_eq!( &result, &[JsonToken::String("\u{8}\u{c}\n\r\t".to_string())] ); - let result = tokenize(String::from("\"\\x\"")); + let result = tokenize(GLOBAL, String::from("\"\\x\"")); assert_eq!( &result, &[ @@ -1101,20 +1231,20 @@ mod test { ] ); - let result = tokenize(String::from("\"\\")); + let result = tokenize(GLOBAL, String::from("\"\\")); assert_eq!(&result, &[JsonToken::ErrorToken(ErrorType::MissingQuotes)]); } #[test] #[wasm_bindgen_test] fn test_unicode() { - let result = tokenize(String::from("\"\\u1234\"")); + let result = tokenize(GLOBAL, String::from("\"\\u1234\"")); assert_eq!(&result, &[JsonToken::String("ሴ".to_string())]); - let result = tokenize(String::from("\"\\uaBcDEeFf\"")); + let result = tokenize(GLOBAL, String::from("\"\\uaBcDEeFf\"")); assert_eq!(&result, &[JsonToken::String("ꯍEeFf".to_string())]); - let result = tokenize(String::from("\"\\uEeFg\"")); + let result = tokenize(GLOBAL, String::from("\"\\uEeFg\"")); assert_eq!( &result, &[ @@ -1123,20 +1253,20 @@ mod test { ] ); - let result = tokenize(String::from("\"\\uEeF")); + let result = tokenize(GLOBAL, String::from("\"\\uEeF")); assert_eq!(&result, &[JsonToken::ErrorToken(ErrorType::MissingQuotes)]); } #[test] #[wasm_bindgen_test] fn test_integer() { - let result = tokenize(String::from("0")); + let result = tokenize(GLOBAL, String::from("0")); assert_eq!(&result, &[JsonToken::Number(0.0)]); - let result = tokenize(String::from("-0")); + let result = tokenize(GLOBAL, String::from("-0")); assert_eq!(&result, &[JsonToken::Number(0.0)]); - let result = tokenize(String::from("0abc")); + let result = tokenize(GLOBAL, String::from("0abc")); assert_eq!( &result, &[ @@ -1145,7 +1275,7 @@ mod test { ] ); - let result = tokenize(String::from("0. 2")); + let result = tokenize(GLOBAL, String::from("0. 2")); assert_eq!( &result, &[ @@ -1154,13 +1284,13 @@ mod test { ] ); - let result = tokenize(String::from("1234567890")); + let result = tokenize(GLOBAL, String::from("1234567890")); assert_eq!(&result, &[JsonToken::Number(1234567890.0)]); - let result = tokenize(String::from("-1234567890")); + let result = tokenize(GLOBAL, String::from("-1234567890")); assert_eq!(&result, &[JsonToken::Number(-1234567890.0)]); - let result = tokenize(String::from("[0,1]")); + let result = tokenize(GLOBAL, String::from("[0,1]")); assert_eq!( &result, &[ @@ -1172,7 +1302,7 @@ mod test { ] ); - let result = tokenize(String::from("001")); + let result = tokenize(GLOBAL, String::from("001")); assert_eq!( &result, &[ @@ -1182,10 +1312,10 @@ mod test { ] ); - let result = tokenize(String::from("-")); + let result = tokenize(GLOBAL, String::from("-")); assert_eq!(&result, &[JsonToken::ErrorToken(ErrorType::InvalidNumber)]); - let result = tokenize(String::from("-{}")); + let result = tokenize(GLOBAL, String::from("-{}")); assert_eq!( &result, &[ @@ -1195,29 +1325,29 @@ mod test { ] ); - let result = tokenize(String::from("9007199254740991")); + let result = tokenize(GLOBAL, String::from("9007199254740991")); assert_eq!(&result, &[JsonToken::Number(9007199254740991.0)]); - let result = tokenize(String::from("9007199254740992")); + let result = tokenize(GLOBAL, String::from("9007199254740992")); assert_eq!(&result, &[JsonToken::Number(9007199254740992.0)]); - let result = tokenize(String::from("9007199254740993")); + let result = tokenize(GLOBAL, String::from("9007199254740993")); assert_eq!(&result, &[JsonToken::Number(9007199254740993.0)]); } #[test] #[wasm_bindgen_test] fn test_big_float() { - let result = tokenize(String::from("340282366920938463463374607431768211456")); + let result = tokenize( + GLOBAL, + String::from("340282366920938463463374607431768211456"), + ); assert_eq!( &result, &[JsonToken::Number(bigfloat_to_f64(BigFloat { - significand: BigInt { - sign: Sign::Positive, - value: BigUint { - value: [0, 0, 1].cast() - } - }, + manager: GLOBAL, + significand: new_bigint(GLOBAL, Sign::Positive, [0, 0, 1]), + sign: Sign::Positive, exp: 0, non_zero_reminder: false }))] @@ -1227,10 +1357,10 @@ mod test { #[test] #[wasm_bindgen_test] fn test_float() { - let result = tokenize(String::from("0.01")); + let result = tokenize(GLOBAL, String::from("0.01")); assert_eq!(&result, &[JsonToken::Number(0.01)]); - let result = tokenize(String::from("[-12.34]")); + let result = tokenize(GLOBAL, String::from("[-12.34]")); assert_eq!( &result, &[ @@ -1244,66 +1374,77 @@ mod test { #[test] #[wasm_bindgen_test] fn test_infinity() { - let result = tokenize(String::from("1e1000")); + let result = tokenize(GLOBAL, String::from("1e1000")); assert_eq!(&result, &[JsonToken::Number(f64::INFINITY)]); - let result = tokenize(String::from("-1e+1000")); + let result = tokenize(GLOBAL, String::from("-1e+1000")); assert_eq!(&result, &[JsonToken::Number(f64::NEG_INFINITY)]); } #[test] #[wasm_bindgen_test] fn test_exp() { - let result = tokenize(String::from("1e2")); + let result = tokenize(GLOBAL, String::from("1e2")); assert_eq!(&result, &[JsonToken::Number(1e2)]); - let result = tokenize(String::from("1E+2")); + let result = tokenize(GLOBAL, String::from("1E+2")); assert_eq!(&result, &[JsonToken::Number(1e2)]); - let result = tokenize(String::from("0e-2")); + let result = tokenize(GLOBAL, String::from("0e-2")); assert_eq!(&result, &[JsonToken::Number(0.0)]); - let result = tokenize(String::from("1e-2")); + let result = tokenize(GLOBAL, String::from("1e-2")); assert_eq!(&result, &[JsonToken::Number(1e-2)]); - let result = tokenize(String::from("1.2e+2")); + let result = tokenize(GLOBAL, String::from("1.2e+2")); assert_eq!(&result, &[JsonToken::Number(1.2e+2)]); - let result = tokenize(String::from("12e0000")); + let result = tokenize(GLOBAL, String::from("12e0000")); assert_eq!(&result, &[JsonToken::Number(12.0)]); - let result = tokenize(String::from("1e")); + let result = tokenize(GLOBAL, String::from("1e")); assert_eq!(&result, &[JsonToken::ErrorToken(ErrorType::InvalidNumber)]); - let result = tokenize(String::from("1e+")); + let result = tokenize(GLOBAL, String::from("1e+")); assert_eq!(&result, &[JsonToken::ErrorToken(ErrorType::InvalidNumber)]); - let result = tokenize(String::from("1e-")); + let result = tokenize(GLOBAL, String::from("1e-")); assert_eq!(&result, &[JsonToken::ErrorToken(ErrorType::InvalidNumber)]); } #[test] #[wasm_bindgen_test] fn test_big_int() { - let result = tokenize(String::from("0n")); - assert_eq!(&result, &[JsonToken::BigInt(BigInt::ZERO)]); + let result = tokenize(GLOBAL, String::from("0n")); + assert_eq!(&result, &[JsonToken::BigInt(zero(GLOBAL))]); - let result = tokenize(String::from("-0n")); + let result = tokenize(GLOBAL, String::from("-0n")); assert_eq!( &result, - &[JsonToken::BigInt(BigInt { - sign: Sign::Negative, - value: BigUint::ZERO - })] + &[JsonToken::BigInt(from_u64(GLOBAL, Sign::Negative, 0))] ); - let result = tokenize(String::from("1234567890n")); - assert_eq!(&result, &[JsonToken::BigInt(BigInt::from_u64(1234567890))]); + let result = tokenize(GLOBAL, String::from("1234567890n")); + assert_eq!( + &result, + &[JsonToken::BigInt(from_u64( + GLOBAL, + Sign::Positive, + 1234567890 + ))] + ); - let result = tokenize(String::from("-1234567890n")); - assert_eq!(&result, &[JsonToken::BigInt(BigInt::from_i64(-1234567890))]); + let result = tokenize(GLOBAL, String::from("-1234567890n")); + assert_eq!( + &result, + &[JsonToken::BigInt(from_u64( + GLOBAL, + Sign::Negative, + 1234567890 + ))] + ); - let result = tokenize(String::from("123.456n")); + let result = tokenize(GLOBAL, String::from("123.456n")); assert_eq!( &result, &[ @@ -1312,7 +1453,7 @@ mod test { ] ); - let result = tokenize(String::from("123e456n")); + let result = tokenize(GLOBAL, String::from("123e456n")); assert_eq!( &result, &[ @@ -1321,7 +1462,7 @@ mod test { ] ); - let result = tokenize(String::from("1234567890na")); + let result = tokenize(GLOBAL, String::from("1234567890na")); assert_eq!( &result, &[ @@ -1330,7 +1471,7 @@ mod test { ] ); - let result = tokenize(String::from("1234567890nn")); + let result = tokenize(GLOBAL, String::from("1234567890nn")); assert_eq!( &result, &[ @@ -1343,7 +1484,7 @@ mod test { #[test] #[wasm_bindgen_test] fn test_errors() { - let result = tokenize(String::from("ᄑ")); + let result = tokenize(GLOBAL, String::from("ᄑ")); assert_eq!( &result, &[JsonToken::ErrorToken(ErrorType::UnexpectedCharacter)] @@ -1353,7 +1494,7 @@ mod test { #[test] #[wasm_bindgen_test] fn test_djs() { - let result = tokenize(String::from("module.exports = ")); + let result = tokenize(GLOBAL, String::from("module.exports = ")); assert_eq!( &result, &[ @@ -1368,7 +1509,7 @@ mod test { #[test] #[wasm_bindgen_test] fn test_singleline_comments() { - let result = tokenize(String::from("{//abc\n2\n}")); + let result = tokenize(GLOBAL, String::from("{//abc\n2\n}")); assert_eq!( &result, &[ @@ -1380,13 +1521,13 @@ mod test { ] ); - let result = tokenize(String::from("0//abc/*")); + let result = tokenize(GLOBAL, String::from("0//abc/*")); assert_eq!(&result, &[JsonToken::Number(0.0),]); - let result = tokenize(String::from("0//")); + let result = tokenize(GLOBAL, String::from("0//")); assert_eq!(&result, &[JsonToken::Number(0.0),]); - let result = tokenize(String::from("0/")); + let result = tokenize(GLOBAL, String::from("0/")); assert_eq!( &result, &[ @@ -1395,7 +1536,7 @@ mod test { ] ); - let result = tokenize(String::from("0/a")); + let result = tokenize(GLOBAL, String::from("0/a")); assert_eq!( &result, &[ @@ -1408,7 +1549,7 @@ mod test { #[test] #[wasm_bindgen_test] fn test_multiline_comments() { - let result = tokenize(String::from("{/*abc\ndef*/2}")); + let result = tokenize(GLOBAL, String::from("{/*abc\ndef*/2}")); assert_eq!( &result, &[ @@ -1418,7 +1559,7 @@ mod test { ] ); - let result = tokenize(String::from("{/*/* /**/2}")); + let result = tokenize(GLOBAL, String::from("{/*/* /**/2}")); assert_eq!( &result, &[ @@ -1428,7 +1569,7 @@ mod test { ] ); - let result = tokenize(String::from("{/*")); + let result = tokenize(GLOBAL, String::from("{/*")); assert_eq!( &result, &[ @@ -1437,7 +1578,7 @@ mod test { ] ); - let result = tokenize(String::from("{/**")); + let result = tokenize(GLOBAL, String::from("{/**")); assert_eq!( &result, &[