Add symbols

This commit is contained in:
Andrew Morris
2023-05-25 13:15:15 +10:00
parent d885873844
commit 706fb78442
13 changed files with 65 additions and 15 deletions

View File

@@ -118,7 +118,9 @@ static FROM: NativeFunction = NativeFunction {
.collect(),
))),
Val::Void | Val::Undefined | Val::Null => return type_error!("items is not iterable"),
Val::Bool(..) | Val::Number(..) | Val::BigInt(..) => Val::Array(Rc::new(VsArray::new())),
Val::Bool(..) | Val::Number(..) | Val::BigInt(..) | Val::Symbol(..) => {
Val::Array(Rc::new(VsArray::new()))
}
Val::Object(..) | Val::Function(..) | Val::Class(..) | Val::Static(..) | Val::Custom(..) => {
let len = op_sub(
first_param.clone(),

View File

@@ -104,6 +104,7 @@ pub fn to_error(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
None => "".to_string(),
})),
)]),
symbol_map: Default::default(),
prototype: Some(make_error_prototype()),
})))
}
@@ -118,6 +119,7 @@ fn make_error_prototype() -> Val {
),
("toString".to_string(), Val::Static(&ERROR_TO_STRING)),
]),
symbol_map: Default::default(),
prototype: None,
}))
}

View File

@@ -95,6 +95,7 @@ pub fn to_range_error(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
None => "".to_string(),
})),
)]),
symbol_map: Default::default(),
prototype: Some(make_range_error_prototype()),
})))
}
@@ -109,6 +110,7 @@ fn make_range_error_prototype() -> Val {
),
("toString".to_string(), Val::Static(&RANGE_ERROR_TO_STRING)),
]),
symbol_map: Default::default(),
prototype: None,
}))
}

View File

@@ -95,6 +95,7 @@ pub fn to_type_error(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
None => "".to_string(),
})),
)]),
symbol_map: Default::default(),
prototype: Some(make_type_error_prototype()),
})))
}
@@ -109,6 +110,7 @@ fn make_type_error_prototype() -> Val {
),
("toString".to_string(), Val::Static(&TYPE_ERROR_TO_STRING)),
]),
symbol_map: Default::default(),
prototype: None,
}))
}

View File

@@ -127,6 +127,7 @@ impl BytecodeDecoder {
Val::Object(Rc::new(VsObject {
string_map: obj,
symbol_map: Default::default(),
prototype: None,
}))
}

View File

@@ -377,6 +377,7 @@ impl StackFrameTrait for BytecodeStackFrame {
let mut instance = Val::Object(Rc::new(VsObject {
string_map: Default::default(),
symbol_map: Default::default(),
prototype: Some(class.instance_prototype.clone()),
}));

View File

@@ -19,6 +19,7 @@ mod vs_class;
mod vs_function;
pub mod vs_object;
mod vs_pointer;
mod vs_symbol;
pub mod vs_value;
pub use virtual_machine::VirtualMachine;

View File

@@ -372,6 +372,7 @@ pub fn op_typeof(input: Val) -> Val {
Bool => "boolean".to_string(),
Number => "number".to_string(),
BigInt => "bigint".to_string(),
Symbol => "symbol".to_string(),
String => "string".to_string(),
Array => "object".to_string(),
Object => "object".to_string(),
@@ -400,6 +401,7 @@ pub fn op_sub(left: Val, right: Val) -> Result<Val, Val> {
}),
Val::Number(number) => Ok(op_sub_number(number, &right)),
Val::BigInt(bigint) => Ok(op_sub_bigint(&bigint, &right)),
Val::Symbol(_) => Ok(Val::Undefined),
Val::String(string_data) => Ok(op_sub_string(&string_data, &right)),
Val::Array(array_data) => {
let right_index = match right.to_index() {
@@ -436,14 +438,16 @@ pub fn op_sub(left: Val, right: Val) -> Result<Val, Val> {
pub fn op_submov(target: &mut Val, subscript: Val, value: Val) -> Result<(), Val> {
match target {
Val::Void => format_err!("Internal: Shouldn't happen"), // TODO: Internal errors
Val::Undefined => format_err!("Cannot assign to subscript of undefined"),
Val::Null => format_err!("Cannot assign to subscript of null"),
Val::Bool(_) => format_err!("Cannot assign to subscript of bool"),
Val::Number(_) => format_err!("Cannot assign to subscript of number"),
Val::BigInt(_) => format_err!("Cannot assign to subscript of bigint"),
Val::String(_) => format_err!("Cannot assign to subscript of string"),
Val::Undefined => type_error!("Cannot assign to subscript of undefined"),
Val::Null => type_error!("Cannot assign to subscript of null"),
Val::Bool(_) => type_error!("Cannot assign to subscript of bool"),
Val::Number(_) => type_error!("Cannot assign to subscript of number"),
Val::BigInt(_) => type_error!("Cannot assign to subscript of bigint"),
Val::Symbol(_) => type_error!("Cannot assign to subscript of symbol"),
Val::String(_) => type_error!("Cannot assign to subscript of string"),
Val::Array(array_data) => {
let subscript_index = match subscript.to_index() {
// TODO: Internal errors
None => return format_err!("TODO: non-uint array subscript assignment"),
Some(i) => i,
};

View File

@@ -29,6 +29,7 @@ impl VsArray {
elements: vals,
object: VsObject {
string_map: Default::default(),
symbol_map: Default::default(),
prototype: Some(Val::Static(&ARRAY_PROTOTYPE)),
},
};
@@ -39,6 +40,7 @@ impl VsArray {
elements: vec![],
object: VsObject {
string_map: Default::default(),
symbol_map: Default::default(),
prototype: Some(Val::Static(&ARRAY_PROTOTYPE)),
},
};

View File

@@ -1,24 +1,34 @@
use std::collections::BTreeMap;
use crate::vs_symbol::VsSymbol;
use super::operations::op_sub;
use super::vs_value::{Val, ValTrait};
#[derive(Clone, Default, Debug)]
pub struct VsObject {
pub string_map: BTreeMap<String, Val>,
pub symbol_map: BTreeMap<VsSymbol, Val>,
pub prototype: Option<Val>,
}
impl VsObject {
pub fn sub(&self, key: Val) -> Val {
return match self.string_map.get(&key.val_to_string()) {
Some(val) => val.clone(),
None => match &self.prototype {
Some(prototype) => op_sub(prototype.clone(), key)
.map_err(|e| e.val_to_string())
.unwrap(), // TODO: Exception
None => Val::Undefined,
},
let val = match &key {
Val::String(string) => self.string_map.get(&**string),
Val::Symbol(symbol) => self.symbol_map.get(symbol),
_ => self.string_map.get(&key.val_to_string()),
};
if let Some(val) = val {
return val.clone();
}
match &self.prototype {
Some(prototype) => op_sub(prototype.clone(), key)
.map_err(|e| e.val_to_string())
.unwrap(), // TODO: Exception
None => Val::Undefined,
}
}
}

View File

@@ -96,6 +96,7 @@ impl ValTrait for VsPointer {
VsType::Bool => true,
VsType::Number => true,
VsType::BigInt => true,
VsType::Symbol => true,
VsType::String => true,
VsType::Array => false,
VsType::Object => false,

View File

@@ -0,0 +1,10 @@
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum VsSymbol {
ITERATOR,
}
pub fn symbol_to_name(symbol: VsSymbol) -> &'static str {
match symbol {
VsSymbol::ITERATOR => "iterator",
}
}

View File

@@ -14,6 +14,7 @@ use crate::vs_array::VsArray;
use crate::vs_class::VsClass;
use crate::vs_function::VsFunction;
use crate::vs_object::VsObject;
use crate::vs_symbol::{symbol_to_name, VsSymbol};
#[derive(Clone, Debug)]
pub enum Val {
@@ -23,6 +24,7 @@ pub enum Val {
Bool(bool),
Number(f64),
BigInt(BigInt),
Symbol(VsSymbol),
String(Rc<String>),
Array(Rc<VsArray>),
Object(Rc<VsObject>),
@@ -39,6 +41,7 @@ pub enum VsType {
Bool,
Number,
BigInt,
Symbol,
String,
Array,
Object,
@@ -97,6 +100,7 @@ impl ValTrait for Val {
Bool(_) => VsType::Bool,
Number(_) => VsType::Number,
BigInt(_) => VsType::BigInt,
Symbol(_) => VsType::Symbol,
String(_) => VsType::String,
Array(_) => VsType::Array,
Object(_) => VsType::Object,
@@ -127,6 +131,7 @@ impl ValTrait for Val {
}
} // TODO: Match js's number string format
BigInt(x) => x.to_string(),
Symbol(s) => format!("Symbol(Symbol.{})", symbol_to_name(s.clone())),
String(s) => s.to_string(),
Array(vals) => {
if vals.elements.len() == 0 {
@@ -169,6 +174,7 @@ impl ValTrait for Val {
Bool(b) => *b as u8 as f64,
Number(x) => *x,
BigInt(x) => x.to_f64().unwrap_or(f64::NAN),
Symbol(_) => f64::NAN, // TODO: Should be TypeError
String(s) => f64::from_str(s).unwrap_or(f64::NAN),
Array(vals) => match vals.elements.len() {
0 => 0_f64,
@@ -193,6 +199,7 @@ impl ValTrait for Val {
Bool(_) => None,
Number(x) => number_to_index(*x),
BigInt(b) => number_to_index(b.to_f64().unwrap_or(f64::NAN)),
Symbol(_) => None,
String(s) => match f64::from_str(s) {
Ok(x) => number_to_index(x),
Err(_) => None,
@@ -216,6 +223,7 @@ impl ValTrait for Val {
Bool(_) => true,
Number(_) => true,
BigInt(_) => true,
Symbol(_) => true,
String(_) => true,
Array(_) => false,
Object(_) => false,
@@ -244,6 +252,7 @@ impl ValTrait for Val {
Bool(b) => *b,
Number(x) => *x != 0_f64 && !x.is_nan(),
BigInt(x) => !x.is_zero(),
Symbol(_) => true,
String(s) => s.len() > 0,
Array(_) => true,
Object(_) => true,
@@ -264,6 +273,7 @@ impl ValTrait for Val {
Bool(_) => false,
Number(_) => false,
BigInt(_) => false,
Symbol(_) => false,
String(_) => false,
Array(_) => false,
Object(_) => false,
@@ -364,6 +374,7 @@ impl ValTrait for Val {
Val::Bool(_) => self.val_to_string(),
Val::Number(_) => self.val_to_string(),
Val::BigInt(_) => self.val_to_string() + "n",
Val::Symbol(s) => format!("Symbol.{}", symbol_to_name(s.clone())),
Val::String(str) => stringify_string(str),
Val::Array(vals) => {
if vals.elements.len() == 0 {
@@ -441,6 +452,7 @@ impl std::fmt::Display for Val {
Val::Bool(_) => write!(f, "\x1b[33m{}\x1b[39m", self.val_to_string()),
Val::Number(_) => write!(f, "\x1b[33m{}\x1b[39m", self.val_to_string()),
Val::BigInt(_) => write!(f, "\x1b[33m{}n\x1b[39m", self.val_to_string()),
Val::Symbol(_) => write!(f, "\x1b[32m{}\x1b[39m", self.codify()),
Val::String(_) => write!(f, "\x1b[32m{}\x1b[39m", self.codify()),
Val::Array(array) => {
if array.elements.len() == 0 {