Remove Vallish, use refs and clones

This commit is contained in:
Andrew Morris
2023-06-21 17:16:03 +10:00
parent 53695d7948
commit b33ef2b5b0
14 changed files with 177 additions and 248 deletions

View File

@@ -13,7 +13,6 @@ use crate::vs_object::VsObject;
use crate::vs_symbol::VsSymbol;
use crate::vs_value::ToVal;
use crate::vs_value::Val;
use crate::Vallish;
#[derive(Clone)]
pub struct BytecodeDecoder {
@@ -97,74 +96,66 @@ impl BytecodeDecoder {
return BytecodeType::from_byte(self.peek_byte());
}
pub fn decode_vallish<'a>(&mut self, registers: &'a Vec<Val>) -> Vallish<'a> {
use Vallish::*;
pub fn decode_val(&mut self, registers: &Vec<Val>) -> Val {
return match self.decode_type() {
BytecodeType::End => panic!("Cannot decode end"),
BytecodeType::Void => Own(Val::Void),
BytecodeType::Undefined => Own(Val::Undefined),
BytecodeType::Null => Own(Val::Null),
BytecodeType::False => Own(Val::Bool(false)),
BytecodeType::True => Own(Val::Bool(true)),
BytecodeType::SignedByte => Own((self.decode_signed_byte() as f64).to_val()),
BytecodeType::Number => Own(self.decode_number().to_val()),
BytecodeType::String => Own(self.decode_string().to_val()),
BytecodeType::Array => Own(self.decode_vec_val(registers).to_val()),
BytecodeType::Void => Val::Void,
BytecodeType::Undefined => Val::Undefined,
BytecodeType::Null => Val::Null,
BytecodeType::False => Val::Bool(false),
BytecodeType::True => Val::Bool(true),
BytecodeType::SignedByte => (self.decode_signed_byte() as f64).to_val(),
BytecodeType::Number => self.decode_number().to_val(),
BytecodeType::String => self.decode_string().to_val(),
BytecodeType::Array => self.decode_vec_val(registers).to_val(),
BytecodeType::Object => {
let mut string_map: BTreeMap<String, Val> = BTreeMap::new();
let mut symbol_map: BTreeMap<VsSymbol, Val> = BTreeMap::new();
while self.peek_type() != BytecodeType::End {
let key = self.decode_vallish(registers);
let key = self.decode_val(registers);
let value = self.decode_val(registers);
match key.get_ref() {
match key {
Val::String(string) => string_map.insert(string.to_string(), value),
Val::Symbol(symbol) => symbol_map.insert(symbol.clone(), value),
Val::Symbol(symbol) => symbol_map.insert(symbol, value),
key => string_map.insert(key.to_string(), value),
};
}
self.decode_type(); // End (TODO: assert)
Own(
VsObject {
string_map,
symbol_map,
prototype: None,
}
.to_val(),
)
}
BytecodeType::Function => Own(self.decode_function(false)),
BytecodeType::Pointer => Own(self.decode_pointer(registers)),
BytecodeType::Register => match registers[self.decode_register_index().unwrap()] {
Val::Void => Own(Val::Undefined),
ref val => Ref(val),
},
BytecodeType::TakeRegister => match registers[self.decode_register_index().unwrap()] {
Val::Void => Own(Val::Undefined),
ref val => Ref(val),
},
BytecodeType::Builtin => Own(BUILTIN_VALS[self.decode_varsize_uint()]()),
BytecodeType::Class => Own(
VsClass {
constructor: self.decode_val(registers),
instance_prototype: self.decode_val(registers),
VsObject {
string_map,
symbol_map,
prototype: None,
}
.to_val(),
),
BytecodeType::BigInt => Own(self.decode_bigint().to_val()),
BytecodeType::GeneratorFunction => Own(self.decode_function(true)),
.to_val()
}
BytecodeType::Function => self.decode_function(false),
BytecodeType::Pointer => self.decode_pointer(registers),
BytecodeType::Register => match registers[self.decode_register_index().unwrap()].clone() {
Val::Void => Val::Undefined,
val => val,
},
BytecodeType::TakeRegister => {
match registers[self.decode_register_index().unwrap()].clone() {
Val::Void => Val::Undefined,
val => val,
}
}
BytecodeType::Builtin => BUILTIN_VALS[self.decode_varsize_uint()](),
BytecodeType::Class => VsClass {
constructor: self.decode_val(registers),
instance_prototype: self.decode_val(registers),
}
.to_val(),
BytecodeType::BigInt => self.decode_bigint().to_val(),
BytecodeType::GeneratorFunction => self.decode_function(true),
BytecodeType::Unrecognized => panic!("Unrecognized bytecode type at {}", self.pos - 1),
};
}
pub fn decode_val(&mut self, registers: &Vec<Val>) -> Val {
return self.decode_vallish(registers).get_own();
}
pub fn decode_vec_val(&mut self, registers: &Vec<Val>) -> Vec<Val> {
let mut vals: Vec<Val> = Vec::new();

View File

@@ -11,7 +11,6 @@ use crate::operations;
use crate::stack_frame::FrameStepOk;
use crate::stack_frame::FrameStepResult;
use crate::stack_frame::{CallResult, StackFrame, StackFrameTrait};
use crate::vallish::Vallish;
use crate::vs_object::VsObject;
use crate::vs_value::ToVal;
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
@@ -36,26 +35,24 @@ pub struct CatchSetting {
impl BytecodeStackFrame {
pub fn apply_unary_op(&mut self, op: fn(input: &Val) -> Val) {
let input = self.decoder.decode_vallish(&self.registers);
let input = self.decoder.decode_val(&self.registers);
let register_index = self.decoder.decode_register_index();
if register_index.is_some() {
self.registers[register_index.unwrap()] = op(input.get_ref());
self.registers[register_index.unwrap()] = op(&input);
}
}
pub fn apply_binary_op(
&mut self,
op: fn(left: Vallish, right: Vallish) -> Result<Val, Val>,
op: fn(left: &Val, right: &Val) -> Result<Val, Val>,
) -> Result<(), Val> {
let left = self.decoder.decode_vallish(&self.registers);
let right = self.decoder.decode_vallish(&self.registers);
let left = self.decoder.decode_val(&self.registers);
let right = self.decoder.decode_val(&self.registers);
let register_index = self.decoder.decode_register_index();
if register_index.is_some() {
self.registers[register_index.unwrap()] = op(left, right)?;
if let Some(register_index) = self.decoder.decode_register_index() {
self.registers[register_index] = op(&left, &right)?;
}
Ok(())
@@ -158,7 +155,7 @@ impl StackFrameTrait for BytecodeStackFrame {
match val {
Val::Number(n) => *n += 1.0,
Val::BigInt(bi) => *bi += 1,
_ => *val = operations::op_plus(Vallish::Ref(val), Vallish::Own(1.0.to_val()))?,
_ => *val = operations::op_plus(val, &1.0.to_val())?,
};
}
@@ -169,7 +166,7 @@ impl StackFrameTrait for BytecodeStackFrame {
match val {
Val::Number(n) => *n -= 1.0,
Val::BigInt(bi) => *bi -= 1,
_ => *val = operations::op_minus(Vallish::Ref(val), Vallish::Own(1.0.to_val()))?,
_ => *val = operations::op_minus(val, &1.0.to_val())?,
};
}
@@ -193,7 +190,14 @@ impl StackFrameTrait for BytecodeStackFrame {
OpGreater => self.apply_binary_op(operations::op_greater)?,
OpGreaterEq => self.apply_binary_op(operations::op_greater_eq)?,
OpNullishCoalesce => self.apply_binary_op(operations::op_nullish_coalesce)?,
OpOptionalChain => self.apply_binary_op(operations::op_optional_chain)?,
OpOptionalChain => {
let mut left = self.decoder.decode_val(&self.registers);
let right = self.decoder.decode_val(&self.registers);
if let Some(register_index) = self.decoder.decode_register_index() {
self.registers[register_index] = operations::op_optional_chain(&mut left, &right)?;
}
}
OpBitAnd => self.apply_binary_op(operations::op_bit_and)?,
OpBitOr => self.apply_binary_op(operations::op_bit_or)?,
@@ -299,7 +303,14 @@ impl StackFrameTrait for BytecodeStackFrame {
}
}
Sub => self.apply_binary_op(operations::op_sub)?,
Sub => {
let mut left = self.decoder.decode_val(&self.registers);
let right = self.decoder.decode_val(&self.registers);
if let Some(register_index) = self.decoder.decode_register_index() {
self.registers[register_index] = operations::op_sub(&mut left, &right)?;
}
}
SubMov => {
// TODO: Ideally we would use a reference for the subscript (decode_vallish), but that would
@@ -329,11 +340,11 @@ impl StackFrameTrait for BytecodeStackFrame {
_ => ThisArg::Val(self.decoder.decode_val(&self.registers)),
};
let subscript = self.decoder.decode_vallish(&self.registers);
let subscript = self.decoder.decode_val(&self.registers);
let fn_ = match &obj {
ThisArg::Register(reg_i) => self.registers[reg_i.clone()].sub(subscript.get_ref())?,
ThisArg::Val(val) => val.sub(subscript.get_ref())?,
ThisArg::Register(reg_i) => self.registers[*reg_i].sub(&subscript)?,
ThisArg::Val(val) => val.sub(&subscript)?,
};
match fn_.load_function() {

View File

@@ -5,7 +5,6 @@ use crate::{
native_function::ThisWrapper,
operations::op_sub,
stack_frame::{CallResult, FrameStepOk, FrameStepResult, StackFrame, StackFrameTrait},
vallish::Vallish,
vs_symbol::VsSymbol,
vs_value::{ToVal, Val},
LoadFunctionResult, ValTrait,
@@ -64,10 +63,7 @@ impl CatStackFrame {
return Ok(FrameStepOk::Continue);
}
let make_iter = op_sub(
Vallish::Ref(&arg),
Vallish::Own(VsSymbol::ITERATOR.to_val()),
)?;
let make_iter = op_sub(&mut arg, &VsSymbol::ITERATOR.to_val())?;
match make_iter.load_function() {
LoadFunctionResult::NotAFunction => Err("Non-iterable cat argument".to_type_error()),

View File

@@ -18,7 +18,6 @@ pub mod operations;
mod stack_frame;
mod string_methods;
mod todo_fn;
mod vallish;
mod virtual_machine;
pub mod vs_array;
mod vs_class;
@@ -28,6 +27,5 @@ mod vs_symbol;
pub mod vs_value;
pub use bytecode::Bytecode;
pub use vallish::Vallish;
pub use virtual_machine::VirtualMachine;
pub use vs_value::{LoadFunctionResult, ValTrait};

View File

@@ -1,3 +1,4 @@
use std::mem::take;
use std::rc::Rc;
use num_bigint::Sign;
@@ -11,15 +12,14 @@ use crate::native_function::native_fn;
use crate::native_function::NativeFunction;
use crate::number_methods::op_sub_number;
use crate::string_methods::op_sub_string;
use crate::vallish::Vallish;
use crate::vs_value::ToVal;
use crate::vs_value::Val;
use crate::vs_value::ValTrait;
use crate::vs_value::VsType;
pub fn op_plus(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_prim = left.get_ref().to_primitive();
let right_prim = right.get_ref().to_primitive();
pub fn op_plus(left: &Val, right: &Val) -> Result<Val, Val> {
let left_prim = left.to_primitive();
let right_prim = right.to_primitive();
let left_type = left_prim.typeof_();
let right_type = right_prim.typeof_();
@@ -51,16 +51,13 @@ pub fn op_unary_plus(input: &Val) -> Val {
}
}
pub fn op_minus(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
match (left_ref.as_bigint_data(), right_ref.as_bigint_data()) {
pub fn op_minus(left: &Val, right: &Val) -> Result<Val, Val> {
match (left.as_bigint_data(), right.as_bigint_data()) {
(Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint - right_bigint)),
(Some(_), None) | (None, Some(_)) => {
return Err("Cannot mix BigInt with other types".to_type_error())
}
_ => Ok(Val::Number(left_ref.to_number() - right_ref.to_number())),
_ => Ok(Val::Number(left.to_number() - right.to_number())),
}
}
@@ -71,44 +68,32 @@ pub fn op_unary_minus(input: &Val) -> Val {
}
}
pub fn op_mul(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
match (left_ref.as_bigint_data(), right_ref.as_bigint_data()) {
pub fn op_mul(left: &Val, right: &Val) -> Result<Val, Val> {
match (left.as_bigint_data(), right.as_bigint_data()) {
(Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint * right_bigint)),
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
_ => Ok(Val::Number(left_ref.to_number() * right_ref.to_number())),
_ => Ok(Val::Number(left.to_number() * right.to_number())),
}
}
pub fn op_div(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
match (left_ref.as_bigint_data(), right_ref.as_bigint_data()) {
pub fn op_div(left: &Val, right: &Val) -> Result<Val, Val> {
match (left.as_bigint_data(), right.as_bigint_data()) {
(Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint / right_bigint)),
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
_ => Ok(Val::Number(left_ref.to_number() / right_ref.to_number())),
_ => Ok(Val::Number(left.to_number() / right.to_number())),
}
}
pub fn op_mod(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
match (left_ref.as_bigint_data(), right_ref.as_bigint_data()) {
pub fn op_mod(left: &Val, right: &Val) -> Result<Val, Val> {
match (left.as_bigint_data(), right.as_bigint_data()) {
(Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint % right_bigint)),
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
_ => Ok(Val::Number(left_ref.to_number() % right_ref.to_number())),
_ => Ok(Val::Number(left.to_number() % right.to_number())),
}
}
pub fn op_exp(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
match (left_ref.as_bigint_data(), right_ref.as_bigint_data()) {
pub fn op_exp(left: &Val, right: &Val) -> Result<Val, Val> {
match (left.as_bigint_data(), right.as_bigint_data()) {
(Some(left_bigint), Some(right_bigint)) => {
if right_bigint.sign() == Sign::Minus {
return Err("Exponent must be non-negative".to_range_error());
@@ -122,15 +107,13 @@ pub fn op_exp(left: Vallish, right: Vallish) -> Result<Val, Val> {
Ok(Val::BigInt(left_bigint.pow(exp)))
}
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
_ => Ok(Val::Number(
left_ref.to_number().powf(right_ref.to_number()),
)),
_ => Ok(Val::Number(left.to_number().powf(right.to_number()))),
}
}
pub fn op_eq_impl(left: Vallish, right: Vallish) -> Result<bool, Val> {
Ok(match (left.get_ref(), right.get_ref()) {
(left_ref, Val::Undefined | Val::Null) => match left_ref {
pub fn op_eq_impl(left: &Val, right: &Val) -> Result<bool, Val> {
Ok(match (left, right) {
(left, Val::Undefined | Val::Null) => match left {
Val::Undefined | Val::Null => true,
_ => false,
},
@@ -142,19 +125,16 @@ pub fn op_eq_impl(left: Vallish, right: Vallish) -> Result<bool, Val> {
})
}
pub fn op_eq(left: Vallish, right: Vallish) -> Result<Val, Val> {
pub fn op_eq(left: &Val, right: &Val) -> Result<Val, Val> {
Ok(Val::Bool(op_eq_impl(left, right)?))
}
pub fn op_ne(left: Vallish, right: Vallish) -> Result<Val, Val> {
pub fn op_ne(left: &Val, right: &Val) -> Result<Val, Val> {
Ok(Val::Bool(!op_eq_impl(left, right)?))
}
pub fn op_triple_eq_impl(left: Vallish, right: Vallish) -> Result<bool, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
Ok(match (left_ref, right_ref) {
pub fn op_triple_eq_impl(left: &Val, right: &Val) -> Result<bool, Val> {
Ok(match (left, right) {
(Val::Undefined, Val::Undefined) => true,
(Val::Null, Val::Null) => true,
(Val::Bool(left_bool), Val::Bool(right_bool)) => left_bool == right_bool,
@@ -162,7 +142,7 @@ pub fn op_triple_eq_impl(left: Vallish, right: Vallish) -> Result<bool, Val> {
(Val::String(left_string), Val::String(right_string)) => left_string == right_string,
(Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint == right_bigint,
_ => {
if left_ref.typeof_() != right_ref.typeof_() {
if left.typeof_() != right.typeof_() {
false
} else {
return Err("TODO".to_error());
@@ -171,37 +151,34 @@ pub fn op_triple_eq_impl(left: Vallish, right: Vallish) -> Result<bool, Val> {
})
}
pub fn op_triple_eq(left: Vallish, right: Vallish) -> Result<Val, Val> {
pub fn op_triple_eq(left: &Val, right: &Val) -> Result<Val, Val> {
let is_eq = op_triple_eq_impl(left, right)?;
Ok(Val::Bool(is_eq))
}
pub fn op_triple_ne(left: Vallish, right: Vallish) -> Result<Val, Val> {
pub fn op_triple_ne(left: &Val, right: &Val) -> Result<Val, Val> {
let is_eq = op_triple_eq_impl(left, right)?;
Ok(Val::Bool(!is_eq))
}
pub fn op_and(left: Vallish, right: Vallish) -> Result<Val, Val> {
let truthy = left.get_ref().is_truthy();
pub fn op_and(left: &Val, right: &Val) -> Result<Val, Val> {
let truthy = left.is_truthy();
Ok((if truthy { right } else { left }).get_own())
Ok((if truthy { right } else { left }).clone())
}
pub fn op_or(left: Vallish, right: Vallish) -> Result<Val, Val> {
let truthy = left.get_ref().is_truthy();
pub fn op_or(left: &Val, right: &Val) -> Result<Val, Val> {
let truthy = left.is_truthy();
Ok((if truthy { left } else { right }).get_own())
Ok((if truthy { left } else { right }).clone())
}
pub fn op_not(input: &Val) -> Val {
return Val::Bool(!input.is_truthy());
}
pub fn op_less(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
Ok(Val::Bool(match (left_ref, right_ref) {
pub fn op_less(left: &Val, right: &Val) -> Result<Val, Val> {
Ok(Val::Bool(match (left, right) {
(Val::Undefined, Val::Undefined) => false,
(Val::Null, Val::Null) => false,
(Val::Bool(left_bool), Val::Bool(right_bool)) => left_bool < right_bool,
@@ -209,7 +186,7 @@ pub fn op_less(left: Vallish, right: Vallish) -> Result<Val, Val> {
(Val::String(left_string), Val::String(right_string)) => left_string < right_string,
(Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint < right_bigint,
_ => {
if left_ref.typeof_() == VsType::Undefined || right_ref.typeof_() == VsType::Undefined {
if left.typeof_() == VsType::Undefined || right.typeof_() == VsType::Undefined {
false
} else {
return Err("TODO".to_error());
@@ -218,8 +195,8 @@ pub fn op_less(left: Vallish, right: Vallish) -> Result<Val, Val> {
}))
}
pub fn op_less_eq(left: Vallish, right: Vallish) -> Result<Val, Val> {
Ok(Val::Bool(match (left.get_ref(), right.get_ref()) {
pub fn op_less_eq(left: &Val, right: &Val) -> Result<Val, Val> {
Ok(Val::Bool(match (left, right) {
(Val::Undefined, Val::Undefined) => false,
(Val::Null, Val::Null) => true,
(Val::Bool(left_bool), Val::Bool(right_bool)) => left_bool <= right_bool,
@@ -230,8 +207,8 @@ pub fn op_less_eq(left: Vallish, right: Vallish) -> Result<Val, Val> {
}))
}
pub fn op_greater(left: Vallish, right: Vallish) -> Result<Val, Val> {
Ok(Val::Bool(match (left.get_ref(), right.get_ref()) {
pub fn op_greater(left: &Val, right: &Val) -> Result<Val, Val> {
Ok(Val::Bool(match (left, right) {
(Val::Undefined, Val::Undefined) => false,
(Val::Null, Val::Null) => false,
(Val::Bool(left_bool), Val::Bool(right_bool)) => left_bool > right_bool,
@@ -242,8 +219,8 @@ pub fn op_greater(left: Vallish, right: Vallish) -> Result<Val, Val> {
}))
}
pub fn op_greater_eq(left: Vallish, right: Vallish) -> Result<Val, Val> {
Ok(Val::Bool(match (left.get_ref(), right.get_ref()) {
pub fn op_greater_eq(left: &Val, right: &Val) -> Result<Val, Val> {
Ok(Val::Bool(match (left, right) {
(Val::Undefined, Val::Undefined) => false,
(Val::Null, Val::Null) => true,
(Val::Bool(left_bool), Val::Bool(right_bool)) => left_bool >= right_bool,
@@ -254,14 +231,14 @@ pub fn op_greater_eq(left: Vallish, right: Vallish) -> Result<Val, Val> {
}))
}
pub fn op_nullish_coalesce(left: Vallish, right: Vallish) -> Result<Val, Val> {
let nullish = left.get_ref().is_nullish();
pub fn op_nullish_coalesce(left: &Val, right: &Val) -> Result<Val, Val> {
let nullish = left.is_nullish();
Ok((if nullish { right } else { left }).get_own())
Ok((if nullish { right } else { left }).clone())
}
pub fn op_optional_chain(left: Vallish, right: Vallish) -> Result<Val, Val> {
return match left.get_ref() {
pub fn op_optional_chain(left: &mut Val, right: &Val) -> Result<Val, Val> {
return match left {
Val::Undefined | Val::Null => Ok(Val::Undefined),
_ => op_sub(left, right),
@@ -288,29 +265,23 @@ pub fn to_u32(x: f64) -> u32 {
return int1 as u32;
}
pub fn op_bit_and(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
match (left_ref.as_bigint_data(), right_ref.as_bigint_data()) {
pub fn op_bit_and(left: &Val, right: &Val) -> Result<Val, Val> {
match (left.as_bigint_data(), right.as_bigint_data()) {
(Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint & right_bigint)),
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
_ => {
let res_i32 = to_i32(left_ref.to_number()) & to_i32(right_ref.to_number());
let res_i32 = to_i32(left.to_number()) & to_i32(right.to_number());
Ok(Val::Number(res_i32 as f64))
}
}
}
pub fn op_bit_or(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
match (left_ref.as_bigint_data(), right_ref.as_bigint_data()) {
pub fn op_bit_or(left: &Val, right: &Val) -> Result<Val, Val> {
match (left.as_bigint_data(), right.as_bigint_data()) {
(Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint | right_bigint)),
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
_ => {
let res_i32 = to_i32(left_ref.to_number()) | to_i32(right_ref.to_number());
let res_i32 = to_i32(left.to_number()) | to_i32(right.to_number());
Ok(Val::Number(res_i32 as f64))
}
}
@@ -326,62 +297,50 @@ pub fn op_bit_not(input: &Val) -> Val {
}
}
pub fn op_bit_xor(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
match (left_ref.as_bigint_data(), right_ref.as_bigint_data()) {
pub fn op_bit_xor(left: &Val, right: &Val) -> Result<Val, Val> {
match (left.as_bigint_data(), right.as_bigint_data()) {
(Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint ^ right_bigint)),
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
_ => {
let res_i32 = to_i32(left_ref.to_number()) ^ to_i32(right_ref.to_number());
let res_i32 = to_i32(left.to_number()) ^ to_i32(right.to_number());
Ok(Val::Number(res_i32 as f64))
}
}
}
pub fn op_left_shift(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
match (left_ref.as_bigint_data(), right_ref.as_bigint_data()) {
pub fn op_left_shift(left: &Val, right: &Val) -> Result<Val, Val> {
match (left.as_bigint_data(), right.as_bigint_data()) {
(Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(
left_bigint << right_bigint.to_i64().expect("TODO"),
)),
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
_ => {
let res_i32 = to_i32(left_ref.to_number()) << (to_u32(right_ref.to_number()) & 0x1f);
let res_i32 = to_i32(left.to_number()) << (to_u32(right.to_number()) & 0x1f);
Ok(Val::Number(res_i32 as f64))
}
}
}
pub fn op_right_shift(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
match (left_ref.as_bigint_data(), right_ref.as_bigint_data()) {
pub fn op_right_shift(left: &Val, right: &Val) -> Result<Val, Val> {
match (left.as_bigint_data(), right.as_bigint_data()) {
(Some(left_bigint), Some(right_bigint)) => {
let right_i64 = right_bigint.to_i64().ok_or("TODO".to_val())?;
Ok(Val::BigInt(left_bigint >> right_i64))
}
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
_ => {
let res_i32 = to_i32(left_ref.to_number()) >> (to_u32(right_ref.to_number()) & 0x1f);
let res_i32 = to_i32(left.to_number()) >> (to_u32(right.to_number()) & 0x1f);
Ok(Val::Number(res_i32 as f64))
}
}
}
pub fn op_right_shift_unsigned(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref();
let right_ref = right.get_ref();
match (left_ref.as_bigint_data(), right_ref.as_bigint_data()) {
pub fn op_right_shift_unsigned(left: &Val, right: &Val) -> Result<Val, Val> {
match (left.as_bigint_data(), right.as_bigint_data()) {
(Some(_), Some(_)) => Err("BigInts don't support unsigned right shift".to_type_error()),
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
_ => {
let res_u32 = to_u32(left_ref.to_number()) >> (to_u32(right_ref.to_number()) & 0x1f);
let res_u32 = to_u32(left.to_number()) >> (to_u32(right.to_number()) & 0x1f);
Ok(Val::Number(res_u32 as f64))
}
}
@@ -406,41 +365,38 @@ pub fn op_typeof(input: &Val) -> Val {
.to_val()
}
pub fn op_instance_of(_left: Vallish, _right: Vallish) -> Result<Val, Val> {
pub fn op_instance_of(_left: &Val, _right: &Val) -> Result<Val, Val> {
Err("TODO: op_instance_of".to_error())
}
pub fn op_in(_left: Vallish, _right: Vallish) -> Result<Val, Val> {
pub fn op_in(_left: &Val, _right: &Val) -> Result<Val, Val> {
Err("TODO: op_in".to_error())
}
pub fn op_sub(left: Vallish, right: Vallish) -> Result<Val, Val> {
let left_ref = left.get_ref(); // TODO: Specialize on Vallish::Own (esp array, object)
let right_ref = right.get_ref();
match left_ref {
pub fn op_sub(left: &mut Val, right: &Val) -> Result<Val, Val> {
match left {
Val::Void => Err("Internal: Shouldn't happen".to_error()), // TODO: Internal errors
Val::Undefined => Err("Cannot subscript undefined".to_type_error()),
Val::Null => Err("Cannot subscript null".to_type_error()),
Val::Bool(_) => Ok(match right_ref.to_string().as_str() {
Val::Bool(_) => Ok(match right.to_string().as_str() {
"toString" => BOOL_TO_STRING.to_val(),
"valueOf" => BOOL_VALUE_OF.to_val(),
_ => Val::Undefined,
}),
Val::Number(number) => Ok(op_sub_number(*number, right_ref)),
Val::BigInt(bigint) => Ok(op_sub_bigint(bigint, right_ref)),
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_ref)),
Val::String(string_data) => Ok(op_sub_string(string_data, right)),
Val::Array(array_data) => {
let right_index = match right_ref.to_index() {
let right_index = match right.to_index() {
None => {
// FIXME: Inefficient to_string() that gets duplicated
// when subscripting the object
if right_ref.to_string() == "length" {
if right.to_string() == "length" {
return Ok(Val::Number(array_data.elements.len() as f64));
}
return Ok(array_data.object.sub(right_ref));
return Ok(array_data.object.sub(right));
}
Some(i) => i,
};
@@ -449,18 +405,21 @@ pub fn op_sub(left: Vallish, right: Vallish) -> Result<Val, Val> {
return Ok(Val::Undefined);
}
let res = array_data.elements[right_index].clone();
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::Object(object_data) => Ok(object_data.sub(right_ref)),
Val::Object(object_data) => Ok(object_data.sub(right)), // TODO: move on single ref
Val::Function(_) | Val::Class(_) => Ok(Val::Undefined),
Val::Static(s) => s.sub(right_ref),
Val::Dynamic(dynamic_data) => dynamic_data.sub(right_ref),
Val::CopyCounter(cc) => Ok(match right_ref.to_string().as_str() {
Val::Static(s) => s.sub(right),
Val::Dynamic(dynamic_data) => dynamic_data.sub(right),
Val::CopyCounter(cc) => Ok(match right.to_string().as_str() {
"tag" => cc.tag.clone(),
"count" => (*cc.count.borrow() as f64).to_val(),
_ => Val::Undefined,

View File

@@ -1,22 +0,0 @@
use crate::vs_value::Val;
pub enum Vallish<'a> {
Own(Val),
Ref(&'a Val),
}
impl<'a> Vallish<'a> {
pub fn get_own(self) -> Val {
match self {
Vallish::Own(val) => val,
Vallish::Ref(val) => val.clone(),
}
}
pub fn get_ref(&self) -> &Val {
match self {
Vallish::Own(val) => val,
Vallish::Ref(val) => val,
}
}
}

View File

@@ -17,7 +17,6 @@ use crate::iteration::array_iterator::ArrayIterator;
use crate::native_function::{native_fn, NativeFunction};
use crate::operations::op_triple_eq_impl;
use crate::todo_fn::TODO;
use crate::vallish::Vallish;
use crate::vs_class::VsClass;
use crate::vs_object::VsObject;
use crate::vs_symbol::VsSymbol;
@@ -343,7 +342,7 @@ static INCLUDES: NativeFunction = native_fn(|this, params| {
let search_param = params.get(0).unwrap_or(&Val::Undefined);
for elem in &array_data.elements {
let is_eq = op_triple_eq_impl(Vallish::Ref(elem), Vallish::Ref(search_param))
let is_eq = op_triple_eq_impl(elem, search_param)
.map_err(|e| e.to_string())
.unwrap(); // TODO: Exception
@@ -364,12 +363,9 @@ static INDEX_OF: NativeFunction = native_fn(|this, params| {
let search_param = params.get(0).unwrap_or(&Val::Undefined);
for i in 0..array_data.elements.len() {
let is_eq = op_triple_eq_impl(
Vallish::Ref(&array_data.elements[i]),
Vallish::Ref(search_param),
)
.map_err(|e| e.to_string())
.unwrap(); // TODO: Exception
let is_eq = op_triple_eq_impl(&array_data.elements[i], search_param)
.map_err(|e| e.to_string())
.unwrap(); // TODO: Exception
if is_eq {
return Ok(Val::Number(i as f64));
@@ -424,12 +420,9 @@ static LAST_INDEX_OF: NativeFunction = native_fn(|this, params| {
let search_param = params.get(0).unwrap_or(&Val::Undefined);
for i in (0..array_data.elements.len()).rev() {
let is_eq = op_triple_eq_impl(
Vallish::Ref(&array_data.elements[i]),
Vallish::Ref(search_param),
)
.map_err(|e| e.to_string())
.unwrap(); // TODO: Exception
let is_eq = op_triple_eq_impl(&array_data.elements[i], search_param)
.map_err(|e| e.to_string())
.unwrap(); // TODO: Exception
if is_eq {
return Ok(Val::Number(i as f64));

View File

@@ -11,7 +11,6 @@ use crate::copy_counter::CopyCounter;
use crate::native_function::ThisWrapper;
use crate::operations::{op_sub, op_submov};
use crate::stack_frame::StackFrame;
use crate::vallish::Vallish;
use crate::vs_array::VsArray;
use crate::vs_class::VsClass;
use crate::vs_function::VsFunction;
@@ -352,8 +351,8 @@ impl ValTrait for Val {
}
fn sub(&self, key: &Val) -> Result<Val, Val> {
// TODO: Avoid indirection?
op_sub(Vallish::Ref(self), Vallish::Ref(key))
// TODO: mut version?
op_sub(&mut self.clone(), key)
}
fn submov(&mut self, key: &Val, value: Val) -> Result<(), Val> {