mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
Implement ArrayIterator.next
This commit is contained in:
@@ -3,13 +3,17 @@ use std::{fmt, rc::Rc};
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use crate::{
|
||||
builtins::type_error_builtin::ToTypeError,
|
||||
builtins::{error_builtin::ToError, type_error_builtin::ToTypeError},
|
||||
native_function::{native_fn, NativeFunction},
|
||||
vs_array::VsArray,
|
||||
vs_class::VsClass,
|
||||
vs_value::{Val, VsType},
|
||||
vs_value::{dynamic_make_mut, ToDynamicVal, ToVal, Val, VsType},
|
||||
LoadFunctionResult, ValTrait,
|
||||
};
|
||||
|
||||
use super::iteration_result::IterationResult;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ArrayIterator {
|
||||
pub array: Rc<VsArray>,
|
||||
pub index: usize,
|
||||
@@ -66,8 +70,12 @@ impl ValTrait for ArrayIterator {
|
||||
LoadFunctionResult::NotAFunction
|
||||
}
|
||||
|
||||
fn sub(&self, _key: Val) -> Result<Val, Val> {
|
||||
todo!()
|
||||
fn sub(&self, key: Val) -> Result<Val, Val> {
|
||||
if key.to_string() == "next" {
|
||||
return Ok(NEXT.to_val());
|
||||
}
|
||||
|
||||
Ok(Val::Undefined)
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> {
|
||||
@@ -92,3 +100,36 @@ impl fmt::Display for ArrayIterator {
|
||||
write!(f, "[object Array Iterator]")
|
||||
}
|
||||
}
|
||||
|
||||
static NEXT: NativeFunction = native_fn(|mut this, _| {
|
||||
let dynamic = match this.get_mut()? {
|
||||
Val::Dynamic(dynamic) => dynamic,
|
||||
_ => return Err("TODO: indirection".to_error()),
|
||||
};
|
||||
|
||||
let iter = dynamic_make_mut(dynamic)
|
||||
.as_any_mut()
|
||||
.downcast_mut::<ArrayIterator>()
|
||||
.ok_or_else(|| "ArrayIterator.next called on different object".to_type_error())?;
|
||||
|
||||
match iter.array.elements.get(iter.index) {
|
||||
Some(item) => {
|
||||
iter.index += 1;
|
||||
|
||||
Ok(
|
||||
IterationResult {
|
||||
value: item.clone(),
|
||||
done: false,
|
||||
}
|
||||
.to_dynamic_val(),
|
||||
)
|
||||
}
|
||||
None => Ok(
|
||||
IterationResult {
|
||||
value: Val::Undefined,
|
||||
done: true,
|
||||
}
|
||||
.to_dynamic_val(),
|
||||
),
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,7 +10,8 @@ use crate::{
|
||||
LoadFunctionResult, ValTrait,
|
||||
};
|
||||
|
||||
struct IterationResult {
|
||||
#[derive(Clone)]
|
||||
pub struct IterationResult {
|
||||
pub value: Val,
|
||||
pub done: bool,
|
||||
}
|
||||
@@ -74,8 +75,8 @@ impl ValTrait for IterationResult {
|
||||
|
||||
fn pretty_fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.done {
|
||||
false => write!(f, "\x1b[36mIteration({})\x1b[39m", self.value.pretty()),
|
||||
true => write!(f, "\x1b[36mIterationDone({})\x1b[39m", self.value.pretty()),
|
||||
false => write!(f, "Iteration({})", self.value.pretty()),
|
||||
true => write!(f, "IterationDone({})", self.value.pretty()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use core::fmt;
|
||||
use std::any::Any;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -30,7 +31,7 @@ pub enum Val {
|
||||
Function(Rc<VsFunction>),
|
||||
Class(Rc<VsClass>),
|
||||
Static(&'static dyn ValTrait),
|
||||
Dynamic(Rc<dyn ValTrait>),
|
||||
Dynamic(Rc<dyn DynValTrait>),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
@@ -77,6 +78,37 @@ pub trait ValTrait: fmt::Display {
|
||||
fn codify(&self) -> String;
|
||||
}
|
||||
|
||||
pub trait DynValTrait: ValTrait {
|
||||
fn clone_interior(&self) -> Rc<dyn DynValTrait>;
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
}
|
||||
|
||||
impl<T> DynValTrait for T
|
||||
where
|
||||
T: 'static + ValTrait + Clone,
|
||||
{
|
||||
fn clone_interior(&self) -> Rc<dyn DynValTrait> {
|
||||
Rc::new(self.clone())
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dynamic_make_mut(rc: &mut Rc<dyn DynValTrait>) -> &mut dyn DynValTrait {
|
||||
if Rc::get_mut(rc).is_none() {
|
||||
*rc = rc.clone_interior();
|
||||
}
|
||||
|
||||
Rc::get_mut(rc).unwrap()
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn ValTrait {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "(dyn ValTrait)(")?;
|
||||
@@ -85,6 +117,14 @@ impl fmt::Debug for dyn ValTrait {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn DynValTrait {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "(dyn DynValTrait)(")?;
|
||||
self.pretty_fmt(f)?;
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
|
||||
impl Val {
|
||||
pub fn to_primitive(&self) -> Val {
|
||||
if self.is_primitive() {
|
||||
@@ -510,7 +550,7 @@ pub trait ToDynamicVal {
|
||||
|
||||
impl<T> ToDynamicVal for T
|
||||
where
|
||||
T: ValTrait + 'static,
|
||||
T: DynValTrait + 'static,
|
||||
{
|
||||
fn to_dynamic_val(self) -> Val {
|
||||
Val::Dynamic(Rc::new(self))
|
||||
|
||||
Reference in New Issue
Block a user