mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
Add symbols
This commit is contained in:
@@ -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(),
|
||||
|
||||
@@ -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,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ impl BytecodeDecoder {
|
||||
|
||||
Val::Object(Rc::new(VsObject {
|
||||
string_map: obj,
|
||||
symbol_map: Default::default(),
|
||||
prototype: None,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -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()),
|
||||
}));
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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)),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
10
valuescript_vm/src/vs_symbol.rs
Normal file
10
valuescript_vm/src/vs_symbol.rs
Normal 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",
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user