Add clone and ToJsString trait to everything

This commit is contained in:
mStar aka a person 2024-01-25 16:42:04 +01:00
parent fd9f5436e5
commit 7ad59ab87e
8 changed files with 318 additions and 250 deletions

View file

@ -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 struct JsArray {
pub values: Vec<VariableContent> pub values: Vec<ValueType>
}
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
}
}
} }

View file

@ -4,132 +4,132 @@ use super::{bool::JsBool, string::JsString};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct JsBigInt { pub struct JsBigInt {
pub value: BigInt pub value: BigInt
} }
// Implements https://tc39.es/ecma262/2023/#table-numeric-type-ops // Implements https://tc39.es/ecma262/2023/#table-numeric-type-ops
impl JsBigInt { impl JsBigInt {
pub fn unary_minus(&self) -> JsBigInt { pub fn unary_minus(&self) -> JsBigInt {
JsBigInt{ JsBigInt{
value: &self.value * -1 value: &self.value * -1
} }
} }
pub fn bitwise_not(&self) -> JsBigInt { pub fn bitwise_not(&self) -> JsBigInt {
JsBigInt{ JsBigInt{
value: !&self.value value: !&self.value
} }
} }
pub fn exponentiate(&self, x: &JsBigInt) -> JsBigInt { pub fn exponentiate(&self, x: &JsBigInt) -> JsBigInt {
let (_, digits) = x.value.to_u32_digits(); let (_, digits) = x.value.to_u32_digits();
JsBigInt{ JsBigInt{
value: self.value.pow(*digits.first().expect("Exponent bigint didn't have any digits")) value: self.value.pow(*digits.first().expect("Exponent bigint didn't have any digits"))
} }
} }
pub fn multiply(&self, x: &JsBigInt) -> JsBigInt { pub fn multiply(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{ JsBigInt{
value: &self.value * &x.value value: &self.value * &x.value
} }
} }
pub fn divide(&self, x: &JsBigInt) -> JsBigInt { pub fn divide(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{ JsBigInt{
value: &self.value / &x.value value: &self.value / &x.value
} }
} }
pub fn add(&self, x: &JsBigInt) -> JsBigInt { pub fn add(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{ JsBigInt{
value: &self.value + &x.value value: &self.value + &x.value
} }
} }
pub fn pre_add(&mut self) -> JsBigInt { pub fn pre_add(&mut self) -> JsBigInt {
self.value += 1; self.value += 1;
self.clone() self.clone()
} }
pub fn post_add(&mut self) -> JsBigInt { pub fn post_add(&mut self) -> JsBigInt {
let old = self.clone(); let old = self.clone();
self.value += 1; self.value += 1;
old old
} }
pub fn subtract(&self, x: &JsBigInt) -> JsBigInt { pub fn subtract(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{ JsBigInt{
value: &self.value - &x.value value: &self.value - &x.value
} }
} }
pub fn pre_subtract(&mut self) -> JsBigInt { pub fn pre_subtract(&mut self) -> JsBigInt {
self.value -= 1; self.value -= 1;
self.clone() self.clone()
} }
pub fn post_subtract(&mut self) -> JsBigInt { pub fn post_subtract(&mut self) -> JsBigInt {
let old = self.clone(); let old = self.clone();
self.value -= 1; self.value -= 1;
old old
} }
pub fn left_shift(&self, x: &JsBigInt) -> JsBigInt { pub fn left_shift(&self, x: &JsBigInt) -> JsBigInt {
let (_, digits) = x.value.to_u32_digits(); let (_, digits) = x.value.to_u32_digits();
JsBigInt{ JsBigInt{
value: &self.value << *digits.first().expect("Shift amount bigint didn't have any digits") value: &self.value << *digits.first().expect("Shift amount bigint didn't have any digits")
} }
} }
pub fn right_shift_signed(&self, x: &JsBigInt) -> JsBigInt { pub fn right_shift_signed(&self, x: &JsBigInt) -> JsBigInt {
let (_, digits) = x.value.to_u32_digits(); let (_, digits) = x.value.to_u32_digits();
JsBigInt{ JsBigInt{
value: &self.value >> *digits.first().expect("Shift amount bigint didn't have any digits") value: &self.value >> *digits.first().expect("Shift amount bigint didn't have any digits")
} }
} }
pub fn right_shift_unsigned(&self, x: &JsBigInt) -> JsBigInt { pub fn right_shift_unsigned(&self, x: &JsBigInt) -> JsBigInt {
let (_, digits) = x.value.to_u32_digits(); let (_, digits) = x.value.to_u32_digits();
let (_, old_bytes) = self.value.to_bytes_be(); let (_, old_bytes) = self.value.to_bytes_be();
let u = BigUint::from_bytes_be(&old_bytes); let u = BigUint::from_bytes_be(&old_bytes);
JsBigInt{ JsBigInt{
value: (u >> *digits.first().expect("Shift amount bigint didn't have any digits")).to_bigint().expect("Failed to convert BigUInt to BigInt") 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 { pub fn less_than(&self, x: &JsBigInt) -> JsBool {
JsBool { value: self.value < x.value } JsBool { value: self.value < x.value }
} }
pub fn equal(&self, x: &JsBigInt) -> JsBool { pub fn equal(&self, x: &JsBigInt) -> JsBool {
JsBool { value: self.value == x.value } JsBool { value: self.value == x.value }
} }
pub fn same_value(&self, x: &JsBigInt) -> JsBool { pub fn same_value(&self, x: &JsBigInt) -> JsBool {
JsBool { value: std::ptr::eq(self, x) } JsBool { value: std::ptr::eq(self, x) }
} }
pub fn bitwise_and(&self, x: &JsBigInt) -> JsBigInt { pub fn bitwise_and(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{ JsBigInt{
value: &self.value & &x.value value: &self.value & &x.value
} }
} }
pub fn bitwise_xor(&self, x: &JsBigInt) -> JsBigInt { pub fn bitwise_xor(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{ JsBigInt{
value: &self.value ^ &x.value value: &self.value ^ &x.value
} }
} }
pub fn bitwise_or(&self, x: &JsBigInt) -> JsBigInt { pub fn bitwise_or(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{ JsBigInt{
value: &self.value | &x.value value: &self.value | &x.value
} }
} }
pub fn to_string(&self) -> JsString { pub fn to_string(&self) -> JsString {
JsString { JsString {
value: self.value.to_string().into() value: self.value.to_string().into()
} }
} }
} }

View file

@ -1,12 +1,24 @@
#[derive(Debug)] use widestring::Utf16String;
use super::{string::JsString, ToJsString};
#[derive(Debug, Clone)]
pub struct JsBool { pub struct JsBool {
pub value: bool pub value: bool
} }
pub const TRUE: JsBool = JsBool{ pub const TRUE: JsBool = JsBool{
value: true, value: true,
}; };
pub const FALSE: JsBool = JsBool{ pub const FALSE: JsBool = JsBool{
value: false, value: false,
}; };
impl ToJsString for JsBool {
fn to_string(&self) -> JsString {
JsString {
value: if self.value {Utf16String::from("true")} else {Utf16String::from("false")}
}
}
}

View file

@ -9,20 +9,37 @@ pub mod big_int;
pub mod object; pub mod object;
pub mod array; pub mod array;
#[derive(Debug, Default)] #[derive(Debug, Default, Clone)]
pub enum VariableContent { pub enum VariableContent {
#[default] #[default]
Undefined, Undefined,
Null, Null,
Value(ValueType), Value(ValueType),
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum ValueType { pub enum ValueType {
Bool(JsBool), Bool(JsBool),
String(JsString), String(JsString),
Symbol(JsSymbol), Symbol(JsSymbol),
Number(JsNumber), Number(JsNumber),
BigInt(JsBigInt), BigInt(JsBigInt),
Object(JsObject), 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(),
}
}
} }

View file

@ -1,158 +1,161 @@
use super::{bool::JsBool, string::JsString}; use super::{bool::JsBool, string::JsString, ToJsString};
use widestring::{utf16str, Utf16String}; use widestring::{utf16str, Utf16String};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct JsNumber { pub struct JsNumber {
pub value: f64 pub value: f64
} }
pub const NAN: JsNumber = JsNumber{ pub const NAN: JsNumber = JsNumber{
value: f64::NAN, value: f64::NAN,
}; };
// Implements https://tc39.es/ecma262/2023/#table-numeric-type-ops // Implements https://tc39.es/ecma262/2023/#table-numeric-type-ops
impl JsNumber { impl JsNumber {
pub fn unary_minus(&self) -> JsNumber { pub fn unary_minus(&self) -> JsNumber {
jsnum_math_op(&self, &self, |x, _| -x) jsnum_math_op(&self, &self, |x, _| -x)
} }
pub fn bitwise_not(&self) -> JsNumber { pub fn bitwise_not(&self) -> JsNumber {
jsnum_math_op(&self, &self, |x, _| !i64::from(x.floor() as i64) as f64) jsnum_math_op(&self, &self, |x, _| !i64::from(x.floor() as i64) as f64)
} }
pub fn exponentiate(&self, x: &JsNumber) -> JsNumber { pub fn exponentiate(&self, x: &JsNumber) -> JsNumber {
jsnum_math_op(&self, &x, |x, y| x.powf(*y)) jsnum_math_op(&self, &x, |x, y| x.powf(*y))
} }
pub fn multiply(&self, x: &JsNumber) -> JsNumber { pub fn multiply(&self, x: &JsNumber) -> JsNumber {
jsnum_math_op(&self, &x, |x, y| x * y) jsnum_math_op(&self, &x, |x, y| x * y)
} }
pub fn divide(&self, x: &JsNumber) -> JsNumber { pub fn divide(&self, x: &JsNumber) -> JsNumber {
jsnum_math_op(&self, &x, |x, y| x % y) jsnum_math_op(&self, &x, |x, y| x % y)
} }
pub fn add(&self, x: &JsNumber) -> JsNumber { pub fn add(&self, x: &JsNumber) -> JsNumber {
jsnum_math_op(&self, &x, |x, y| x + y) jsnum_math_op(&self, &x, |x, y| x + y)
} }
pub fn pre_add(&mut self) -> JsNumber { pub fn pre_add(&mut self) -> JsNumber {
return if self.value.is_nan() { return if self.value.is_nan() {
return NAN.clone() return NAN.clone()
} else { } else {
self.value += 1.0; self.value += 1.0;
self.clone() self.clone()
} }
} }
pub fn post_add(&mut self) -> JsNumber { pub fn post_add(&mut self) -> JsNumber {
return if self.value.is_nan() { return if self.value.is_nan() {
return NAN.clone() return NAN.clone()
} else { } else {
let old = self.clone(); let old = self.clone();
self.value += 1.0; self.value += 1.0;
old old
} }
} }
pub fn subtract(&self, x: &JsNumber) -> JsNumber { pub fn subtract(&self, x: &JsNumber) -> JsNumber {
jsnum_math_op(&self, &x, |x, y| x - y) jsnum_math_op(&self, &x, |x, y| x - y)
} }
pub fn pre_subtract(&mut self) -> JsNumber { pub fn pre_subtract(&mut self) -> JsNumber {
return if self.value.is_nan() { return if self.value.is_nan() {
return NAN.clone() return NAN.clone()
} else { } else {
self.value -= 1.0; self.value -= 1.0;
self.clone() self.clone()
} }
} }
pub fn post_subtract(&mut self) -> JsNumber { pub fn post_subtract(&mut self) -> JsNumber {
return if self.value.is_nan() { return if self.value.is_nan() {
return NAN.clone() return NAN.clone()
} else { } else {
let old = self.clone(); let old = self.clone();
self.value -= 1.0; self.value -= 1.0;
old old
} }
} }
pub fn left_shift(&self, x: &JsNumber) -> JsNumber { 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) 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 { 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) 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 { 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) 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 { pub fn less_than(&self, x: &JsNumber) -> JsBool {
jsnum_comp_op(&self, &x, |x, y| x < y) jsnum_comp_op(&self, &x, |x, y| x < y)
} }
pub fn equal(&self, x: &JsNumber) -> JsBool { pub fn equal(&self, x: &JsNumber) -> JsBool {
jsnum_comp_op(&self, &x, |x, y| x == y) jsnum_comp_op(&self, &x, |x, y| x == y)
} }
pub fn same_value(&self, x: &JsNumber) -> JsBool { pub fn same_value(&self, x: &JsNumber) -> JsBool {
JsBool { value: std::ptr::eq(self, x) } JsBool { value: std::ptr::eq(self, x) }
} }
pub fn bitwise_and(&self, x: &JsNumber) -> JsNumber { 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) 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 { 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) 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 { 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) 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{ impl ToJsString for JsNumber {
value: utf16str!("Infinity").to_owned() fn to_string(&self) -> JsString {
} if self.value.is_infinite() {
} else if self.value.is_nan() { JsString{
JsString{ value: utf16str!("Infinity").to_owned()
value: utf16str!("NaN").to_owned() }
} } else if self.value.is_nan() {
} else { JsString{
JsString{ value: utf16str!("NaN").to_owned()
value: Utf16String::from_str(&self.value.to_string()) }
} } else {
} JsString{
} value: Utf16String::from_str(&self.value.to_string())
}
}
}
} }
fn jsnum_math_op<F>(x: &JsNumber, y: &JsNumber, f: F) -> JsNumber where fn jsnum_math_op<F>(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() { if x.value.is_nan() || y.value.is_nan() {
NAN.clone() NAN.clone()
} else { } else {
let value = f(&x.value, &y.value); let value = f(&x.value, &y.value);
JsNumber{ JsNumber{
value value
} }
} }
} }
fn jsnum_comp_op<F>(x: &JsNumber, y: &JsNumber, f: F) -> JsBool where fn jsnum_comp_op<F>(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() { if x.value.is_nan() || y.value.is_nan() {
super::bool::FALSE super::bool::FALSE
} else { } else {
let value = f(&x.value, &y.value); let value = f(&x.value, &y.value);
JsBool{ JsBool{
value value
} }
} }
} }

View file

@ -1,6 +1,18 @@
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug)] use widestring::Utf16String;
use super::{string::JsString, ToJsString};
#[derive(Debug, Clone)]
pub struct JsObject { pub struct JsObject {
pub value: HashMap<String, super::VariableContent> pub value: HashMap<String, super::VariableContent>
}
impl ToJsString for JsObject {
fn to_string(&self) -> JsString {
JsString{
value: Utf16String::from_str("[object Object]")
}
}
} }

View file

@ -1,6 +1,14 @@
use widestring::Utf16String; use widestring::Utf16String;
#[derive(Debug)] use super::ToJsString;
#[derive(Debug, Clone)]
pub struct JsString { pub struct JsString {
pub value: Utf16String, pub value: Utf16String,
}
impl ToJsString for JsString {
fn to_string(&self) -> JsString {
self.clone()
}
} }

View file

@ -1,4 +1,4 @@
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct JsSymbol { 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
} }