Add base types
Implement JsNumber
This commit is contained in:
commit
de3e998808
13 changed files with 322 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
53
Cargo.lock
generated
Normal file
53
Cargo.lock
generated
Normal file
|
@ -0,0 +1,53 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "capibara-engine"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"widestring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8"
|
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "capibara-engine"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
num-bigint = "0.4.4"
|
||||
widestring = "1.0.2"
|
31
TODO.md
Normal file
31
TODO.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Todos
|
||||
|
||||
## Stage 1
|
||||
|
||||
- [ ] Js interpreter (for [EMCA Script 2023](https://tc39.es/ecma262/2023))
|
||||
- [ ] Js into token stream/tree
|
||||
- [ ] Stack handling
|
||||
- [ ] Token stream/tree interpretation
|
||||
|
||||
## Stage 2
|
||||
|
||||
- [ ] Update interpreter to latest stable ECMA script version
|
||||
|
||||
## Stage 3
|
||||
|
||||
- [ ] Deep type tracing
|
||||
|
||||
## Stage 4
|
||||
|
||||
- [ ] Typscript support
|
||||
|
||||
## Stage 5
|
||||
|
||||
- [ ] Precompile as much as possible
|
||||
|
||||
## Stage 6
|
||||
|
||||
- [ ] Profit?
|
||||
|
||||
## Comments
|
||||
- Have to add wasm somewhere
|
6
src/data_types/array.rs
Normal file
6
src/data_types/array.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
use super::VariableContent;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct JsArray {
|
||||
pub values: Vec<VariableContent>
|
||||
}
|
6
src/data_types/big_int.rs
Normal file
6
src/data_types/big_int.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
use num_bigint::BigInt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct JsBigInt {
|
||||
pub value: BigInt
|
||||
}
|
12
src/data_types/bool.rs
Normal file
12
src/data_types/bool.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
#[derive(Debug)]
|
||||
pub struct JsBool {
|
||||
pub value: bool
|
||||
}
|
||||
|
||||
pub const TRUE: JsBool = JsBool{
|
||||
value: true,
|
||||
};
|
||||
|
||||
pub const FALSE: JsBool = JsBool{
|
||||
value: false,
|
||||
};
|
27
src/data_types/mod.rs
Normal file
27
src/data_types/mod.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use self::{big_int::JsBigInt, bool::JsBool, number::JsNumber, object::JsObject, string::JsString, symbol::JsSymbol};
|
||||
|
||||
pub mod bool;
|
||||
pub mod string;
|
||||
pub mod symbol;
|
||||
pub mod number;
|
||||
pub mod big_int;
|
||||
pub mod object;
|
||||
pub mod array;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub enum VariableContent {
|
||||
#[default]
|
||||
Undefined,
|
||||
Null,
|
||||
Value(ValueType),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ValueType {
|
||||
Bool(JsBool),
|
||||
String(JsString),
|
||||
Symbol(JsSymbol),
|
||||
Number(JsNumber),
|
||||
BigInt(JsBigInt),
|
||||
Object(JsObject),
|
||||
}
|
158
src/data_types/number.rs
Normal file
158
src/data_types/number.rs
Normal file
|
@ -0,0 +1,158 @@
|
|||
use super::{bool::JsBool, string::JsString};
|
||||
use widestring::{utf16str, Utf16String};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct JsNumber {
|
||||
pub value: f64
|
||||
}
|
||||
|
||||
pub const NAN: JsNumber = JsNumber{
|
||||
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 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 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 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 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 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 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 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 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_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 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<F>(x: &JsNumber, y: &JsNumber, f: F) -> JsNumber where
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn jsnum_comp_op<F>(x: &JsNumber, y: &JsNumber, f: F) -> JsBool where
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
6
src/data_types/object.rs
Normal file
6
src/data_types/object.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct JsObject {
|
||||
pub value: HashMap<String, super::VariableContent>
|
||||
}
|
6
src/data_types/string.rs
Normal file
6
src/data_types/string.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
use widestring::Utf16String;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct JsString {
|
||||
pub value: Utf16String,
|
||||
}
|
4
src/data_types/symbol.rs
Normal file
4
src/data_types/symbol.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
#[derive(Debug)]
|
||||
pub struct JsSymbol {
|
||||
pub value: f64, // TODO: Understand what symbol is and turn this into a representation for those
|
||||
}
|
2
src/lib.rs
Normal file
2
src/lib.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
mod data_types;
|
||||
|
Loading…
Reference in a new issue