diff --git a/src/data_types/array.rs b/src/data_types/array.rs index c8eca42..7b4eb81 100644 --- a/src/data_types/array.rs +++ b/src/data_types/array.rs @@ -1,6 +1,22 @@ -use super::VariableContent; +use widestring::Utf16String; -#[derive(Debug)] +use super::{string::JsString, ToJsString, ValueType}; + +#[derive(Debug, Clone)] pub struct JsArray { - pub values: Vec + pub values: Vec +} + +impl ToJsString for JsArray { + fn to_string(&self) -> JsString { + let mut s = Utf16String::from("["); + for i in self.values.iter() { + let i = i as &dyn ToJsString; + s.push_utfstr(&i.to_string().value); + } + s += "]"; + JsString { + value: s + } + } } \ No newline at end of file diff --git a/src/data_types/big_int.rs b/src/data_types/big_int.rs index 66b3111..f59d7dc 100644 --- a/src/data_types/big_int.rs +++ b/src/data_types/big_int.rs @@ -4,132 +4,132 @@ use super::{bool::JsBool, string::JsString}; #[derive(Debug, Clone)] pub struct JsBigInt { - pub value: BigInt + pub value: BigInt } // Implements https://tc39.es/ecma262/2023/#table-numeric-type-ops impl JsBigInt { - pub fn unary_minus(&self) -> JsBigInt { - JsBigInt{ - value: &self.value * -1 - } - } + pub fn unary_minus(&self) -> JsBigInt { + JsBigInt{ + value: &self.value * -1 + } + } - pub fn bitwise_not(&self) -> JsBigInt { - JsBigInt{ - value: !&self.value - } - } + pub fn bitwise_not(&self) -> JsBigInt { + JsBigInt{ + value: !&self.value + } + } - pub fn exponentiate(&self, x: &JsBigInt) -> JsBigInt { - let (_, digits) = x.value.to_u32_digits(); - JsBigInt{ - value: self.value.pow(*digits.first().expect("Exponent bigint didn't have any digits")) - } - } + pub fn exponentiate(&self, x: &JsBigInt) -> JsBigInt { + let (_, digits) = x.value.to_u32_digits(); + JsBigInt{ + value: self.value.pow(*digits.first().expect("Exponent bigint didn't have any digits")) + } + } - pub fn multiply(&self, x: &JsBigInt) -> JsBigInt { - JsBigInt{ - value: &self.value * &x.value - } - } + pub fn multiply(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value * &x.value + } + } - pub fn divide(&self, x: &JsBigInt) -> JsBigInt { - JsBigInt{ - value: &self.value / &x.value - } - } + pub fn divide(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value / &x.value + } + } - pub fn add(&self, x: &JsBigInt) -> JsBigInt { - JsBigInt{ - value: &self.value + &x.value - } - } + pub fn add(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value + &x.value + } + } - pub fn pre_add(&mut self) -> JsBigInt { - self.value += 1; - self.clone() - } + pub fn pre_add(&mut self) -> JsBigInt { + self.value += 1; + self.clone() + } - pub fn post_add(&mut self) -> JsBigInt { - let old = self.clone(); - self.value += 1; - old - } + pub fn post_add(&mut self) -> JsBigInt { + let old = self.clone(); + self.value += 1; + old + } - pub fn subtract(&self, x: &JsBigInt) -> JsBigInt { - JsBigInt{ - value: &self.value - &x.value - } - } + pub fn subtract(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value - &x.value + } + } - pub fn pre_subtract(&mut self) -> JsBigInt { - self.value -= 1; - self.clone() - } + pub fn pre_subtract(&mut self) -> JsBigInt { + self.value -= 1; + self.clone() + } - pub fn post_subtract(&mut self) -> JsBigInt { - let old = self.clone(); - self.value -= 1; - old - } + pub fn post_subtract(&mut self) -> JsBigInt { + let old = self.clone(); + self.value -= 1; + old + } - pub fn left_shift(&self, x: &JsBigInt) -> JsBigInt { - let (_, digits) = x.value.to_u32_digits(); - JsBigInt{ - value: &self.value << *digits.first().expect("Shift amount bigint didn't have any digits") - } - } - - pub fn right_shift_signed(&self, x: &JsBigInt) -> JsBigInt { - let (_, digits) = x.value.to_u32_digits(); - JsBigInt{ - value: &self.value >> *digits.first().expect("Shift amount bigint didn't have any digits") - } - } + pub fn left_shift(&self, x: &JsBigInt) -> JsBigInt { + let (_, digits) = x.value.to_u32_digits(); + JsBigInt{ + value: &self.value << *digits.first().expect("Shift amount bigint didn't have any digits") + } + } + + pub fn right_shift_signed(&self, x: &JsBigInt) -> JsBigInt { + let (_, digits) = x.value.to_u32_digits(); + JsBigInt{ + value: &self.value >> *digits.first().expect("Shift amount bigint didn't have any digits") + } + } - pub fn right_shift_unsigned(&self, x: &JsBigInt) -> JsBigInt { - let (_, digits) = x.value.to_u32_digits(); - let (_, old_bytes) = self.value.to_bytes_be(); - let u = BigUint::from_bytes_be(&old_bytes); - JsBigInt{ - value: (u >> *digits.first().expect("Shift amount bigint didn't have any digits")).to_bigint().expect("Failed to convert BigUInt to BigInt") - } - } + pub fn right_shift_unsigned(&self, x: &JsBigInt) -> JsBigInt { + let (_, digits) = x.value.to_u32_digits(); + let (_, old_bytes) = self.value.to_bytes_be(); + let u = BigUint::from_bytes_be(&old_bytes); + JsBigInt{ + value: (u >> *digits.first().expect("Shift amount bigint didn't have any digits")).to_bigint().expect("Failed to convert BigUInt to BigInt") + } + } - pub fn less_than(&self, x: &JsBigInt) -> JsBool { - JsBool { value: self.value < x.value } - } + pub fn less_than(&self, x: &JsBigInt) -> JsBool { + JsBool { value: self.value < x.value } + } - pub fn equal(&self, x: &JsBigInt) -> JsBool { - JsBool { value: self.value == x.value } - } + pub fn equal(&self, x: &JsBigInt) -> JsBool { + JsBool { value: self.value == x.value } + } - pub fn same_value(&self, x: &JsBigInt) -> JsBool { - JsBool { value: std::ptr::eq(self, x) } - } + pub fn same_value(&self, x: &JsBigInt) -> JsBool { + JsBool { value: std::ptr::eq(self, x) } + } - pub fn bitwise_and(&self, x: &JsBigInt) -> JsBigInt { - JsBigInt{ - value: &self.value & &x.value - } - } + pub fn bitwise_and(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value & &x.value + } + } - pub fn bitwise_xor(&self, x: &JsBigInt) -> JsBigInt { - JsBigInt{ - value: &self.value ^ &x.value - } - } + pub fn bitwise_xor(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value ^ &x.value + } + } - pub fn bitwise_or(&self, x: &JsBigInt) -> JsBigInt { - JsBigInt{ - value: &self.value | &x.value - } - } + pub fn bitwise_or(&self, x: &JsBigInt) -> JsBigInt { + JsBigInt{ + value: &self.value | &x.value + } + } - pub fn to_string(&self) -> JsString { - JsString { - value: self.value.to_string().into() - } - } + pub fn to_string(&self) -> JsString { + JsString { + value: self.value.to_string().into() + } + } } diff --git a/src/data_types/bool.rs b/src/data_types/bool.rs index dd3f0f5..5848c7e 100644 --- a/src/data_types/bool.rs +++ b/src/data_types/bool.rs @@ -1,12 +1,24 @@ -#[derive(Debug)] +use widestring::Utf16String; + +use super::{string::JsString, ToJsString}; + +#[derive(Debug, Clone)] pub struct JsBool { - pub value: bool + pub value: bool } pub const TRUE: JsBool = JsBool{ - value: true, + value: true, }; pub const FALSE: JsBool = JsBool{ - value: false, -}; \ No newline at end of file + value: false, +}; + +impl ToJsString for JsBool { + fn to_string(&self) -> JsString { + JsString { + value: if self.value {Utf16String::from("true")} else {Utf16String::from("false")} + } + } +} \ No newline at end of file diff --git a/src/data_types/mod.rs b/src/data_types/mod.rs index 1094bef..7b5e9a3 100644 --- a/src/data_types/mod.rs +++ b/src/data_types/mod.rs @@ -9,20 +9,37 @@ pub mod big_int; pub mod object; pub mod array; -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub enum VariableContent { - #[default] - Undefined, - Null, - Value(ValueType), + #[default] + Undefined, + Null, + Value(ValueType), } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum ValueType { - Bool(JsBool), - String(JsString), - Symbol(JsSymbol), - Number(JsNumber), - BigInt(JsBigInt), - Object(JsObject), + Bool(JsBool), + String(JsString), + Symbol(JsSymbol), + Number(JsNumber), + BigInt(JsBigInt), + Object(JsObject), +} + +pub trait ToJsString { + fn to_string(&self) -> JsString; +} + +impl ToJsString for ValueType { + fn to_string(&self) -> JsString { + match &self { + ValueType::Bool(x) => x.to_string(), + ValueType::String(x) => x.clone(), + ValueType::Symbol(x) => todo!(), + ValueType::Number(x) => x.to_string(), + ValueType::BigInt(x) => x.to_string(), + ValueType::Object(x) => x.to_string(), + } + } } \ No newline at end of file diff --git a/src/data_types/number.rs b/src/data_types/number.rs index 9620aae..69578b3 100644 --- a/src/data_types/number.rs +++ b/src/data_types/number.rs @@ -1,158 +1,161 @@ -use super::{bool::JsBool, string::JsString}; +use super::{bool::JsBool, string::JsString, ToJsString}; use widestring::{utf16str, Utf16String}; #[derive(Debug, Clone, Copy)] pub struct JsNumber { - pub value: f64 + pub value: f64 } pub const NAN: JsNumber = JsNumber{ - value: f64::NAN, + value: f64::NAN, }; // Implements https://tc39.es/ecma262/2023/#table-numeric-type-ops impl JsNumber { - pub fn unary_minus(&self) -> JsNumber { - jsnum_math_op(&self, &self, |x, _| -x) - } + pub fn unary_minus(&self) -> JsNumber { + jsnum_math_op(&self, &self, |x, _| -x) + } - pub fn bitwise_not(&self) -> JsNumber { - jsnum_math_op(&self, &self, |x, _| !i64::from(x.floor() as i64) as f64) - } + pub fn bitwise_not(&self) -> JsNumber { + jsnum_math_op(&self, &self, |x, _| !i64::from(x.floor() as i64) as f64) + } - pub fn exponentiate(&self, x: &JsNumber) -> JsNumber { - jsnum_math_op(&self, &x, |x, y| x.powf(*y)) - } + pub fn exponentiate(&self, x: &JsNumber) -> JsNumber { + jsnum_math_op(&self, &x, |x, y| x.powf(*y)) + } - pub fn multiply(&self, x: &JsNumber) -> JsNumber { - jsnum_math_op(&self, &x, |x, y| x * y) - } + pub fn multiply(&self, x: &JsNumber) -> JsNumber { + jsnum_math_op(&self, &x, |x, y| x * y) + } - pub fn divide(&self, x: &JsNumber) -> JsNumber { - jsnum_math_op(&self, &x, |x, y| x % y) - } + pub fn divide(&self, x: &JsNumber) -> JsNumber { + jsnum_math_op(&self, &x, |x, y| x % y) + } - pub fn add(&self, x: &JsNumber) -> JsNumber { - jsnum_math_op(&self, &x, |x, y| x + y) - } + pub fn add(&self, x: &JsNumber) -> JsNumber { + jsnum_math_op(&self, &x, |x, y| x + y) + } - pub fn pre_add(&mut self) -> JsNumber { - return if self.value.is_nan() { - return NAN.clone() - } else { - self.value += 1.0; - self.clone() - } - } + pub fn pre_add(&mut self) -> JsNumber { + return if self.value.is_nan() { + return NAN.clone() + } else { + self.value += 1.0; + self.clone() + } + } - pub fn post_add(&mut self) -> JsNumber { - return if self.value.is_nan() { - return NAN.clone() - } else { - let old = self.clone(); - self.value += 1.0; - old - } - } + pub fn post_add(&mut self) -> JsNumber { + return if self.value.is_nan() { + return NAN.clone() + } else { + let old = self.clone(); + self.value += 1.0; + old + } + } - pub fn subtract(&self, x: &JsNumber) -> JsNumber { - jsnum_math_op(&self, &x, |x, y| x - y) - } + pub fn subtract(&self, x: &JsNumber) -> JsNumber { + jsnum_math_op(&self, &x, |x, y| x - y) + } - pub fn pre_subtract(&mut self) -> JsNumber { - return if self.value.is_nan() { - return NAN.clone() - } else { - self.value -= 1.0; - self.clone() - } - } + pub fn pre_subtract(&mut self) -> JsNumber { + return if self.value.is_nan() { + return NAN.clone() + } else { + self.value -= 1.0; + self.clone() + } + } - pub fn post_subtract(&mut self) -> JsNumber { - return if self.value.is_nan() { - return NAN.clone() - } else { - let old = self.clone(); - self.value -= 1.0; - old - } - } + pub fn post_subtract(&mut self) -> JsNumber { + return if self.value.is_nan() { + return NAN.clone() + } else { + let old = self.clone(); + self.value -= 1.0; + old + } + } - pub fn left_shift(&self, x: &JsNumber) -> JsNumber { - jsnum_math_op(&self, &x, |x, y| ((x.floor() as i64) << (y.floor() as i64)) as f64) - } - - pub fn right_shift_signed(&self, x: &JsNumber) -> JsNumber { - jsnum_math_op(&self, &x, |x, y| ((x.floor() as i64) >> (y.floor() as i64)) as f64) - } + pub fn left_shift(&self, x: &JsNumber) -> JsNumber { + jsnum_math_op(&self, &x, |x, y| ((x.floor() as i64) << (y.floor() as i64)) as f64) + } + + pub fn right_shift_signed(&self, x: &JsNumber) -> JsNumber { + jsnum_math_op(&self, &x, |x, y| ((x.floor() as i64) >> (y.floor() as i64)) as f64) + } - pub fn right_shift_unsigned(&self, x: &JsNumber) -> JsNumber { - jsnum_math_op(&self, &x, |x, y| (((x.floor() as i64) as u64) >> (y.floor() as i64)) as f64) - } + pub fn right_shift_unsigned(&self, x: &JsNumber) -> JsNumber { + jsnum_math_op(&self, &x, |x, y| (((x.floor() as i64) as u64) >> (y.floor() as i64)) as f64) + } - pub fn less_than(&self, x: &JsNumber) -> JsBool { - jsnum_comp_op(&self, &x, |x, y| x < y) - } + pub fn less_than(&self, x: &JsNumber) -> JsBool { + jsnum_comp_op(&self, &x, |x, y| x < y) + } - pub fn equal(&self, x: &JsNumber) -> JsBool { - jsnum_comp_op(&self, &x, |x, y| x == y) - } + pub fn equal(&self, x: &JsNumber) -> JsBool { + jsnum_comp_op(&self, &x, |x, y| x == y) + } - pub fn same_value(&self, x: &JsNumber) -> JsBool { - JsBool { value: std::ptr::eq(self, x) } - } + pub fn same_value(&self, x: &JsNumber) -> JsBool { + JsBool { value: std::ptr::eq(self, x) } + } - pub fn bitwise_and(&self, x: &JsNumber) -> JsNumber { - jsnum_math_op(&self, &x, |x, y| ((x.floor() as i64) & (y.floor() as i64)) as f64) - } + pub fn bitwise_and(&self, x: &JsNumber) -> JsNumber { + jsnum_math_op(&self, &x, |x, y| ((x.floor() as i64) & (y.floor() as i64)) as f64) + } - pub fn bitwise_xor(&self, x: &JsNumber) -> JsNumber { - jsnum_math_op(&self, &x, |x, y| ((x.floor() as i64) ^ (y.floor() as i64)) as f64) - } + pub fn bitwise_xor(&self, x: &JsNumber) -> JsNumber { + jsnum_math_op(&self, &x, |x, y| ((x.floor() as i64) ^ (y.floor() as i64)) as f64) + } - pub fn bitwise_or(&self, x: &JsNumber) -> JsNumber { - jsnum_math_op(&self, &x, |x, y| ((x.floor() as i64) | (y.floor() as i64)) as f64) - } + pub fn bitwise_or(&self, x: &JsNumber) -> JsNumber { + jsnum_math_op(&self, &x, |x, y| ((x.floor() as i64) | (y.floor() as i64)) as f64) + } - pub fn to_string(&self) -> JsString { - if self.value.is_infinite() { - JsString{ - value: utf16str!("Infinity").to_owned() - } - } else if self.value.is_nan() { - JsString{ - value: utf16str!("NaN").to_owned() - } - } else { - JsString{ - value: Utf16String::from_str(&self.value.to_string()) - } - } - } +} + +impl ToJsString for JsNumber { + fn to_string(&self) -> JsString { + if self.value.is_infinite() { + JsString{ + value: utf16str!("Infinity").to_owned() + } + } else if self.value.is_nan() { + JsString{ + value: utf16str!("NaN").to_owned() + } + } else { + JsString{ + value: Utf16String::from_str(&self.value.to_string()) + } + } + } } fn jsnum_math_op(x: &JsNumber, y: &JsNumber, f: F) -> JsNumber where - F: Fn(&f64, &f64) -> f64 + F: Fn(&f64, &f64) -> f64 { - if x.value.is_nan() || y.value.is_nan() { - NAN.clone() - } else { - let value = f(&x.value, &y.value); - JsNumber{ - value - } - } + if x.value.is_nan() || y.value.is_nan() { + NAN.clone() + } else { + let value = f(&x.value, &y.value); + JsNumber{ + value + } + } } fn jsnum_comp_op(x: &JsNumber, y: &JsNumber, f: F) -> JsBool where - F: Fn(&f64, &f64) -> bool + F: Fn(&f64, &f64) -> bool { - if x.value.is_nan() || y.value.is_nan() { - super::bool::FALSE - } else { - let value = f(&x.value, &y.value); - JsBool{ - value - } - } + if x.value.is_nan() || y.value.is_nan() { + super::bool::FALSE + } else { + let value = f(&x.value, &y.value); + JsBool{ + value + } + } } \ No newline at end of file diff --git a/src/data_types/object.rs b/src/data_types/object.rs index ec409e9..0800a6f 100644 --- a/src/data_types/object.rs +++ b/src/data_types/object.rs @@ -1,6 +1,18 @@ use std::collections::HashMap; -#[derive(Debug)] +use widestring::Utf16String; + +use super::{string::JsString, ToJsString}; + +#[derive(Debug, Clone)] pub struct JsObject { - pub value: HashMap + pub value: HashMap +} + +impl ToJsString for JsObject { + fn to_string(&self) -> JsString { + JsString{ + value: Utf16String::from_str("[object Object]") + } + } } \ No newline at end of file diff --git a/src/data_types/string.rs b/src/data_types/string.rs index 082529d..596700c 100644 --- a/src/data_types/string.rs +++ b/src/data_types/string.rs @@ -1,6 +1,14 @@ use widestring::Utf16String; -#[derive(Debug)] +use super::ToJsString; + +#[derive(Debug, Clone)] pub struct JsString { - pub value: Utf16String, + pub value: Utf16String, +} + +impl ToJsString for JsString { + fn to_string(&self) -> JsString { + self.clone() + } } \ No newline at end of file diff --git a/src/data_types/symbol.rs b/src/data_types/symbol.rs index c86d43c..e4e7b3c 100644 --- a/src/data_types/symbol.rs +++ b/src/data_types/symbol.rs @@ -1,4 +1,4 @@ -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct JsSymbol { - pub value: f64, // TODO: Understand what symbol is and turn this into a representation for those + pub value: f64, // TODO: Understand what symbol is and turn this into a representation for those } \ No newline at end of file