mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-01-15 00:18:06 -05:00
Implement in operator
This commit is contained in:
@@ -70,6 +70,13 @@ where
|
||||
Ok(Self::bo_sub(&key.to_string()))
|
||||
}
|
||||
|
||||
fn has(&self, key: &Val) -> Option<bool> {
|
||||
match Self::bo_sub(&key.to_string()) {
|
||||
Val::Undefined => Some(false),
|
||||
_ => Some(true),
|
||||
}
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: &Val, _value: Val) -> Result<(), Val> {
|
||||
Err(format!("Cannot assign to subscript of {} builtin", Self::bo_name()).to_type_error())
|
||||
}
|
||||
|
||||
@@ -92,6 +92,18 @@ impl ValTrait for Generator {
|
||||
Ok(Val::Undefined)
|
||||
}
|
||||
|
||||
fn has(&self, key: &Val) -> Option<bool> {
|
||||
if key.to_string() == "next" {
|
||||
return Some(true);
|
||||
}
|
||||
|
||||
if let Val::Symbol(VsSymbol::ITERATOR) = key {
|
||||
return Some(true);
|
||||
}
|
||||
|
||||
Some(false)
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: &Val, _value: Val) -> Result<(), Val> {
|
||||
Err("Cannot assign to subscript of a generator".to_type_error())
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@ use crate::{
|
||||
LoadFunctionResult, ValTrait,
|
||||
};
|
||||
|
||||
use super::{iteration_result::IterationResult, return_this::RETURN_THIS};
|
||||
use super::{
|
||||
iteration_result::IterationResult, iterator_has::iterator_has, return_this::RETURN_THIS,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ArrayEntriesIterator {
|
||||
@@ -87,6 +89,10 @@ impl ValTrait for ArrayEntriesIterator {
|
||||
Ok(Val::Undefined)
|
||||
}
|
||||
|
||||
fn has(&self, key: &Val) -> Option<bool> {
|
||||
iterator_has(key)
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: &Val, _value: Val) -> Result<(), Val> {
|
||||
Err("Cannot assign to subscript of array iterator".to_type_error())
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@ use crate::{
|
||||
LoadFunctionResult, ValTrait,
|
||||
};
|
||||
|
||||
use super::{iteration_result::IterationResult, return_this::RETURN_THIS};
|
||||
use super::{
|
||||
iteration_result::IterationResult, iterator_has::iterator_has, return_this::RETURN_THIS,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ArrayIterator {
|
||||
@@ -87,6 +89,10 @@ impl ValTrait for ArrayIterator {
|
||||
Ok(Val::Undefined)
|
||||
}
|
||||
|
||||
fn has(&self, key: &Val) -> Option<bool> {
|
||||
iterator_has(key)
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: &Val, _value: Val) -> Result<(), Val> {
|
||||
Err("Cannot assign to subscript of array iterator".to_type_error())
|
||||
}
|
||||
|
||||
@@ -69,6 +69,13 @@ impl ValTrait for IterationResult {
|
||||
})
|
||||
}
|
||||
|
||||
fn has(&self, key: &Val) -> Option<bool> {
|
||||
Some(match key.to_string().as_str() {
|
||||
"value" | "done" => true,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: &Val, _value: Val) -> Result<(), Val> {
|
||||
Err("Cannot assign to subscript of iteration result".to_type_error())
|
||||
}
|
||||
|
||||
17
valuescript_vm/src/iteration/iterator_has.rs
Normal file
17
valuescript_vm/src/iteration/iterator_has.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use crate::{vs_value::Val, VsSymbol};
|
||||
|
||||
pub fn iterator_has(key: &Val) -> Option<bool> {
|
||||
if key.to_string() == "next" {
|
||||
return Some(true);
|
||||
}
|
||||
|
||||
if let Val::Symbol(key) = key {
|
||||
match key {
|
||||
VsSymbol::ITERATOR => {
|
||||
return Some(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(false)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod array_entries_iterator;
|
||||
pub mod array_iterator;
|
||||
pub mod iteration_result;
|
||||
mod iterator_has;
|
||||
pub mod return_this;
|
||||
pub mod string_iterator;
|
||||
|
||||
@@ -12,7 +12,9 @@ use crate::{
|
||||
LoadFunctionResult, ValTrait,
|
||||
};
|
||||
|
||||
use super::{iteration_result::IterationResult, return_this::RETURN_THIS};
|
||||
use super::{
|
||||
iteration_result::IterationResult, iterator_has::iterator_has, return_this::RETURN_THIS,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct StringIterator {
|
||||
@@ -123,6 +125,10 @@ impl ValTrait for StringIterator {
|
||||
Ok(Val::Undefined)
|
||||
}
|
||||
|
||||
fn has(&self, key: &Val) -> Option<bool> {
|
||||
iterator_has(key)
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: &Val, _value: Val) -> Result<(), Val> {
|
||||
Err("Cannot assign to subscript of string iterator".to_type_error())
|
||||
}
|
||||
|
||||
@@ -63,6 +63,10 @@ impl ValTrait for NativeFrameFunction {
|
||||
Err("TODO: Subscript native function".to_internal_error())
|
||||
}
|
||||
|
||||
fn has(&self, _key: &Val) -> Option<bool> {
|
||||
Some(false)
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: &Val, _value: Val) -> Result<(), Val> {
|
||||
Err("Cannot assign to subscript of native function".to_type_error())
|
||||
}
|
||||
|
||||
@@ -84,6 +84,10 @@ impl ValTrait for NativeFunction {
|
||||
Err("TODO: Subscript native function".to_internal_error())
|
||||
}
|
||||
|
||||
fn has(&self, _key: &Val) -> Option<bool> {
|
||||
Some(false)
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: &Val, _value: Val) -> Result<(), Val> {
|
||||
Err("Cannot assign to subscript of native function".to_type_error())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::mem::take;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -523,8 +522,11 @@ pub fn op_instance_of(_left: &Val, _right: &Val) -> Result<Val, Val> {
|
||||
Err("TODO: op_instance_of".to_internal_error())
|
||||
}
|
||||
|
||||
pub fn op_in(_left: &Val, _right: &Val) -> Result<Val, Val> {
|
||||
Err("TODO: op_in".to_internal_error())
|
||||
pub fn op_in(left: &Val, right: &Val) -> Result<Val, Val> {
|
||||
match right.has(left) {
|
||||
Some(found) => Ok(found.to_val()),
|
||||
None => Err(format!("Can't use `in` with a {}", right.typeof_()).to_type_error()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn op_sub(left: &mut Val, right: &Val) -> Result<Val, Val> {
|
||||
@@ -541,34 +543,7 @@ pub fn op_sub(left: &mut Val, right: &Val) -> Result<Val, Val> {
|
||||
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() {
|
||||
None => {
|
||||
// FIXME: Inefficient to_string() that gets duplicated
|
||||
// when subscripting the object
|
||||
if right.to_string() == "length" {
|
||||
return Ok(Val::Number(array_data.elements.len() as f64));
|
||||
}
|
||||
|
||||
return op_sub_array(array_data, right);
|
||||
}
|
||||
Some(i) => i,
|
||||
};
|
||||
|
||||
if right_index >= array_data.elements.len() {
|
||||
return Ok(Val::Undefined);
|
||||
}
|
||||
|
||||
let res = match Rc::get_mut(array_data) {
|
||||
Some(array_data) => take(&mut array_data.elements[right_index]),
|
||||
None => array_data.elements[right_index].clone(),
|
||||
};
|
||||
|
||||
return Ok(match res {
|
||||
Val::Void => Val::Undefined,
|
||||
_ => res,
|
||||
});
|
||||
}
|
||||
Val::Array(array_data) => op_sub_array(array_data, right),
|
||||
Val::Object(object_data) => Ok(object_data.sub(right)), // TODO: move on single ref
|
||||
Val::Function(_) => Ok(Val::Undefined),
|
||||
Val::Class(class) => op_sub(&mut class.static_.clone(), right),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use core::fmt;
|
||||
use std::any::Any;
|
||||
use std::fmt::Display;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -57,6 +58,24 @@ pub enum VsType {
|
||||
Class,
|
||||
}
|
||||
|
||||
impl Display for VsType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
VsType::Undefined => f.write_str("undefined"),
|
||||
VsType::Null => f.write_str("null"),
|
||||
VsType::Bool => f.write_str("bool"),
|
||||
VsType::Number => f.write_str("number"),
|
||||
VsType::BigInt => f.write_str("bigint"),
|
||||
VsType::Symbol => f.write_str("symbol"),
|
||||
VsType::String => f.write_str("string"),
|
||||
VsType::Array => f.write_str("array"),
|
||||
VsType::Object => f.write_str("object"),
|
||||
VsType::Function => f.write_str("function"),
|
||||
VsType::Class => f.write_str("class"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum LoadFunctionResult {
|
||||
NotAFunction,
|
||||
StackFrame(StackFrame),
|
||||
@@ -80,6 +99,7 @@ pub trait ValTrait: fmt::Display {
|
||||
fn load_function(&self) -> LoadFunctionResult;
|
||||
|
||||
fn sub(&self, key: &Val) -> Result<Val, Val>;
|
||||
fn has(&self, key: &Val) -> Option<bool>;
|
||||
fn submov(&mut self, key: &Val, value: Val) -> Result<(), Val>;
|
||||
|
||||
fn pretty_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
|
||||
@@ -355,6 +375,97 @@ impl ValTrait for Val {
|
||||
op_sub(&mut self.clone(), key)
|
||||
}
|
||||
|
||||
fn has(&self, key: &Val) -> Option<bool> {
|
||||
match self {
|
||||
Val::Void
|
||||
| Val::Undefined
|
||||
| Val::Null
|
||||
| Val::Bool(_)
|
||||
| Val::Number(_)
|
||||
| Val::BigInt(_)
|
||||
| Val::Symbol(_)
|
||||
| Val::String(_) => None,
|
||||
|
||||
Val::Array(array) => {
|
||||
let index = match key.to_index() {
|
||||
None => {
|
||||
return Some(match key.to_string().as_str() {
|
||||
"at" => true,
|
||||
"concat" => true,
|
||||
"copyWithin" => true,
|
||||
"entries" => true,
|
||||
"every" => true,
|
||||
"fill" => true,
|
||||
"filter" => true,
|
||||
"find" => true,
|
||||
"findIndex" => true,
|
||||
"flat" => true,
|
||||
"flatMap" => true,
|
||||
"includes" => true,
|
||||
"indexOf" => true,
|
||||
"join" => true,
|
||||
"keys" => true,
|
||||
"lastIndexOf" => true,
|
||||
"length" => true,
|
||||
"map" => true,
|
||||
"pop" => true,
|
||||
"push" => true,
|
||||
"reduce" => true,
|
||||
"reduceRight" => true,
|
||||
"reverse" => true,
|
||||
"shift" => true,
|
||||
"slice" => true,
|
||||
"some" => true,
|
||||
"sort" => true,
|
||||
"splice" => true,
|
||||
"toLocaleString" => true,
|
||||
"toString" => true,
|
||||
"unshift" => true,
|
||||
"values" => true,
|
||||
|
||||
_ => false,
|
||||
});
|
||||
}
|
||||
Some(i) => i,
|
||||
};
|
||||
|
||||
return Some(index < array.elements.len());
|
||||
}
|
||||
Val::Object(object) => match key {
|
||||
Val::Symbol(symbol) => {
|
||||
if object.symbol_map.contains_key(symbol) {
|
||||
return Some(true);
|
||||
}
|
||||
|
||||
if let Some(proto) = &object.prototype {
|
||||
return proto.has(key);
|
||||
}
|
||||
|
||||
return Some(false);
|
||||
}
|
||||
_ => {
|
||||
if object.string_map.contains_key(&key.to_string()) {
|
||||
return Some(true);
|
||||
}
|
||||
|
||||
if let Some(proto) = &object.prototype {
|
||||
return proto.has(key);
|
||||
}
|
||||
|
||||
return Some(false);
|
||||
}
|
||||
},
|
||||
Val::Function(_) => Some(false),
|
||||
Val::Class(class) => class.static_.has(key),
|
||||
Val::Static(static_) => static_.has(key),
|
||||
Val::Dynamic(dynamic) => dynamic.has(key),
|
||||
Val::CopyCounter(_) => Some(match key.to_string().as_str() {
|
||||
"tag" | "count" => true,
|
||||
_ => false,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn submov(&mut self, key: &Val, value: Val) -> Result<(), Val> {
|
||||
op_submov(self, key, value)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user