mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-01-14 16:08:02 -05:00
to_val refactor, remove error macros
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
use std::rc::Rc;
|
||||
use crate::vs_value::ToVal;
|
||||
|
||||
use super::super::vs_value::{Val, ValTrait};
|
||||
use super::super::vs_array::VsArray;
|
||||
use super::super::native_frame_function::NativeFrameFunction;
|
||||
use super::array_mapping_frame::{ArrayMappingState, ArrayMappingFrame};
|
||||
use super::super::vs_value::{Val, ValTrait};
|
||||
use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState};
|
||||
|
||||
pub static FILTER: NativeFrameFunction = NativeFrameFunction {
|
||||
make_frame: || Box::new(ArrayMappingFrame::new(Box::new(FilterState::default()))),
|
||||
@@ -26,6 +25,6 @@ impl ArrayMappingState for FilterState {
|
||||
fn finish(&mut self) -> Val {
|
||||
let mut filter_results = Vec::new();
|
||||
std::mem::swap(&mut self.filter_results, &mut filter_results);
|
||||
return Val::Array(Rc::new(VsArray::from(filter_results)));
|
||||
filter_results.to_val()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use std::rc::Rc;
|
||||
use crate::vs_value::ToVal;
|
||||
|
||||
use super::super::vs_value::{Val, ValTrait};
|
||||
use super::super::vs_array::VsArray;
|
||||
use super::super::native_frame_function::NativeFrameFunction;
|
||||
use super::array_mapping_frame::{ArrayMappingState, ArrayMappingFrame};
|
||||
use super::super::vs_value::{Val, ValTrait};
|
||||
use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState};
|
||||
|
||||
pub static FLAT_MAP: NativeFrameFunction = NativeFrameFunction {
|
||||
make_frame: || Box::new(ArrayMappingFrame::new(Box::new(FlatMapState::default()))),
|
||||
@@ -31,6 +30,6 @@ impl ArrayMappingState for FlatMapState {
|
||||
fn finish(&mut self) -> Val {
|
||||
let mut flat_map_results = Vec::new();
|
||||
std::mem::swap(&mut self.flat_map_results, &mut flat_map_results);
|
||||
return Val::Array(Rc::new(VsArray::from(flat_map_results)));
|
||||
flat_map_results.to_val()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use std::rc::Rc;
|
||||
use crate::vs_value::ToVal;
|
||||
|
||||
use super::super::vs_value::{Val};
|
||||
use super::super::vs_array::VsArray;
|
||||
use super::super::native_frame_function::NativeFrameFunction;
|
||||
use super::array_mapping_frame::{ArrayMappingState, ArrayMappingFrame};
|
||||
use super::super::vs_value::Val;
|
||||
use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState};
|
||||
|
||||
pub static MAP: NativeFrameFunction = NativeFrameFunction {
|
||||
make_frame: || Box::new(ArrayMappingFrame::new(Box::new(MapState::default()))),
|
||||
@@ -23,6 +22,6 @@ impl ArrayMappingState for MapState {
|
||||
fn finish(&mut self) -> Val {
|
||||
let mut map_results = Vec::new();
|
||||
std::mem::swap(&mut self.map_results, &mut map_results);
|
||||
return Val::Array(Rc::new(VsArray::from(map_results)));
|
||||
map_results.to_val()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::builtins::type_error_builtin::ToTypeError;
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::stack_frame::FrameStepResult;
|
||||
use crate::stack_frame::{CallResult, FrameStepOk, StackFrameTrait};
|
||||
use crate::vs_array::VsArray;
|
||||
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
|
||||
pub trait ArrayMappingState {
|
||||
fn process(&mut self, i: usize, element: &Val, mapped: Val) -> Option<Val>;
|
||||
@@ -60,7 +60,7 @@ impl StackFrameTrait for ArrayMappingFrame {
|
||||
|
||||
fn step(&mut self) -> FrameStepResult {
|
||||
let array_data = match &self.this {
|
||||
None => return type_error!("Array fn called on non-array"),
|
||||
None => return Err("Array fn called on non-array".to_type_error()),
|
||||
Some(ad) => ad,
|
||||
};
|
||||
|
||||
@@ -80,9 +80,7 @@ impl StackFrameTrait for ArrayMappingFrame {
|
||||
Some(el) => match el {
|
||||
Val::Void => Ok(FrameStepOk::Continue),
|
||||
_ => match self.mapper.load_function() {
|
||||
LoadFunctionResult::NotAFunction => {
|
||||
type_error!("map fn is not a function")
|
||||
}
|
||||
LoadFunctionResult::NotAFunction => Err("map fn is not a function".to_type_error()),
|
||||
LoadFunctionResult::NativeFunction(native_fn) => {
|
||||
match self.state.process(
|
||||
array_i,
|
||||
@@ -124,7 +122,7 @@ impl StackFrameTrait for ArrayMappingFrame {
|
||||
|
||||
let element = match &self.this {
|
||||
None => {
|
||||
self.early_exit = Some(type_error!("Array fn called on non-array"));
|
||||
self.early_exit = Some(Err("Array fn called on non-array".to_type_error()));
|
||||
return;
|
||||
}
|
||||
Some(ad) => &ad.elements[array_i],
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::builtins::type_error_builtin::ToTypeError;
|
||||
use crate::native_frame_function::NativeFrameFunction;
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::stack_frame::{CallResult, FrameStepOk, FrameStepResult, StackFrameTrait};
|
||||
use crate::vs_array::VsArray;
|
||||
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
|
||||
pub static REDUCE: NativeFrameFunction = NativeFrameFunction {
|
||||
make_frame: || {
|
||||
@@ -50,7 +50,7 @@ impl StackFrameTrait for ReduceFrame {
|
||||
|
||||
fn step(&mut self) -> FrameStepResult {
|
||||
let array_data = match &self.this {
|
||||
None => return type_error!("reduce called on non-array"),
|
||||
None => return Err("reduce called on non-array".to_type_error()),
|
||||
Some(ad) => ad,
|
||||
};
|
||||
|
||||
@@ -66,7 +66,9 @@ impl StackFrameTrait for ReduceFrame {
|
||||
FrameStepOk::Continue
|
||||
}
|
||||
Some(value) => match self.reducer.load_function() {
|
||||
LoadFunctionResult::NotAFunction => return type_error!("reduce fn is not a function"),
|
||||
LoadFunctionResult::NotAFunction => {
|
||||
return Err("reduce fn is not a function".to_type_error())
|
||||
}
|
||||
LoadFunctionResult::NativeFunction(native_fn) => {
|
||||
self.value = Some(native_fn(
|
||||
ThisWrapper::new(true, &mut Val::Undefined),
|
||||
@@ -91,7 +93,7 @@ impl StackFrameTrait for ReduceFrame {
|
||||
},
|
||||
},
|
||||
None => match &self.value {
|
||||
None => return type_error!("reduce of empty array with no initial value"),
|
||||
None => return Err("reduce of empty array with no initial value".to_type_error()),
|
||||
Some(value) => FrameStepOk::Pop(CallResult {
|
||||
return_: value.clone(),
|
||||
this: Val::Array(array_data.clone()),
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::builtins::type_error_builtin::ToTypeError;
|
||||
use crate::native_frame_function::NativeFrameFunction;
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::stack_frame::{CallResult, FrameStepOk, FrameStepResult, StackFrameTrait};
|
||||
use crate::vs_array::VsArray;
|
||||
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
|
||||
use crate::{builtins::type_error_builtin::to_type_error, format_err, type_error};
|
||||
|
||||
pub static REDUCE_RIGHT: NativeFrameFunction = NativeFrameFunction {
|
||||
make_frame: || {
|
||||
@@ -56,14 +56,14 @@ impl StackFrameTrait for ReduceRightFrame {
|
||||
|
||||
fn step(&mut self) -> FrameStepResult {
|
||||
let array_data = match &self.this {
|
||||
None => return type_error!("reduceRight called on non-array"),
|
||||
None => return Err("reduceRight called on non-array".to_type_error()),
|
||||
Some(ad) => ad,
|
||||
};
|
||||
|
||||
if self.array_i == 0 {
|
||||
match &self.value {
|
||||
None => {
|
||||
return type_error!("reduceRight of empty array with no initial value");
|
||||
return Err("reduceRight of empty array with no initial value".to_type_error());
|
||||
}
|
||||
Some(value) => {
|
||||
return Ok(FrameStepOk::Pop(CallResult {
|
||||
@@ -88,7 +88,7 @@ impl StackFrameTrait for ReduceRightFrame {
|
||||
}
|
||||
Some(value) => match self.reducer.load_function() {
|
||||
LoadFunctionResult::NotAFunction => {
|
||||
return format_err!("TpeError: reduceRight fn is not a function")
|
||||
return Err("reduceRight fn is not a function".to_type_error())
|
||||
}
|
||||
LoadFunctionResult::NativeFunction(native_fn) => {
|
||||
self.value = Some(native_fn(
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::builtins::type_error_builtin::ToTypeError;
|
||||
use crate::native_frame_function::NativeFrameFunction;
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::stack_frame::FrameStepResult;
|
||||
use crate::stack_frame::{CallResult, FrameStepOk, StackFrameTrait};
|
||||
use crate::vs_array::VsArray;
|
||||
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
use crate::vs_value::{LoadFunctionResult, ToVal, Val, ValTrait};
|
||||
|
||||
pub static SORT: NativeFrameFunction = NativeFrameFunction {
|
||||
make_frame: || {
|
||||
@@ -208,7 +208,7 @@ enum SortTreeNodeData {
|
||||
impl StackFrameTrait for SortFrame {
|
||||
fn write_this(&mut self, const_: bool, this: Val) -> Result<(), Val> {
|
||||
if const_ {
|
||||
return type_error!("Cannot sort const array");
|
||||
return Err("Cannot sort const array".to_type_error());
|
||||
}
|
||||
|
||||
self.this = this.as_array_data();
|
||||
@@ -229,7 +229,7 @@ impl StackFrameTrait for SortFrame {
|
||||
fn step(&mut self) -> FrameStepResult {
|
||||
if !self.started {
|
||||
let array_data = match &mut self.this {
|
||||
None => return type_error!("array fn called on non-array"),
|
||||
None => return Err("array fn called on non-array".to_type_error()),
|
||||
Some(ad) => ad,
|
||||
};
|
||||
|
||||
@@ -263,7 +263,7 @@ impl StackFrameTrait for SortFrame {
|
||||
SortTreeNodeData::Sorted(vals) => {
|
||||
let mut owned_vals = vec![];
|
||||
std::mem::swap(&mut owned_vals, vals);
|
||||
let res = Val::Array(Rc::new(VsArray::from(owned_vals)));
|
||||
let res = owned_vals.to_val();
|
||||
|
||||
FrameStepOk::Pop(CallResult {
|
||||
return_: res.clone(),
|
||||
@@ -274,7 +274,7 @@ impl StackFrameTrait for SortFrame {
|
||||
},
|
||||
Some((left, right)) => match self.comparator.load_function() {
|
||||
LoadFunctionResult::NotAFunction => {
|
||||
return type_error!("comparator is not a function");
|
||||
return Err("comparator is not a function".to_type_error());
|
||||
}
|
||||
LoadFunctionResult::NativeFunction(native_fn) => {
|
||||
let res = native_fn(
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::{
|
||||
format_err,
|
||||
builtins::error_builtin::ToError,
|
||||
native_function::{NativeFunction, ThisWrapper},
|
||||
todo_fn::TODO,
|
||||
vs_value::{Val, ValTrait},
|
||||
vs_value::{ToValString, Val, ValTrait},
|
||||
};
|
||||
|
||||
pub fn op_sub_bigint(_bigint: &BigInt, subscript: &Val) -> Val {
|
||||
@@ -23,12 +21,12 @@ static TO_STRING: NativeFunction = NativeFunction {
|
||||
Ok(match this.get() {
|
||||
Val::BigInt(_) => match params.get(0) {
|
||||
Some(_) => {
|
||||
return format_err!("TODO: toString with radix");
|
||||
return Err("TODO: toString with radix".to_error());
|
||||
}
|
||||
|
||||
None => Val::String(Rc::new(this.get().val_to_string())),
|
||||
None => this.get().to_val_string(),
|
||||
},
|
||||
_ => return format_err!("TODO: bigint indirection"),
|
||||
_ => return Err("TODO: bigint indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -37,7 +35,7 @@ static VALUE_OF: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
Val::BigInt(bigint) => Val::BigInt(bigint.clone()),
|
||||
_ => return format_err!("TODO: bigint indirection"),
|
||||
_ => return Err("TODO: bigint indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,18 +4,18 @@ use num_bigint::BigInt;
|
||||
|
||||
use crate::{
|
||||
builtins::range_error_builtin::to_range_error,
|
||||
builtins::type_error_builtin::to_type_error,
|
||||
format_err,
|
||||
native_function::{NativeFunction, ThisWrapper},
|
||||
operations::op_sub,
|
||||
range_error, type_error,
|
||||
range_error,
|
||||
vs_array::VsArray,
|
||||
vs_class::VsClass,
|
||||
vs_object::VsObject,
|
||||
vs_value::{LoadFunctionResult, Val, VsType},
|
||||
vs_value::{LoadFunctionResult, ToVal, ToValString, Val, VsType},
|
||||
ValTrait,
|
||||
};
|
||||
|
||||
use super::type_error_builtin::ToTypeError;
|
||||
|
||||
pub struct ArrayBuiltin {}
|
||||
|
||||
pub static ARRAY_BUILTIN: ArrayBuiltin = ArrayBuiltin {};
|
||||
@@ -37,7 +37,7 @@ impl ValTrait for ArrayBuiltin {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new("function Array() { [native code] }".to_string()))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -75,7 +75,7 @@ impl ValTrait for ArrayBuiltin {
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of Array builtin")
|
||||
Err("Cannot assign to subscript of Array builtin".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
@@ -106,36 +106,31 @@ static IS_ARRAY: NativeFunction = NativeFunction {
|
||||
static FROM: NativeFunction = NativeFunction {
|
||||
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
|
||||
let first_param = match params.get(0) {
|
||||
None => return type_error!("undefined is not iterable"),
|
||||
None => return Err("undefined is not iterable".to_type_error()),
|
||||
Some(p) => p,
|
||||
};
|
||||
|
||||
if params.len() > 1 {
|
||||
return format_err!("TODO: Using Array.from with a map function");
|
||||
return Err(format!("TODO: Using Array.from with a map function").to_val());
|
||||
}
|
||||
|
||||
Ok(match first_param {
|
||||
Val::Array(arr) => Val::Array(arr.clone()),
|
||||
Val::String(s) => Val::Array(Rc::new(VsArray::from(
|
||||
s.chars()
|
||||
.map(|c| Val::String(Rc::new(c.to_string())))
|
||||
.collect(),
|
||||
))),
|
||||
Val::Void | Val::Undefined | Val::Null => return type_error!("items is not iterable"),
|
||||
Val::String(s) => s.chars().map(|c| c.to_val()).collect::<Vec<Val>>().to_val(),
|
||||
Val::Void | Val::Undefined | Val::Null => {
|
||||
return Err("items is not iterable".to_type_error())
|
||||
}
|
||||
Val::Bool(..) | Val::Number(..) | Val::BigInt(..) | Val::Symbol(..) => {
|
||||
Val::Array(Rc::new(VsArray::new()))
|
||||
VsArray::new().to_val()
|
||||
}
|
||||
Val::Object(..) | Val::Function(..) | Val::Class(..) | Val::Static(..) | Val::Custom(..) => {
|
||||
let len = op_sub(
|
||||
first_param.clone(),
|
||||
Val::String(Rc::new("length".to_string())),
|
||||
)
|
||||
.map_err(|e| e.val_to_string())
|
||||
.unwrap() // TODO: Exception
|
||||
.to_number();
|
||||
let len = op_sub(first_param.clone(), "length".to_val())
|
||||
.map_err(|e| e.val_to_string())
|
||||
.unwrap() // TODO: Exception
|
||||
.to_number();
|
||||
|
||||
if len.is_sign_negative() || len.is_nan() {
|
||||
return Ok(Val::Array(Rc::new(VsArray::new())));
|
||||
return Ok(VsArray::new().to_val());
|
||||
}
|
||||
|
||||
if len.is_infinite() {
|
||||
@@ -156,7 +151,7 @@ static FROM: NativeFunction = NativeFunction {
|
||||
);
|
||||
}
|
||||
|
||||
Val::Array(Rc::new(VsArray::from(arr)))
|
||||
VsArray::from(arr).to_val()
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -164,13 +159,13 @@ static FROM: NativeFunction = NativeFunction {
|
||||
|
||||
static OF: NativeFunction = NativeFunction {
|
||||
fn_: |_this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(Val::Array(Rc::new(VsArray::from(params))))
|
||||
Ok(VsArray::from(params).to_val())
|
||||
},
|
||||
};
|
||||
|
||||
fn to_array(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
|
||||
if params.len() != 1 {
|
||||
return Ok(Val::Array(Rc::new(VsArray::from(params))));
|
||||
return Ok(VsArray::from(params).to_val());
|
||||
}
|
||||
|
||||
Ok(match params[0] {
|
||||
@@ -187,8 +182,8 @@ fn to_array(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
|
||||
arr.push(Val::Void);
|
||||
}
|
||||
|
||||
Val::Array(Rc::new(VsArray::from(arr)))
|
||||
VsArray::from(arr).to_val()
|
||||
}
|
||||
_ => Val::Array(Rc::new(VsArray::from(params))),
|
||||
_ => VsArray::from(params).to_val(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,16 +3,16 @@ use std::rc::Rc;
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::{
|
||||
builtins::type_error_builtin::to_type_error,
|
||||
native_function::ThisWrapper,
|
||||
type_error,
|
||||
vs_array::VsArray,
|
||||
vs_class::VsClass,
|
||||
vs_object::VsObject,
|
||||
vs_value::{LoadFunctionResult, Val, VsType},
|
||||
vs_value::{LoadFunctionResult, ToValString, Val, VsType},
|
||||
ValTrait,
|
||||
};
|
||||
|
||||
use super::type_error_builtin::ToTypeError;
|
||||
|
||||
pub struct BooleanBuiltin {}
|
||||
|
||||
pub static BOOLEAN_BUILTIN: BooleanBuiltin = BooleanBuiltin {};
|
||||
@@ -34,7 +34,7 @@ impl ValTrait for BooleanBuiltin {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new("function Boolean() { [native code] }".to_string()))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -67,7 +67,7 @@ impl ValTrait for BooleanBuiltin {
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of Boolean builtin")
|
||||
Err("Cannot assign to subscript of Boolean builtin".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
|
||||
@@ -6,8 +6,9 @@ use crate::native_function::{NativeFunction, ThisWrapper};
|
||||
use crate::vs_array::VsArray;
|
||||
use crate::vs_class::VsClass;
|
||||
use crate::vs_object::VsObject;
|
||||
use crate::vs_value::{LoadFunctionResult, Val, ValTrait, VsType};
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
use crate::vs_value::{LoadFunctionResult, ToValString, Val, ValTrait, VsType};
|
||||
|
||||
use super::type_error_builtin::ToTypeError;
|
||||
|
||||
pub struct DebugBuiltin {}
|
||||
|
||||
@@ -30,7 +31,7 @@ impl ValTrait for DebugBuiltin {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new(self.val_to_string()))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -69,7 +70,7 @@ impl ValTrait for DebugBuiltin {
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of Debug builtin")
|
||||
Err("Cannot assign to subscript of Debug builtin".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
|
||||
@@ -3,9 +3,8 @@ use std::{collections::BTreeMap, rc::Rc};
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
use crate::vs_value::{ToVal, ToValString};
|
||||
use crate::{
|
||||
format_val,
|
||||
native_function::NativeFunction,
|
||||
operations::{op_sub, op_submov},
|
||||
vs_array::VsArray,
|
||||
@@ -15,6 +14,8 @@ use crate::{
|
||||
ValTrait,
|
||||
};
|
||||
|
||||
use super::type_error_builtin::ToTypeError;
|
||||
|
||||
pub struct ErrorBuiltin {}
|
||||
|
||||
pub static ERROR_BUILTIN: ErrorBuiltin = ErrorBuiltin {};
|
||||
@@ -36,7 +37,7 @@ impl ValTrait for ErrorBuiltin {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new("function Error() { [native code] }".to_string()))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -64,7 +65,15 @@ impl ValTrait for ErrorBuiltin {
|
||||
}
|
||||
|
||||
fn load_function(&self) -> LoadFunctionResult {
|
||||
LoadFunctionResult::NativeFunction(to_error)
|
||||
LoadFunctionResult::NativeFunction(|_: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(
|
||||
match params.get(0) {
|
||||
Some(param) => param.to_val_string(),
|
||||
None => "".to_val(),
|
||||
}
|
||||
.to_error(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn sub(&self, _key: Val) -> Result<Val, Val> {
|
||||
@@ -72,7 +81,7 @@ impl ValTrait for ErrorBuiltin {
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of Error builtin")
|
||||
Err("Cannot assign to subscript of Error builtin".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
@@ -88,44 +97,44 @@ impl ValTrait for ErrorBuiltin {
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! error {
|
||||
($fmt:expr $(, $($arg:expr),*)?) => {{
|
||||
let formatted_string = format!($fmt $(, $($arg),*)?);
|
||||
Err(to_error(
|
||||
ThisWrapper::new(true, &mut Val::Undefined),
|
||||
vec![Val::String(Rc::new(formatted_string))],
|
||||
).unwrap())
|
||||
}};
|
||||
pub trait ToError {
|
||||
fn to_error(self) -> Val;
|
||||
}
|
||||
|
||||
pub fn to_error(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
|
||||
Ok(Val::Object(Rc::new(VsObject {
|
||||
string_map: BTreeMap::from([(
|
||||
"message".to_string(),
|
||||
Val::String(Rc::new(match params.get(0) {
|
||||
Some(param) => param.val_to_string(),
|
||||
None => "".to_string(),
|
||||
})),
|
||||
)]),
|
||||
symbol_map: Default::default(),
|
||||
prototype: Some(make_error_prototype()),
|
||||
})))
|
||||
impl ToError for Val {
|
||||
fn to_error(self) -> Val {
|
||||
VsObject {
|
||||
string_map: BTreeMap::from([("message".to_string(), self.to_val_string())]),
|
||||
symbol_map: Default::default(),
|
||||
prototype: Some(make_error_prototype()),
|
||||
}
|
||||
.to_val()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToError for String {
|
||||
fn to_error(self) -> Val {
|
||||
self.to_val().to_error()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToError for &str {
|
||||
fn to_error(self) -> Val {
|
||||
self.to_string().to_error()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Static? (Rc -> Arc?)
|
||||
fn make_error_prototype() -> Val {
|
||||
Val::Object(Rc::new(VsObject {
|
||||
VsObject {
|
||||
string_map: BTreeMap::from([
|
||||
(
|
||||
"name".to_string(),
|
||||
Val::String(Rc::new("Error".to_string())),
|
||||
),
|
||||
("toString".to_string(), Val::Static(&ERROR_TO_STRING)),
|
||||
("name".to_string(), "Error".to_val()),
|
||||
("toString".to_string(), ERROR_TO_STRING.to_val()),
|
||||
]),
|
||||
symbol_map: Default::default(),
|
||||
prototype: None,
|
||||
}))
|
||||
}
|
||||
.to_val()
|
||||
}
|
||||
|
||||
static SET_MESSAGE: NativeFunction = NativeFunction {
|
||||
@@ -135,11 +144,7 @@ static SET_MESSAGE: NativeFunction = NativeFunction {
|
||||
None => "".to_string(),
|
||||
};
|
||||
|
||||
op_submov(
|
||||
this.get_mut()?,
|
||||
format_val!("message"),
|
||||
format_val!("{}", message),
|
||||
)?;
|
||||
op_submov(this.get_mut()?, "message".to_val(), message.to_val())?;
|
||||
|
||||
Ok(Val::Undefined)
|
||||
},
|
||||
@@ -147,7 +152,7 @@ static SET_MESSAGE: NativeFunction = NativeFunction {
|
||||
|
||||
static ERROR_TO_STRING: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
let message = op_sub(this.get().clone(), format_val!("message"))?;
|
||||
Ok(format_val!("Error({})", message)) // TODO: Fixes needed here (and other errors)
|
||||
let message = op_sub(this.get().clone(), "message".to_val())?;
|
||||
Ok(format!("Error({})", message).to_val()) // TODO: Fixes needed here (and other errors)
|
||||
},
|
||||
};
|
||||
|
||||
@@ -7,8 +7,9 @@ use crate::operations::to_u32;
|
||||
use crate::vs_array::VsArray;
|
||||
use crate::vs_class::VsClass;
|
||||
use crate::vs_object::VsObject;
|
||||
use crate::vs_value::{LoadFunctionResult, Val, ValTrait, VsType};
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
use crate::vs_value::{LoadFunctionResult, ToValString, Val, ValTrait, VsType};
|
||||
|
||||
use super::type_error_builtin::ToTypeError;
|
||||
|
||||
pub struct MathBuiltin {}
|
||||
|
||||
@@ -31,7 +32,7 @@ impl ValTrait for MathBuiltin {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new(self.val_to_string()))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -114,7 +115,7 @@ impl ValTrait for MathBuiltin {
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of Math builtin")
|
||||
Err("Cannot assign to subscript of Math builtin".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::rc::Rc;
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
use crate::vs_value::ToValString;
|
||||
use crate::{
|
||||
native_function::NativeFunction,
|
||||
vs_array::VsArray,
|
||||
@@ -13,6 +13,8 @@ use crate::{
|
||||
ValTrait,
|
||||
};
|
||||
|
||||
use super::type_error_builtin::ToTypeError;
|
||||
|
||||
pub struct NumberBuiltin {}
|
||||
|
||||
pub static NUMBER_BUILTIN: NumberBuiltin = NumberBuiltin {};
|
||||
@@ -34,7 +36,7 @@ impl ValTrait for NumberBuiltin {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new("function Number() { [native code] }".to_string()))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -83,7 +85,7 @@ impl ValTrait for NumberBuiltin {
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of Number builtin")
|
||||
Err("Cannot assign to subscript of Number builtin".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
|
||||
@@ -3,9 +3,8 @@ use std::{collections::BTreeMap, rc::Rc};
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
use crate::vs_value::{ToVal, ToValString};
|
||||
use crate::{
|
||||
format_val,
|
||||
native_function::NativeFunction,
|
||||
operations::{op_sub, op_submov},
|
||||
vs_array::VsArray,
|
||||
@@ -15,6 +14,8 @@ use crate::{
|
||||
ValTrait,
|
||||
};
|
||||
|
||||
use super::type_error_builtin::ToTypeError;
|
||||
|
||||
pub struct RangeErrorBuiltin {}
|
||||
|
||||
pub static RANGE_ERROR_BUILTIN: RangeErrorBuiltin = RangeErrorBuiltin {};
|
||||
@@ -36,9 +37,7 @@ impl ValTrait for RangeErrorBuiltin {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new(
|
||||
"function RangeError() { [native code] }".to_string(),
|
||||
))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -74,7 +73,7 @@ impl ValTrait for RangeErrorBuiltin {
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of RangeError builtin")
|
||||
Err("Cannot assign to subscript of RangeError builtin".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
@@ -91,32 +90,33 @@ impl ValTrait for RangeErrorBuiltin {
|
||||
}
|
||||
|
||||
pub fn to_range_error(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
|
||||
Ok(Val::Object(Rc::new(VsObject {
|
||||
string_map: BTreeMap::from([(
|
||||
"message".to_string(),
|
||||
Val::String(Rc::new(match params.get(0) {
|
||||
Some(param) => param.val_to_string(),
|
||||
None => "".to_string(),
|
||||
})),
|
||||
)]),
|
||||
symbol_map: Default::default(),
|
||||
prototype: Some(make_range_error_prototype()),
|
||||
})))
|
||||
Ok(
|
||||
VsObject {
|
||||
string_map: BTreeMap::from([(
|
||||
"message".to_string(),
|
||||
match params.get(0) {
|
||||
Some(param) => param.to_val_string(),
|
||||
None => "".to_val(),
|
||||
},
|
||||
)]),
|
||||
symbol_map: Default::default(),
|
||||
prototype: Some(make_range_error_prototype()),
|
||||
}
|
||||
.to_val(),
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: Static? (Rc -> Arc?)
|
||||
fn make_range_error_prototype() -> Val {
|
||||
Val::Object(Rc::new(VsObject {
|
||||
VsObject {
|
||||
string_map: BTreeMap::from([
|
||||
(
|
||||
"name".to_string(),
|
||||
Val::String(Rc::new("RangeError".to_string())),
|
||||
),
|
||||
("name".to_string(), "RangeError".to_val()),
|
||||
("toString".to_string(), Val::Static(&RANGE_ERROR_TO_STRING)),
|
||||
]),
|
||||
symbol_map: Default::default(),
|
||||
prototype: None,
|
||||
}))
|
||||
}
|
||||
.to_val()
|
||||
}
|
||||
|
||||
static SET_MESSAGE: NativeFunction = NativeFunction {
|
||||
@@ -126,11 +126,7 @@ static SET_MESSAGE: NativeFunction = NativeFunction {
|
||||
None => "".to_string(),
|
||||
};
|
||||
|
||||
op_submov(
|
||||
this.get_mut()?,
|
||||
format_val!("message"),
|
||||
format_val!("{}", message),
|
||||
)?;
|
||||
op_submov(this.get_mut()?, "message".to_val(), message.to_val())?;
|
||||
|
||||
Ok(Val::Undefined)
|
||||
},
|
||||
@@ -138,8 +134,8 @@ static SET_MESSAGE: NativeFunction = NativeFunction {
|
||||
|
||||
static RANGE_ERROR_TO_STRING: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
let message = op_sub(this.get().clone(), format_val!("message"))?;
|
||||
Ok(format_val!("RangeError({})", message))
|
||||
let message = op_sub(this.get().clone(), "message".to_val())?;
|
||||
Ok(format!("RangeError({})", message).to_val())
|
||||
},
|
||||
};
|
||||
|
||||
@@ -149,7 +145,7 @@ macro_rules! range_error {
|
||||
let formatted_string = format!($fmt $(, $($arg),*)?);
|
||||
Err(to_range_error(
|
||||
ThisWrapper::new(true, &mut Val::Undefined),
|
||||
vec![Val::String(Rc::new(formatted_string))],
|
||||
vec![formatted_string.to_val()],
|
||||
).unwrap())
|
||||
}};
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ use std::rc::Rc;
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::vs_value::{ToVal, ToValString};
|
||||
use crate::{builtins::range_error_builtin::to_range_error, range_error};
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
use crate::{
|
||||
native_function::NativeFunction,
|
||||
vs_array::VsArray,
|
||||
@@ -14,6 +14,8 @@ use crate::{
|
||||
ValTrait,
|
||||
};
|
||||
|
||||
use super::type_error_builtin::ToTypeError;
|
||||
|
||||
pub struct StringBuiltin {}
|
||||
|
||||
pub static STRING_BUILTIN: StringBuiltin = StringBuiltin {};
|
||||
@@ -35,7 +37,7 @@ impl ValTrait for StringBuiltin {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new("function String() { [native code] }".to_string()))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -76,7 +78,7 @@ impl ValTrait for StringBuiltin {
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of String builtin")
|
||||
Err("Cannot assign to subscript of String builtin".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
@@ -107,14 +109,14 @@ static FROM_CODE_POINT: NativeFunction = NativeFunction {
|
||||
result.push(char);
|
||||
}
|
||||
|
||||
Ok(Val::String(Rc::new(result)))
|
||||
Ok(result.to_val())
|
||||
},
|
||||
};
|
||||
|
||||
fn to_string(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
|
||||
Ok(if let Some(value) = params.get(0) {
|
||||
Val::String(Rc::new(value.val_to_string()))
|
||||
value.to_val_string()
|
||||
} else {
|
||||
Val::String(Rc::new("".to_string()))
|
||||
"".to_val()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,17 +3,16 @@ use std::rc::Rc;
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::{
|
||||
builtins::type_error_builtin::to_type_error,
|
||||
native_function::ThisWrapper,
|
||||
type_error,
|
||||
vs_array::VsArray,
|
||||
vs_class::VsClass,
|
||||
vs_object::VsObject,
|
||||
vs_symbol::VsSymbol,
|
||||
vs_value::{LoadFunctionResult, Val, VsType},
|
||||
vs_value::{LoadFunctionResult, ToValString, Val, VsType},
|
||||
ValTrait,
|
||||
};
|
||||
|
||||
use super::type_error_builtin::ToTypeError;
|
||||
|
||||
pub struct SymbolBuiltin {}
|
||||
|
||||
pub static SYMBOL_BUILTIN: SymbolBuiltin = SymbolBuiltin {};
|
||||
@@ -35,7 +34,7 @@ impl ValTrait for SymbolBuiltin {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new("[object Symbol]".to_string()))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -71,7 +70,7 @@ impl ValTrait for SymbolBuiltin {
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of Symbol builtin")
|
||||
Err("Cannot assign to subscript of Symbol builtin".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
|
||||
@@ -3,9 +3,8 @@ use std::{collections::BTreeMap, rc::Rc};
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::type_error;
|
||||
use crate::vs_value::{ToVal, ToValString};
|
||||
use crate::{
|
||||
format_val,
|
||||
native_function::NativeFunction,
|
||||
operations::{op_sub, op_submov},
|
||||
vs_array::VsArray,
|
||||
@@ -36,9 +35,7 @@ impl ValTrait for TypeErrorBuiltin {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new(
|
||||
"function TypeError() { [native code] }".to_string(),
|
||||
))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -66,7 +63,15 @@ impl ValTrait for TypeErrorBuiltin {
|
||||
}
|
||||
|
||||
fn load_function(&self) -> LoadFunctionResult {
|
||||
LoadFunctionResult::NativeFunction(to_type_error)
|
||||
LoadFunctionResult::NativeFunction(|_: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(
|
||||
match params.get(0) {
|
||||
Some(param) => param.to_val_string(),
|
||||
None => "".to_val(),
|
||||
}
|
||||
.to_type_error(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn sub(&self, _key: Val) -> Result<Val, Val> {
|
||||
@@ -74,7 +79,7 @@ impl ValTrait for TypeErrorBuiltin {
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of TypeError builtin")
|
||||
Err("Cannot assign to subscript of TypeError builtin".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
@@ -90,33 +95,17 @@ impl ValTrait for TypeErrorBuiltin {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_type_error(_: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
|
||||
Ok(Val::Object(Rc::new(VsObject {
|
||||
string_map: BTreeMap::from([(
|
||||
"message".to_string(),
|
||||
Val::String(Rc::new(match params.get(0) {
|
||||
Some(param) => param.val_to_string(),
|
||||
None => "".to_string(),
|
||||
})),
|
||||
)]),
|
||||
symbol_map: Default::default(),
|
||||
prototype: Some(make_type_error_prototype()),
|
||||
})))
|
||||
}
|
||||
|
||||
// TODO: Static? (Rc -> Arc?)
|
||||
fn make_type_error_prototype() -> Val {
|
||||
Val::Object(Rc::new(VsObject {
|
||||
VsObject {
|
||||
string_map: BTreeMap::from([
|
||||
(
|
||||
"name".to_string(),
|
||||
Val::String(Rc::new("TypeError".to_string())),
|
||||
),
|
||||
("toString".to_string(), Val::Static(&TYPE_ERROR_TO_STRING)),
|
||||
("name".to_string(), "TypeError".to_val()),
|
||||
("toString".to_string(), TYPE_ERROR_TO_STRING.to_val()),
|
||||
]),
|
||||
symbol_map: Default::default(),
|
||||
prototype: None,
|
||||
}))
|
||||
}
|
||||
.to_val()
|
||||
}
|
||||
|
||||
static SET_MESSAGE: NativeFunction = NativeFunction {
|
||||
@@ -126,11 +115,7 @@ static SET_MESSAGE: NativeFunction = NativeFunction {
|
||||
None => "".to_string(),
|
||||
};
|
||||
|
||||
op_submov(
|
||||
this.get_mut()?,
|
||||
format_val!("message"),
|
||||
format_val!("{}", message),
|
||||
)?;
|
||||
op_submov(this.get_mut()?, "message".to_val(), message.to_val())?;
|
||||
|
||||
Ok(Val::Undefined)
|
||||
},
|
||||
@@ -138,18 +123,34 @@ static SET_MESSAGE: NativeFunction = NativeFunction {
|
||||
|
||||
static TYPE_ERROR_TO_STRING: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
let message = op_sub(this.get().clone(), format_val!("message"))?;
|
||||
Ok(format_val!("TypeError({})", message))
|
||||
let message = op_sub(this.get().clone(), "message".to_val())?;
|
||||
Ok(format!("TypeError({})", message).to_val())
|
||||
},
|
||||
};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! type_error {
|
||||
($fmt:expr $(, $($arg:expr),*)?) => {{
|
||||
let formatted_string = format!($fmt $(, $($arg),*)?);
|
||||
Err(to_type_error(
|
||||
ThisWrapper::new(true, &mut Val::Undefined),
|
||||
vec![Val::String(Rc::new(formatted_string))],
|
||||
).unwrap())
|
||||
}};
|
||||
pub trait ToTypeError {
|
||||
fn to_type_error(self) -> Val;
|
||||
}
|
||||
|
||||
impl ToTypeError for &str {
|
||||
fn to_type_error(self) -> Val {
|
||||
self.to_string().to_type_error()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTypeError for String {
|
||||
fn to_type_error(self) -> Val {
|
||||
self.to_val().to_type_error()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTypeError for Val {
|
||||
fn to_type_error(self) -> Val {
|
||||
VsObject {
|
||||
string_map: BTreeMap::from([("message".to_string(), self)]),
|
||||
symbol_map: Default::default(),
|
||||
prototype: Some(make_type_error_prototype()),
|
||||
}
|
||||
.to_val()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ use num_bigint::Sign;
|
||||
use valuescript_common::InstructionByte;
|
||||
|
||||
use crate::builtins::BUILTIN_VALS;
|
||||
use crate::vs_array::VsArray;
|
||||
use crate::vs_class::VsClass;
|
||||
use crate::vs_function::VsFunction;
|
||||
use crate::vs_object::VsObject;
|
||||
use crate::vs_pointer::VsPointer;
|
||||
use crate::vs_symbol::VsSymbol;
|
||||
use crate::vs_value::ToVal;
|
||||
use crate::vs_value::Val;
|
||||
use crate::vs_value::ValTrait;
|
||||
|
||||
@@ -100,9 +100,9 @@ impl BytecodeDecoder {
|
||||
BytecodeType::Null => Val::Null,
|
||||
BytecodeType::False => Val::Bool(false),
|
||||
BytecodeType::True => Val::Bool(true),
|
||||
BytecodeType::SignedByte => Val::Number(self.decode_signed_byte() as f64),
|
||||
BytecodeType::Number => Val::Number(self.decode_number()),
|
||||
BytecodeType::String => Val::String(Rc::new(self.decode_string())),
|
||||
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 => {
|
||||
let mut vals: Vec<Val> = Vec::new();
|
||||
|
||||
@@ -112,7 +112,7 @@ impl BytecodeDecoder {
|
||||
|
||||
self.decode_type(); // End (TODO: assert)
|
||||
|
||||
Val::Array(Rc::new(VsArray::from(vals)))
|
||||
vals.to_val()
|
||||
}
|
||||
BytecodeType::Object => {
|
||||
let mut string_map: BTreeMap<String, Val> = BTreeMap::new();
|
||||
@@ -131,11 +131,12 @@ impl BytecodeDecoder {
|
||||
|
||||
self.decode_type(); // End (TODO: assert)
|
||||
|
||||
Val::Object(Rc::new(VsObject {
|
||||
VsObject {
|
||||
string_map,
|
||||
symbol_map,
|
||||
prototype: None,
|
||||
}))
|
||||
}
|
||||
.to_val()
|
||||
}
|
||||
BytecodeType::Function => self.decode_function_header(),
|
||||
BytecodeType::Pointer => self.decode_pointer(),
|
||||
@@ -144,11 +145,12 @@ impl BytecodeDecoder {
|
||||
val => val,
|
||||
},
|
||||
BytecodeType::Builtin => Val::Static(BUILTIN_VALS[self.decode_varsize_uint()]),
|
||||
BytecodeType::Class => Val::Class(Rc::new(VsClass {
|
||||
BytecodeType::Class => VsClass {
|
||||
constructor: self.decode_val(registers),
|
||||
instance_prototype: self.decode_val(registers),
|
||||
})),
|
||||
BytecodeType::BigInt => Val::BigInt(self.decode_bigint()),
|
||||
}
|
||||
.to_val(),
|
||||
BytecodeType::BigInt => self.decode_bigint().to_val(),
|
||||
BytecodeType::Unrecognized => panic!("Unrecognized bytecode type at {}", self.pos - 1),
|
||||
};
|
||||
}
|
||||
@@ -249,7 +251,7 @@ impl BytecodeDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
return VsPointer::new(&self.data, pos);
|
||||
VsPointer::new(&self.data, pos).to_val()
|
||||
}
|
||||
|
||||
pub fn decode_function_header(&mut self) -> Val {
|
||||
@@ -257,13 +259,14 @@ impl BytecodeDecoder {
|
||||
let register_count = self.decode_byte() as usize;
|
||||
let parameter_count = self.decode_byte() as usize;
|
||||
|
||||
return Val::Function(Rc::new(VsFunction {
|
||||
return VsFunction {
|
||||
bytecode: self.data.clone(),
|
||||
register_count: register_count,
|
||||
parameter_count: parameter_count,
|
||||
register_count,
|
||||
parameter_count,
|
||||
start: self.pos,
|
||||
binds: Vec::new(),
|
||||
}));
|
||||
}
|
||||
.to_val();
|
||||
}
|
||||
|
||||
pub fn decode_instruction(&mut self) -> InstructionByte {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use valuescript_common::InstructionByte;
|
||||
|
||||
use crate::builtins::type_error_builtin::to_type_error;
|
||||
use crate::builtins::type_error_builtin::ToTypeError;
|
||||
use crate::bytecode_decoder::BytecodeDecoder;
|
||||
use crate::bytecode_decoder::BytecodeType;
|
||||
use crate::native_function::ThisWrapper;
|
||||
@@ -10,8 +8,8 @@ use crate::operations;
|
||||
use crate::stack_frame::FrameStepOk;
|
||||
use crate::stack_frame::FrameStepResult;
|
||||
use crate::stack_frame::{CallResult, StackFrame, StackFrameTrait};
|
||||
use crate::type_error;
|
||||
use crate::vs_object::VsObject;
|
||||
use crate::vs_value::ToVal;
|
||||
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
|
||||
|
||||
pub struct BytecodeStackFrame {
|
||||
@@ -371,15 +369,16 @@ impl StackFrameTrait for BytecodeStackFrame {
|
||||
let class = match self.decoder.decode_val(&self.registers).as_class_data() {
|
||||
Some(class) => class,
|
||||
None => {
|
||||
return type_error!("value is not a constructor");
|
||||
return Err("value is not a constructor".to_type_error());
|
||||
}
|
||||
};
|
||||
|
||||
let mut instance = Val::Object(Rc::new(VsObject {
|
||||
let mut instance = VsObject {
|
||||
string_map: Default::default(),
|
||||
symbol_map: Default::default(),
|
||||
prototype: Some(class.instance_prototype.clone()),
|
||||
}));
|
||||
}
|
||||
.to_val();
|
||||
|
||||
match class.constructor {
|
||||
Val::Void => {
|
||||
@@ -456,7 +455,7 @@ impl StackFrameTrait for BytecodeStackFrame {
|
||||
|
||||
RequireMutableThis => {
|
||||
if self.const_this {
|
||||
return type_error!("Cannot mutate this because it is const");
|
||||
return Err("Cannot mutate this because it is const".to_type_error());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,7 +5,6 @@ mod bytecode_decoder;
|
||||
mod bytecode_stack_frame;
|
||||
mod first_stack_frame;
|
||||
mod helpers;
|
||||
mod macros;
|
||||
mod native_frame_function;
|
||||
mod native_function;
|
||||
mod number_methods;
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#[macro_export]
|
||||
macro_rules! format_err {
|
||||
($fmt:expr $(, $($arg:expr),*)?) => {{
|
||||
let formatted_string = format!($fmt $(, $($arg),*)?);
|
||||
|
||||
// TODO: This should be a proper error type
|
||||
Err(Val::String(Rc::new(formatted_string)))
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! format_val {
|
||||
($fmt:expr $(, $($arg:expr),*)?) => {{
|
||||
let formatted_string = format!($fmt $(, $($arg),*)?);
|
||||
Val::String(Rc::new(formatted_string))
|
||||
}};
|
||||
}
|
||||
@@ -2,14 +2,13 @@ use std::rc::Rc;
|
||||
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::format_err;
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::builtins::error_builtin::ToError;
|
||||
use crate::builtins::type_error_builtin::ToTypeError;
|
||||
use crate::stack_frame::StackFrame;
|
||||
use crate::vs_array::VsArray;
|
||||
use crate::vs_class::VsClass;
|
||||
use crate::vs_object::VsObject;
|
||||
use crate::vs_value::{LoadFunctionResult, Val, ValTrait, VsType};
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
use crate::vs_value::{LoadFunctionResult, ToValString, Val, ValTrait, VsType};
|
||||
|
||||
pub struct NativeFrameFunction {
|
||||
pub make_frame: fn() -> StackFrame,
|
||||
@@ -32,7 +31,7 @@ impl ValTrait for NativeFrameFunction {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new(self.val_to_string()))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -63,11 +62,11 @@ impl ValTrait for NativeFrameFunction {
|
||||
}
|
||||
|
||||
fn sub(&self, _key: Val) -> Result<Val, Val> {
|
||||
format_err!("TODO: Subscript native function")
|
||||
Err("TODO: Subscript native function".to_error())
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of native function")
|
||||
Err("Cannot assign to subscript of native function".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
|
||||
@@ -2,12 +2,12 @@ use std::rc::Rc;
|
||||
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::format_err;
|
||||
use crate::builtins::error_builtin::ToError;
|
||||
use crate::builtins::type_error_builtin::ToTypeError;
|
||||
use crate::vs_array::VsArray;
|
||||
use crate::vs_class::VsClass;
|
||||
use crate::vs_object::VsObject;
|
||||
use crate::vs_value::{LoadFunctionResult, Val, ValTrait, VsType};
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
use crate::vs_value::{LoadFunctionResult, ToVal, ToValString, Val, ValTrait, VsType};
|
||||
|
||||
pub struct ThisWrapper<'a> {
|
||||
const_: bool,
|
||||
@@ -25,7 +25,7 @@ impl<'a> ThisWrapper<'a> {
|
||||
|
||||
pub fn get_mut(&mut self) -> Result<&mut Val, Val> {
|
||||
if self.const_ {
|
||||
return type_error!("Cannot mutate this because it is const");
|
||||
return Err("Cannot mutate this because it is const".to_type_error());
|
||||
}
|
||||
|
||||
Ok(self.this)
|
||||
@@ -53,7 +53,7 @@ impl ValTrait for NativeFunction {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new(self.val_to_string()))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -84,11 +84,11 @@ impl ValTrait for NativeFunction {
|
||||
}
|
||||
|
||||
fn sub(&self, _key: Val) -> Result<Val, Val> {
|
||||
format_err!("TODO: Subscript native function")
|
||||
Err("TODO: Subscript native function".to_error())
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of native function")
|
||||
Err("Cannot assign to subscript of native function".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
@@ -103,3 +103,9 @@ impl ValTrait for NativeFunction {
|
||||
"function() { [native code] }".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for &'static NativeFunction {
|
||||
fn to_val(self) -> Val {
|
||||
Val::Static(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::builtins::error_builtin::ToError;
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::vs_value::{ToVal, ToValString};
|
||||
use crate::{builtins::range_error_builtin::to_range_error, range_error};
|
||||
use crate::{
|
||||
format_err, format_val,
|
||||
native_function::NativeFunction,
|
||||
todo_fn::TODO,
|
||||
vs_value::{Val, ValTrait},
|
||||
@@ -26,16 +25,19 @@ static TO_FIXED: NativeFunction = NativeFunction {
|
||||
Ok(match this.get() {
|
||||
Val::Number(number) => {
|
||||
if number.is_infinite() {
|
||||
return Ok(if number.is_sign_positive() {
|
||||
Val::String(Rc::new("Infinity".to_string()))
|
||||
} else {
|
||||
Val::String(Rc::new("-Infinity".to_string()))
|
||||
});
|
||||
return Ok(
|
||||
if number.is_sign_positive() {
|
||||
"Infinity"
|
||||
} else {
|
||||
"-Infinity"
|
||||
}
|
||||
.to_val(),
|
||||
);
|
||||
}
|
||||
|
||||
let mut precision = match params.get(0) {
|
||||
Some(p) => p.to_number(),
|
||||
_ => return Ok(Val::String(Rc::new(this.get().val_to_string()))),
|
||||
_ => return Ok(this.get().to_val_string()),
|
||||
};
|
||||
|
||||
precision = f64::floor(precision);
|
||||
@@ -44,9 +46,9 @@ static TO_FIXED: NativeFunction = NativeFunction {
|
||||
return range_error!("precision must be between 1 and 100");
|
||||
}
|
||||
|
||||
format_val!("{:.*}", precision as usize, number)
|
||||
format!("{:.*}", precision as usize, number).to_val()
|
||||
}
|
||||
_ => return format_err!("TODO: number indirection"),
|
||||
_ => return Err(format!("TODO: number indirection").to_val()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -67,7 +69,7 @@ static TO_EXPONENTIAL: NativeFunction = NativeFunction {
|
||||
}
|
||||
None => format_exponential(*number, None),
|
||||
},
|
||||
_ => return format_err!("number indirection"),
|
||||
_ => return Err("number indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -75,8 +77,8 @@ static TO_EXPONENTIAL: NativeFunction = NativeFunction {
|
||||
static TODO_LOCALE: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
match this.get() {
|
||||
Val::Number(_number) => return format_err!("TODO: locale"),
|
||||
_ => return format_err!("number indirection"),
|
||||
Val::Number(_number) => return Err("TODO: locale".to_error()),
|
||||
_ => return Err("number indirection".to_error()),
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -86,12 +88,12 @@ static TO_STRING: NativeFunction = NativeFunction {
|
||||
Ok(match this.get() {
|
||||
Val::Number(_) => match params.get(0) {
|
||||
Some(_) => {
|
||||
return format_err!("TODO: toString with radix");
|
||||
return Err("TODO: toString with radix".to_error());
|
||||
}
|
||||
|
||||
None => Val::String(Rc::new(this.get().val_to_string())),
|
||||
None => this.get().to_val_string(),
|
||||
},
|
||||
_ => return format_err!("number indirection"),
|
||||
_ => return Err("number indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -100,7 +102,7 @@ static VALUE_OF: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
Val::Number(number) => Val::Number(*number),
|
||||
_ => return format_err!("number indirection"),
|
||||
_ => return Err("number indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -108,10 +110,11 @@ static VALUE_OF: NativeFunction = NativeFunction {
|
||||
fn format_exponential(number: f64, precision: Option<usize>) -> Val {
|
||||
if number.is_infinite() {
|
||||
return if number.is_sign_positive() {
|
||||
Val::String(Rc::new("Infinity".to_string()))
|
||||
"Infinity"
|
||||
} else {
|
||||
Val::String(Rc::new("-Infinity".to_string()))
|
||||
};
|
||||
"-Infinity"
|
||||
}
|
||||
.to_val();
|
||||
}
|
||||
|
||||
let exp_format = match precision {
|
||||
@@ -125,7 +128,7 @@ fn format_exponential(number: f64, precision: Option<usize>) -> Val {
|
||||
|
||||
let exponent = match parts.next() {
|
||||
Some(e) => e,
|
||||
None => return Val::String(Rc::new(exp_format)),
|
||||
None => return exp_format.to_val(),
|
||||
};
|
||||
|
||||
let string = if exponent.starts_with('-') {
|
||||
@@ -134,5 +137,5 @@ fn format_exponential(number: f64, precision: Option<usize>) -> Val {
|
||||
format!("{}e+{}", mantissa, exponent)
|
||||
};
|
||||
|
||||
Val::String(Rc::new(string))
|
||||
string.to_val()
|
||||
}
|
||||
|
||||
@@ -4,17 +4,17 @@ use num_bigint::Sign;
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
use crate::bigint_methods::op_sub_bigint;
|
||||
use crate::format_err;
|
||||
use crate::format_val;
|
||||
use crate::builtins::error_builtin::ToError;
|
||||
use crate::builtins::type_error_builtin::ToTypeError;
|
||||
use crate::native_function::NativeFunction;
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::number_methods::op_sub_number;
|
||||
use crate::string_methods::op_sub_string;
|
||||
use crate::vs_value::ToVal;
|
||||
use crate::vs_value::Val;
|
||||
use crate::vs_value::ValTrait;
|
||||
use crate::vs_value::VsType;
|
||||
use crate::{builtins::range_error_builtin::to_range_error, range_error};
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
|
||||
pub fn op_plus(left: Val, right: Val) -> Result<Val, Val> {
|
||||
let left_prim = left.to_primitive();
|
||||
@@ -24,21 +24,19 @@ pub fn op_plus(left: Val, right: Val) -> Result<Val, Val> {
|
||||
let right_type = right_prim.typeof_();
|
||||
|
||||
if left_type == VsType::String || right_type == VsType::String {
|
||||
return Ok(Val::String(Rc::new(
|
||||
left_prim.val_to_string() + &right_prim.val_to_string(),
|
||||
)));
|
||||
return Ok((left_prim.val_to_string() + &right_prim.val_to_string()).to_val());
|
||||
}
|
||||
|
||||
if left_type == VsType::BigInt || right_type == VsType::BigInt {
|
||||
if left_type != right_type {
|
||||
return type_error!("Cannot mix BigInt and other types");
|
||||
return Err("Cannot mix BigInt and other types".to_type_error());
|
||||
}
|
||||
|
||||
match (left_prim.as_bigint_data(), right_prim.as_bigint_data()) {
|
||||
(Some(left_bigint), Some(right_bigint)) => {
|
||||
return Ok(Val::BigInt(left_bigint + right_bigint));
|
||||
}
|
||||
_ => return format_err!("TODO"),
|
||||
_ => return Err("TODO".to_error()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +53,9 @@ pub fn op_unary_plus(input: Val) -> Val {
|
||||
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 type_error!("Cannot mix BigInt with other types"),
|
||||
(Some(_), None) | (None, Some(_)) => {
|
||||
return Err("Cannot mix BigInt with other types".to_type_error())
|
||||
}
|
||||
_ => Ok(Val::Number(left.to_number() - right.to_number())),
|
||||
}
|
||||
}
|
||||
@@ -70,9 +70,7 @@ pub fn op_unary_minus(input: Val) -> Val {
|
||||
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(_)) => {
|
||||
type_error!("Cannot mix BigInt with other types")
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
|
||||
_ => Ok(Val::Number(left.to_number() * right.to_number())),
|
||||
}
|
||||
}
|
||||
@@ -80,9 +78,7 @@ pub fn op_mul(left: Val, right: Val) -> Result<Val, Val> {
|
||||
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(_)) => {
|
||||
type_error!("Cannot mix BigInt with other types")
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
|
||||
_ => Ok(Val::Number(left.to_number() / right.to_number())),
|
||||
}
|
||||
}
|
||||
@@ -90,9 +86,7 @@ pub fn op_div(left: Val, right: Val) -> Result<Val, Val> {
|
||||
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(_)) => {
|
||||
type_error!("Cannot mix BigInt with other types")
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
|
||||
_ => Ok(Val::Number(left.to_number() % right.to_number())),
|
||||
}
|
||||
}
|
||||
@@ -111,9 +105,7 @@ pub fn op_exp(left: Val, right: Val) -> Result<Val, Val> {
|
||||
|
||||
Ok(Val::BigInt(left_bigint.pow(exp)))
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => {
|
||||
type_error!("Cannot mix BigInt with other types")
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
|
||||
_ => Ok(Val::Number(left.to_number().powf(right.to_number()))),
|
||||
}
|
||||
}
|
||||
@@ -126,7 +118,7 @@ pub fn op_eq(left: Val, right: Val) -> Result<Val, Val> {
|
||||
(Val::Number(left_number), Val::Number(right_number)) => left_number == right_number,
|
||||
(Val::String(left_string), Val::String(right_string)) => left_string == right_string,
|
||||
(Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint == right_bigint,
|
||||
_ => return format_err!("TODO"),
|
||||
_ => return Err("TODO".to_error()),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -138,7 +130,7 @@ pub fn op_ne(left: Val, right: Val) -> Result<Val, Val> {
|
||||
(Val::Number(left_number), Val::Number(right_number)) => left_number != right_number,
|
||||
(Val::String(left_string), Val::String(right_string)) => left_string != right_string,
|
||||
(Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint != right_bigint,
|
||||
_ => return format_err!("TODO"),
|
||||
_ => return Err("TODO".to_error()),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -154,7 +146,7 @@ pub fn op_triple_eq_impl(left: Val, right: Val) -> Result<bool, Val> {
|
||||
if left.typeof_() != right.typeof_() {
|
||||
false
|
||||
} else {
|
||||
return format_err!("TODO");
|
||||
return Err("TODO".to_error());
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -194,7 +186,7 @@ pub fn op_less(left: Val, right: Val) -> Result<Val, Val> {
|
||||
if left.typeof_() == VsType::Undefined || right.typeof_() == VsType::Undefined {
|
||||
false
|
||||
} else {
|
||||
return format_err!("TODO");
|
||||
return Err("TODO".to_error());
|
||||
}
|
||||
}
|
||||
}))
|
||||
@@ -208,7 +200,7 @@ pub fn op_less_eq(left: Val, right: Val) -> Result<Val, Val> {
|
||||
(Val::Number(left_number), Val::Number(right_number)) => left_number <= right_number,
|
||||
(Val::String(left_string), Val::String(right_string)) => left_string <= right_string,
|
||||
(Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint <= right_bigint,
|
||||
_ => return format_err!("TODO"),
|
||||
_ => return Err("TODO".to_type_error()),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -220,7 +212,7 @@ pub fn op_greater(left: Val, right: Val) -> Result<Val, Val> {
|
||||
(Val::Number(left_number), Val::Number(right_number)) => left_number > right_number,
|
||||
(Val::String(left_string), Val::String(right_string)) => left_string > right_string,
|
||||
(Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint > right_bigint,
|
||||
_ => return format_err!("TODO"),
|
||||
_ => return Err("TODO".to_error()),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -232,7 +224,7 @@ pub fn op_greater_eq(left: Val, right: Val) -> Result<Val, Val> {
|
||||
(Val::Number(left_number), Val::Number(right_number)) => left_number >= right_number,
|
||||
(Val::String(left_string), Val::String(right_string)) => left_string >= right_string,
|
||||
(Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint >= right_bigint,
|
||||
_ => return format_err!("TODO"),
|
||||
_ => return Err("TODO".to_type_error()),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -271,9 +263,7 @@ pub fn to_u32(x: f64) -> u32 {
|
||||
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(_)) => {
|
||||
type_error!("Cannot mix BigInt with other types")
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
|
||||
_ => {
|
||||
let res_i32 = to_i32(left.to_number()) & to_i32(right.to_number());
|
||||
Ok(Val::Number(res_i32 as f64))
|
||||
@@ -284,9 +274,7 @@ pub fn op_bit_and(left: Val, right: Val) -> Result<Val, Val> {
|
||||
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(_)) => {
|
||||
type_error!("Cannot mix BigInt with other types")
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
|
||||
_ => {
|
||||
let res_i32 = to_i32(left.to_number()) | to_i32(right.to_number());
|
||||
Ok(Val::Number(res_i32 as f64))
|
||||
@@ -307,9 +295,7 @@ pub fn op_bit_not(input: Val) -> Val {
|
||||
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(_)) => {
|
||||
type_error!("Cannot mix BigInt with other types")
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
|
||||
_ => {
|
||||
let res_i32 = to_i32(left.to_number()) ^ to_i32(right.to_number());
|
||||
Ok(Val::Number(res_i32 as f64))
|
||||
@@ -322,9 +308,7 @@ pub fn op_left_shift(left: Val, right: Val) -> Result<Val, Val> {
|
||||
(Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(
|
||||
left_bigint << right_bigint.to_i64().expect("TODO"),
|
||||
)),
|
||||
(Some(_), None) | (None, Some(_)) => {
|
||||
type_error!("Cannot mix BigInt with other types")
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
|
||||
_ => {
|
||||
let res_i32 = to_i32(left.to_number()) << (to_u32(right.to_number()) & 0x1f);
|
||||
Ok(Val::Number(res_i32 as f64))
|
||||
@@ -335,12 +319,10 @@ pub fn op_left_shift(left: Val, right: Val) -> Result<Val, Val> {
|
||||
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(format_val!("TODO"))?;
|
||||
let right_i64 = right_bigint.to_i64().ok_or("TODO".to_val())?;
|
||||
Ok(Val::BigInt(left_bigint >> right_i64))
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => {
|
||||
type_error!("Cannot mix BigInt with other types")
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
|
||||
_ => {
|
||||
let res_i32 = to_i32(left.to_number()) >> (to_u32(right.to_number()) & 0x1f);
|
||||
Ok(Val::Number(res_i32 as f64))
|
||||
@@ -350,12 +332,8 @@ pub fn op_right_shift(left: Val, right: Val) -> Result<Val, Val> {
|
||||
|
||||
pub fn op_right_shift_unsigned(left: Val, right: Val) -> Result<Val, Val> {
|
||||
match (left.as_bigint_data(), right.as_bigint_data()) {
|
||||
(Some(_), Some(_)) => {
|
||||
type_error!("BigInts don't support unsigned right shift")
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => {
|
||||
type_error!("Cannot mix BigInt with other types")
|
||||
}
|
||||
(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.to_number()) >> (to_u32(right.to_number()) & 0x1f);
|
||||
Ok(Val::Number(res_u32 as f64))
|
||||
@@ -366,34 +344,35 @@ pub fn op_right_shift_unsigned(left: Val, right: Val) -> Result<Val, Val> {
|
||||
pub fn op_typeof(input: Val) -> Val {
|
||||
use VsType::*;
|
||||
|
||||
return Val::String(Rc::new(match input.typeof_() {
|
||||
Undefined => "undefined".to_string(),
|
||||
Null => "object".to_string(),
|
||||
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(),
|
||||
Function => "function".to_string(),
|
||||
Class => "function".to_string(),
|
||||
}));
|
||||
match input.typeof_() {
|
||||
Undefined => "undefined",
|
||||
Null => "object",
|
||||
Bool => "boolean",
|
||||
Number => "number",
|
||||
BigInt => "bigint",
|
||||
Symbol => "symbol",
|
||||
String => "string",
|
||||
Array => "object",
|
||||
Object => "object",
|
||||
Function => "function",
|
||||
Class => "function",
|
||||
}
|
||||
.to_val()
|
||||
}
|
||||
|
||||
pub fn op_instance_of(_left: Val, _right: Val) -> Result<Val, Val> {
|
||||
format_err!("TODO: op_instance_of")
|
||||
Err("TODO: op_instance_of".to_error())
|
||||
}
|
||||
|
||||
pub fn op_in(_left: Val, _right: Val) -> Result<Val, Val> {
|
||||
format_err!("TODO: op_in")
|
||||
Err("TODO: op_in".to_error())
|
||||
}
|
||||
|
||||
pub fn op_sub(left: Val, right: Val) -> Result<Val, Val> {
|
||||
return match left {
|
||||
Val::Void => format_err!("Internal: Shouldn't happen"), // TODO: Internal errors
|
||||
Val::Undefined => type_error!("Cannot subscript undefined"),
|
||||
Val::Null => type_error!("Cannot subscript null"),
|
||||
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.val_to_string().as_str() {
|
||||
"toString" => Val::Static(&BOOL_TO_STRING),
|
||||
"valueOf" => Val::Static(&BOOL_VALUE_OF),
|
||||
@@ -437,18 +416,18 @@ 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 => 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::Void => Err("Internal: Shouldn't happen".to_error()), // TODO: Internal errors
|
||||
Val::Undefined => Err("Cannot assign to subscript of undefined".to_type_error()),
|
||||
Val::Null => Err("Cannot assign to subscript of null".to_type_error()),
|
||||
Val::Bool(_) => Err("Cannot assign to subscript of bool".to_type_error()),
|
||||
Val::Number(_) => Err("Cannot assign to subscript of number".to_type_error()),
|
||||
Val::BigInt(_) => Err("Cannot assign to subscript of bigint".to_type_error()),
|
||||
Val::Symbol(_) => Err("Cannot assign to subscript of symbol".to_type_error()),
|
||||
Val::String(_) => Err("Cannot assign to subscript of string".to_type_error()),
|
||||
Val::Array(array_data) => {
|
||||
let subscript_index = match subscript.to_index() {
|
||||
// TODO: Internal errors
|
||||
None => return format_err!("TODO: non-uint array subscript assignment"),
|
||||
None => return Err("TODO: non-uint array subscript assignment".to_type_error()),
|
||||
Some(i) => i,
|
||||
};
|
||||
|
||||
@@ -458,7 +437,7 @@ pub fn op_submov(target: &mut Val, subscript: Val, value: Val) -> Result<(), Val
|
||||
array_data_mut.elements[subscript_index] = value;
|
||||
} else {
|
||||
if subscript_index - array_data_mut.elements.len() > 100 {
|
||||
return format_err!("TODO: Sparse arrays");
|
||||
return Err("TODO: Sparse arrays".to_type_error());
|
||||
}
|
||||
|
||||
while subscript_index > array_data_mut.elements.len() {
|
||||
@@ -483,18 +462,18 @@ pub fn op_submov(target: &mut Val, subscript: Val, value: Val) -> Result<(), Val
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Val::Function(_) => format_err!("TODO: function subscript assignment"),
|
||||
Val::Class(_) => format_err!("Cannot assign to subscript of class"),
|
||||
Val::Static(_) => format_err!("Cannot assign to subscript of static value"),
|
||||
Val::Custom(_) => format_err!("TODO: Assign to subscript of custom value"),
|
||||
Val::Function(_) => Err("TODO: function subscript assignment".to_type_error()),
|
||||
Val::Class(_) => Err("Cannot assign to subscript of class".to_type_error()),
|
||||
Val::Static(_) => Err("Cannot assign to subscript of static value".to_type_error()),
|
||||
Val::Custom(_) => Err("TODO: Assign to subscript of custom value".to_type_error()),
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL_TO_STRING: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
Val::Bool(b) => Val::String(Rc::new(b.to_string())),
|
||||
_ => return format_err!("bool indirection"),
|
||||
Val::Bool(b) => b.to_string().to_val(),
|
||||
_ => return Err("bool indirection".to_type_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -503,7 +482,7 @@ static BOOL_VALUE_OF: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
Val::Bool(b) => Val::Bool(*b),
|
||||
_ => return format_err!("bool indirection"),
|
||||
_ => return Err("bool indirection".to_type_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use std::{rc::Rc, str::Chars};
|
||||
|
||||
use crate::{
|
||||
format_err,
|
||||
builtins::error_builtin::ToError,
|
||||
helpers::{to_wrapping_index, to_wrapping_index_clamped},
|
||||
native_function::{NativeFunction, ThisWrapper},
|
||||
vs_array::VsArray,
|
||||
vs_value::Val,
|
||||
vs_value::{ToVal, Val},
|
||||
ValTrait,
|
||||
};
|
||||
|
||||
@@ -30,8 +29,8 @@ pub fn op_sub_string(string_data: &Rc<String>, subscript: &Val) -> Val {
|
||||
}
|
||||
|
||||
match unicode_at(string_bytes, string_bytes.len(), right_index) {
|
||||
Some(char) => Val::String(Rc::new(char.to_string())),
|
||||
None => Val::String(Rc::new(String::from(""))),
|
||||
Some(char) => char.to_string().to_val(),
|
||||
None => "".to_val(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,11 +95,11 @@ static AT: NativeFunction = NativeFunction {
|
||||
};
|
||||
|
||||
match unicode_at(string_bytes, string_bytes.len(), index) {
|
||||
Some(char) => Val::String(Rc::new(char.to_string())),
|
||||
None => Val::String(Rc::new(String::from(""))),
|
||||
Some(char) => char.to_string().to_val(),
|
||||
None => "".to_val(),
|
||||
}
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -124,7 +123,7 @@ static CODE_POINT_AT: NativeFunction = NativeFunction {
|
||||
None => Val::Undefined,
|
||||
}
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -139,9 +138,9 @@ static CONCAT: NativeFunction = NativeFunction {
|
||||
result.push_str(param.val_to_string().as_str());
|
||||
}
|
||||
|
||||
Val::String(Rc::new(result))
|
||||
result.to_val()
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -184,7 +183,7 @@ static ENDS_WITH: NativeFunction = NativeFunction {
|
||||
|
||||
Val::Bool(true)
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -216,7 +215,7 @@ static INCLUDES: NativeFunction = NativeFunction {
|
||||
None => Val::Bool(false),
|
||||
}
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -248,7 +247,7 @@ static INDEX_OF: NativeFunction = NativeFunction {
|
||||
None => Val::Number(-1.0),
|
||||
}
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -280,7 +279,7 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction {
|
||||
None => Val::Number(-1.0),
|
||||
}
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -290,9 +289,9 @@ static TODO_LOCALE: NativeFunction = NativeFunction {
|
||||
// TODO: Ok(...)
|
||||
match this.get() {
|
||||
Val::String(_string_data) => {
|
||||
return format_err!("TODO: locale");
|
||||
return Err("TODO: locale".to_error());
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -302,9 +301,9 @@ static TODO_REGEXES: NativeFunction = NativeFunction {
|
||||
// TODO: Ok(...)
|
||||
match this.get() {
|
||||
Val::String(_string_data) => {
|
||||
return format_err!("TODO: regexes");
|
||||
return Err("TODO: regexes".to_error());
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -315,9 +314,9 @@ static NORMALIZE: NativeFunction = NativeFunction {
|
||||
match this.get() {
|
||||
Val::String(_string_data) => {
|
||||
// Consider https://docs.rs/unicode-normalization/latest/unicode_normalization/
|
||||
return format_err!("TODO: normalize");
|
||||
return Err("TODO: normalize".to_error());
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -369,9 +368,9 @@ static PAD_END: NativeFunction = NativeFunction {
|
||||
}
|
||||
}
|
||||
|
||||
Val::String(Rc::new(string))
|
||||
string.to_val()
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -425,9 +424,9 @@ static PAD_START: NativeFunction = NativeFunction {
|
||||
|
||||
prefix.push_str(string_data);
|
||||
|
||||
Val::String(Rc::new(prefix))
|
||||
prefix.to_val()
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -450,9 +449,9 @@ static REPEAT: NativeFunction = NativeFunction {
|
||||
result.push_str(string_data);
|
||||
}
|
||||
|
||||
Val::String(Rc::new(result))
|
||||
result.to_val()
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -484,9 +483,9 @@ static SLICE: NativeFunction = NativeFunction {
|
||||
}
|
||||
}
|
||||
|
||||
Val::String(Rc::new(new_string))
|
||||
new_string.to_val()
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -512,19 +511,19 @@ static SPLIT: NativeFunction = NativeFunction {
|
||||
let mut result = Vec::<Val>::new();
|
||||
|
||||
if limit == 0 {
|
||||
return Ok(Val::Array(Rc::new(VsArray::from(result))));
|
||||
return Ok(result.to_val());
|
||||
}
|
||||
|
||||
if separator.is_empty() {
|
||||
for c in string_data.chars() {
|
||||
result.push(Val::String(Rc::new(c.to_string())));
|
||||
result.push(c.to_val());
|
||||
|
||||
if result.len() == limit {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(Val::Array(Rc::new(VsArray::from(result))));
|
||||
return Ok(result.to_val());
|
||||
}
|
||||
|
||||
let mut part = String::new();
|
||||
@@ -534,7 +533,7 @@ static SPLIT: NativeFunction = NativeFunction {
|
||||
if match_chars(&mut str_chars, &separator) {
|
||||
let mut new_part = String::new();
|
||||
std::mem::swap(&mut new_part, &mut part);
|
||||
result.push(Val::String(Rc::new(new_part)));
|
||||
result.push(new_part.to_val());
|
||||
|
||||
if result.len() == limit {
|
||||
break;
|
||||
@@ -543,16 +542,16 @@ static SPLIT: NativeFunction = NativeFunction {
|
||||
match str_chars.next() {
|
||||
Some(c) => part.push(c),
|
||||
None => {
|
||||
result.push(Val::String(Rc::new(part)));
|
||||
result.push(part.to_val());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Val::Array(Rc::new(VsArray::from(result)))
|
||||
result.to_val()
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -593,7 +592,7 @@ static STARTS_WITH: NativeFunction = NativeFunction {
|
||||
|
||||
Val::Bool(true)
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -634,9 +633,9 @@ static SUBSTRING: NativeFunction = NativeFunction {
|
||||
}
|
||||
}
|
||||
|
||||
Val::String(Rc::new(new_string))
|
||||
new_string.to_val()
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -644,11 +643,8 @@ static SUBSTRING: NativeFunction = NativeFunction {
|
||||
static TO_LOWER_CASE: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
Val::String(string_data) => {
|
||||
let lowercased_string = string_data.to_lowercase();
|
||||
Val::String(Rc::new(lowercased_string))
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
Val::String(string_data) => string_data.to_lowercase().to_val(),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -657,7 +653,7 @@ static TO_STRING: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
Val::String(string_data) => Val::String(string_data.clone()),
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -665,11 +661,8 @@ static TO_STRING: NativeFunction = NativeFunction {
|
||||
static TO_UPPER_CASE: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
Val::String(string_data) => {
|
||||
let uppercased_string = string_data.to_uppercase();
|
||||
Val::String(Rc::new(uppercased_string))
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
Val::String(string_data) => string_data.to_uppercase().to_val(),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -677,11 +670,8 @@ static TO_UPPER_CASE: NativeFunction = NativeFunction {
|
||||
static TRIM: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
Val::String(string_data) => {
|
||||
let trimmed_string = string_data.trim();
|
||||
Val::String(Rc::new(trimmed_string.to_owned()))
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
Val::String(string_data) => string_data.trim().to_val(),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -689,11 +679,8 @@ static TRIM: NativeFunction = NativeFunction {
|
||||
static TRIM_END: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
Val::String(string_data) => {
|
||||
let trimmed_string = string_data.trim_end();
|
||||
Val::String(Rc::new(trimmed_string.to_owned()))
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
Val::String(string_data) => string_data.trim_end().to_val(),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -701,11 +688,8 @@ static TRIM_END: NativeFunction = NativeFunction {
|
||||
static TRIM_START: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
Val::String(string_data) => {
|
||||
let trimmed_string = string_data.trim_start();
|
||||
Val::String(Rc::new(trimmed_string.to_owned()))
|
||||
}
|
||||
_ => return format_err!("string indirection"),
|
||||
Val::String(string_data) => string_data.trim_start().to_val(),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -714,7 +698,7 @@ static VALUE_OF: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
Val::String(string_data) => Val::String(string_data.clone()),
|
||||
_ => return format_err!("string indirection"),
|
||||
_ => return Err("string indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::{
|
||||
format_err,
|
||||
builtins::error_builtin::ToError,
|
||||
native_function::{NativeFunction, ThisWrapper},
|
||||
vs_value::Val,
|
||||
};
|
||||
|
||||
pub static TODO: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
match this.get() {
|
||||
Val::Number(_number) => return format_err!("TODO: locale"),
|
||||
_ => return format_err!("number indirection"),
|
||||
}
|
||||
},
|
||||
fn_: |_: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> { Err("TODO".to_error()) },
|
||||
};
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::builtins::error_builtin::to_error;
|
||||
use crate::builtins::error_builtin::ToError;
|
||||
use crate::bytecode_decoder::BytecodeDecoder;
|
||||
use crate::error;
|
||||
use crate::first_stack_frame::FirstStackFrame;
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::stack_frame::FrameStepOk;
|
||||
use crate::stack_frame::StackFrame;
|
||||
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
|
||||
@@ -52,7 +50,7 @@ impl VirtualMachine {
|
||||
}
|
||||
}
|
||||
|
||||
error!("step limit reached")
|
||||
Err("step limit reached".to_error())
|
||||
}
|
||||
None => {
|
||||
while self.stack.len() > 0 {
|
||||
|
||||
@@ -8,14 +8,15 @@ use crate::array_higher_functions::{
|
||||
array_flat_map::FLAT_MAP, array_map::MAP, array_reduce::REDUCE, array_reduce_right::REDUCE_RIGHT,
|
||||
array_some::SOME, array_sort::SORT,
|
||||
};
|
||||
use crate::format_err;
|
||||
use crate::builtins::error_builtin::ToError;
|
||||
use crate::builtins::type_error_builtin::ToTypeError;
|
||||
use crate::helpers::{to_wrapping_index, to_wrapping_index_clamped};
|
||||
use crate::native_function::{NativeFunction, ThisWrapper};
|
||||
use crate::operations::op_triple_eq_impl;
|
||||
use crate::todo_fn::TODO;
|
||||
use crate::vs_class::VsClass;
|
||||
use crate::vs_object::VsObject;
|
||||
use crate::vs_value::{LoadFunctionResult, Val, ValTrait, VsType};
|
||||
use crate::{builtins::type_error_builtin::to_type_error, type_error};
|
||||
use crate::vs_value::{LoadFunctionResult, ToVal, ToValString, Val, ValTrait, VsType};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VsArray {
|
||||
@@ -47,6 +48,12 @@ impl VsArray {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for VsArray {
|
||||
fn to_val(self) -> Val {
|
||||
Val::Array(Rc::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ArrayPrototype {}
|
||||
|
||||
static ARRAY_PROTOTYPE: ArrayPrototype = ArrayPrototype {};
|
||||
@@ -68,7 +75,7 @@ impl ValTrait for ArrayPrototype {
|
||||
false
|
||||
}
|
||||
fn to_primitive(&self) -> Val {
|
||||
Val::String(Rc::new("".to_string()))
|
||||
self.to_val_string()
|
||||
}
|
||||
fn is_truthy(&self) -> bool {
|
||||
true
|
||||
@@ -116,7 +123,7 @@ impl ValTrait for ArrayPrototype {
|
||||
"includes" => &INCLUDES,
|
||||
"indexOf" => &INDEX_OF,
|
||||
"join" => &JOIN,
|
||||
"keys" => &KEYS,
|
||||
"keys" => &TODO,
|
||||
"lastIndexOf" => &LAST_INDEX_OF,
|
||||
"map" => &MAP,
|
||||
"pop" => &POP,
|
||||
@@ -129,16 +136,16 @@ impl ValTrait for ArrayPrototype {
|
||||
"some" => &SOME,
|
||||
"sort" => &SORT,
|
||||
"splice" => &SPLICE,
|
||||
"toLocaleString" => &TO_LOCALE_STRING,
|
||||
"toLocaleString" => &TODO,
|
||||
"toString" => &TO_STRING,
|
||||
"unshift" => &UNSHIFT,
|
||||
"values" => &VALUES,
|
||||
"values" => &TODO,
|
||||
_ => return Ok(Val::Undefined),
|
||||
}))
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
type_error!("Cannot assign to subscript of Array.prototype")
|
||||
Err("Cannot assign to subscript of Array.prototype".to_type_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
@@ -161,7 +168,7 @@ static AT: NativeFunction = NativeFunction {
|
||||
None => Val::Undefined,
|
||||
Some(i) => array_data.elements[i].clone(),
|
||||
},
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -185,9 +192,9 @@ static CONCAT: NativeFunction = NativeFunction {
|
||||
}
|
||||
}
|
||||
|
||||
Val::Array(Rc::new(new_array))
|
||||
new_array.to_val()
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -202,7 +209,7 @@ static COPY_WITHIN: NativeFunction = NativeFunction {
|
||||
let ulen = array_data_mut.elements.len();
|
||||
|
||||
if ulen > isize::MAX as usize {
|
||||
return format_err!("TODO: array len exceeds isize");
|
||||
return Err("TODO: array len exceeds isize".to_error());
|
||||
}
|
||||
|
||||
let mut target = match params.get(0) {
|
||||
@@ -261,7 +268,7 @@ static COPY_WITHIN: NativeFunction = NativeFunction {
|
||||
|
||||
this.clone()
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -269,8 +276,8 @@ static COPY_WITHIN: NativeFunction = NativeFunction {
|
||||
static ENTRIES: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
match this.get() {
|
||||
Val::Array(_array_data) => return format_err!("TODO: iterators"),
|
||||
_ => return format_err!("array indirection"),
|
||||
Val::Array(_array_data) => return Err("TODO: iterators".to_error()),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -302,7 +309,7 @@ static FILL: NativeFunction = NativeFunction {
|
||||
|
||||
this.clone()
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -312,7 +319,7 @@ static FLAT: NativeFunction = NativeFunction {
|
||||
Ok(match this.get() {
|
||||
Val::Array(array_data) => {
|
||||
if params.len() > 0 {
|
||||
return format_err!("TODO: .flat depth parameter");
|
||||
return Err("TODO: .flat depth parameter".to_error());
|
||||
}
|
||||
|
||||
let mut new_elems = Vec::<Val>::new();
|
||||
@@ -330,9 +337,9 @@ static FLAT: NativeFunction = NativeFunction {
|
||||
}
|
||||
}
|
||||
|
||||
Val::Array(Rc::new(VsArray::from(new_elems)))
|
||||
new_elems.to_val()
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -355,7 +362,7 @@ static INCLUDES: NativeFunction = NativeFunction {
|
||||
|
||||
Val::Bool(false)
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -378,7 +385,7 @@ static INDEX_OF: NativeFunction = NativeFunction {
|
||||
|
||||
Val::Number(-1.0)
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -388,11 +395,11 @@ static JOIN: NativeFunction = NativeFunction {
|
||||
Ok(match this.get() {
|
||||
Val::Array(vals) => {
|
||||
if vals.elements.len() == 0 {
|
||||
return Ok(Val::String(Rc::new("".to_string())));
|
||||
return Ok("".to_val());
|
||||
}
|
||||
|
||||
if vals.elements.len() == 1 {
|
||||
return Ok(Val::String(Rc::new(vals.elements[0].val_to_string())));
|
||||
return Ok(vals.elements[0].to_val_string());
|
||||
}
|
||||
|
||||
let separator = params.get(0).unwrap_or(&Val::Undefined);
|
||||
@@ -416,25 +423,13 @@ static JOIN: NativeFunction = NativeFunction {
|
||||
};
|
||||
}
|
||||
|
||||
Val::String(Rc::new(res))
|
||||
res.to_val()
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
static KEYS: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
// TODO: Ok(...)
|
||||
match this.get() {
|
||||
Val::Array(_array_data) => {
|
||||
return format_err!("TODO: KEYS");
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
static LAST_INDEX_OF: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(match this.get() {
|
||||
@@ -453,7 +448,7 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction {
|
||||
|
||||
Val::Number(-1_f64)
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -479,7 +474,7 @@ static POP: NativeFunction = NativeFunction {
|
||||
_ => removed_el,
|
||||
}
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -498,7 +493,7 @@ static PUSH: NativeFunction = NativeFunction {
|
||||
|
||||
Val::Number(array_data_mut.elements.len() as f64)
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -527,7 +522,7 @@ static REVERSE: NativeFunction = NativeFunction {
|
||||
|
||||
this.clone()
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -546,7 +541,7 @@ static SHIFT: NativeFunction = NativeFunction {
|
||||
|
||||
array_data_mut.elements.remove(0)
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -571,9 +566,9 @@ static SLICE: NativeFunction = NativeFunction {
|
||||
new_elems.push(array_data.elements[i as usize].clone());
|
||||
}
|
||||
|
||||
Val::Array(Rc::new(VsArray::from(new_elems)))
|
||||
new_elems.to_val()
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
@@ -650,29 +645,17 @@ static SPLICE: NativeFunction = NativeFunction {
|
||||
}
|
||||
}
|
||||
|
||||
Val::Array(Rc::new(VsArray::from(deleted_elements)))
|
||||
deleted_elements.to_val()
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
static TO_LOCALE_STRING: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
// TODO: Ok(...)
|
||||
match this.get() {
|
||||
Val::Array(_array_data) => {
|
||||
return format_err!("TODO: TO_LOCALE_STRING");
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
// TODO: Share this? (JS doesn't?)
|
||||
static TO_STRING: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
Ok(Val::String(Rc::new(this.get().val_to_string())))
|
||||
Ok(this.get().to_val_string())
|
||||
},
|
||||
};
|
||||
|
||||
@@ -693,19 +676,7 @@ static UNSHIFT: NativeFunction = NativeFunction {
|
||||
|
||||
Val::Number(array_data_mut.elements.len() as f64)
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
_ => return Err("array indirection".to_error()),
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
static VALUES: NativeFunction = NativeFunction {
|
||||
fn_: |this: ThisWrapper, _params: Vec<Val>| -> Result<Val, Val> {
|
||||
// TODO: Ok(...)
|
||||
match this.get() {
|
||||
Val::Array(_array_data) => {
|
||||
return format_err!("TODO: VALUES");
|
||||
}
|
||||
_ => return format_err!("array indirection"),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::vs_value::ToVal;
|
||||
|
||||
use super::vs_value::Val;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -7,3 +11,9 @@ pub struct VsClass {
|
||||
}
|
||||
|
||||
impl VsClass {}
|
||||
|
||||
impl ToVal for VsClass {
|
||||
fn to_val(self) -> Val {
|
||||
Val::Class(Rc::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::vs_value::ToVal;
|
||||
|
||||
use super::bytecode_decoder::BytecodeDecoder;
|
||||
use super::bytecode_stack_frame::BytecodeStackFrame;
|
||||
use super::stack_frame::StackFrame;
|
||||
@@ -60,3 +62,9 @@ impl VsFunction {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for VsFunction {
|
||||
fn to_val(self) -> Val {
|
||||
Val::Function(Rc::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::vs_symbol::VsSymbol;
|
||||
use crate::vs_value::ToVal;
|
||||
|
||||
use super::operations::op_sub;
|
||||
use super::vs_value::{Val, ValTrait};
|
||||
@@ -32,3 +34,9 @@ impl VsObject {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for VsObject {
|
||||
fn to_val(self) -> Val {
|
||||
Val::Object(Rc::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ use std::rc::Rc;
|
||||
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::format_err;
|
||||
use crate::builtins::error_builtin::ToError;
|
||||
use crate::vs_value::ToVal;
|
||||
|
||||
use super::bytecode_decoder::{BytecodeDecoder, BytecodeType};
|
||||
use super::vs_array::VsArray;
|
||||
@@ -18,12 +19,12 @@ pub struct VsPointer {
|
||||
}
|
||||
|
||||
impl VsPointer {
|
||||
pub fn new(bytecode: &Rc<Vec<u8>>, pos: usize) -> Val {
|
||||
return Val::Custom(Rc::new(VsPointer {
|
||||
pub fn new(bytecode: &Rc<Vec<u8>>, pos: usize) -> VsPointer {
|
||||
VsPointer {
|
||||
bytecode: bytecode.clone(),
|
||||
pos,
|
||||
resolved: RefCell::new(None),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve(&self) -> Val {
|
||||
@@ -146,7 +147,7 @@ impl ValTrait for VsPointer {
|
||||
}
|
||||
|
||||
fn submov(&mut self, _subscript: Val, _value: Val) -> Result<(), Val> {
|
||||
format_err!("TODO: Probably an exception, but might be possible")
|
||||
Err("TODO: Probably an exception, but might be possible".to_error())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> LoadFunctionResult {
|
||||
@@ -161,3 +162,9 @@ impl ValTrait for VsPointer {
|
||||
self.resolve().codify()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for VsPointer {
|
||||
fn to_val(self) -> Val {
|
||||
Val::Custom(Rc::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,7 @@ use num_bigint::BigInt;
|
||||
use num_traits::cast::ToPrimitive;
|
||||
use num_traits::Zero;
|
||||
|
||||
use crate::format_val;
|
||||
use crate::native_function::ThisWrapper;
|
||||
use crate::native_function::{NativeFunction, ThisWrapper};
|
||||
use crate::operations::{op_sub, op_submov};
|
||||
use crate::stack_frame::StackFrame;
|
||||
use crate::vs_array::VsArray;
|
||||
@@ -55,6 +54,37 @@ pub enum LoadFunctionResult {
|
||||
NativeFunction(fn(this: ThisWrapper, params: Vec<Val>) -> Result<Val, Val>),
|
||||
}
|
||||
|
||||
pub trait ToLoadFunctionResult {
|
||||
fn to_load_function_result(self) -> LoadFunctionResult;
|
||||
}
|
||||
|
||||
impl ToLoadFunctionResult for StackFrame {
|
||||
fn to_load_function_result(self) -> LoadFunctionResult {
|
||||
LoadFunctionResult::StackFrame(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToLoadFunctionResult for fn(this: ThisWrapper, params: Vec<Val>) -> Result<Val, Val> {
|
||||
fn to_load_function_result(self) -> LoadFunctionResult {
|
||||
LoadFunctionResult::NativeFunction(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToLoadFunctionResult for NativeFunction {
|
||||
fn to_load_function_result(self) -> LoadFunctionResult {
|
||||
self.fn_.to_load_function_result()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for LoadFunctionResult
|
||||
where
|
||||
T: ToLoadFunctionResult,
|
||||
{
|
||||
fn from(value: T) -> Self {
|
||||
value.to_load_function_result()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ValTrait {
|
||||
fn typeof_(&self) -> VsType;
|
||||
fn val_to_string(&self) -> String;
|
||||
@@ -238,10 +268,10 @@ impl ValTrait for Val {
|
||||
|
||||
fn to_primitive(&self) -> Val {
|
||||
if self.is_primitive() {
|
||||
return self.clone();
|
||||
self.clone()
|
||||
} else {
|
||||
self.to_val_string()
|
||||
}
|
||||
|
||||
return Val::String(Rc::new(self.val_to_string()));
|
||||
}
|
||||
|
||||
fn is_truthy(&self) -> bool {
|
||||
@@ -290,7 +320,7 @@ impl ValTrait for Val {
|
||||
use Val::*;
|
||||
|
||||
return match self {
|
||||
Function(f) => Some(Val::Function(Rc::new(f.bind(params)))),
|
||||
Function(f) => Some(f.bind(params).to_val()),
|
||||
Custom(val) => val.bind(params),
|
||||
|
||||
_ => None,
|
||||
@@ -368,7 +398,7 @@ impl ValTrait for Val {
|
||||
match self {
|
||||
// TODO: iterator
|
||||
_ => {
|
||||
let next_fn = op_sub(self.clone(), Val::String(Rc::new("next".into())));
|
||||
let next_fn = op_sub(self.clone(), "next".to_val());
|
||||
|
||||
match next_fn {
|
||||
Ok(next_fn) => next_fn.load_function(),
|
||||
@@ -416,7 +446,7 @@ impl ValTrait for Val {
|
||||
let mut res = String::new();
|
||||
|
||||
if let Some(proto) = &object.prototype {
|
||||
match op_sub(proto.clone(), format_val!("name")) {
|
||||
match op_sub(proto.clone(), "name".to_val()) {
|
||||
Ok(name) => {
|
||||
if name.typeof_() == VsType::String {
|
||||
res += format!("{}", name.val_to_string()).as_str();
|
||||
@@ -459,6 +489,71 @@ impl ValTrait for Val {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToValString {
|
||||
fn to_val_string(&self) -> Val;
|
||||
}
|
||||
|
||||
impl<T: ValTrait> ToValString for T {
|
||||
fn to_val_string(&self) -> Val {
|
||||
Val::String(Rc::new(self.val_to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToVal {
|
||||
fn to_val(self) -> Val;
|
||||
}
|
||||
|
||||
impl<T> From<T> for Val
|
||||
where
|
||||
T: ToVal,
|
||||
{
|
||||
fn from(value: T) -> Val {
|
||||
value.to_val()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for char {
|
||||
fn to_val(self) -> Val {
|
||||
self.to_string().to_val()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for &str {
|
||||
fn to_val(self) -> Val {
|
||||
Val::String(Rc::new(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for String {
|
||||
fn to_val(self) -> Val {
|
||||
Val::String(Rc::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for f64 {
|
||||
fn to_val(self) -> Val {
|
||||
Val::Number(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for bool {
|
||||
fn to_val(self) -> Val {
|
||||
Val::Bool(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for BigInt {
|
||||
fn to_val(self) -> Val {
|
||||
Val::BigInt(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToVal for Vec<Val> {
|
||||
fn to_val(self) -> Val {
|
||||
Val::Array(Rc::new(VsArray::from(self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Val {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
@@ -493,7 +588,7 @@ impl std::fmt::Display for Val {
|
||||
}
|
||||
Val::Object(object) => {
|
||||
if let Some(proto) = &object.prototype {
|
||||
match op_sub(proto.clone(), format_val!("name")) {
|
||||
match op_sub(proto.clone(), "name".to_val()) {
|
||||
Ok(name) => {
|
||||
if name.typeof_() == VsType::String {
|
||||
write!(f, "{} ", name.val_to_string())?;
|
||||
|
||||
Reference in New Issue
Block a user