Add array.entries()

This commit is contained in:
Andrew Morris
2023-05-30 09:34:05 +10:00
parent 4570aac6e8
commit c79e40a1dd
5 changed files with 149 additions and 18 deletions

View File

@@ -0,0 +1,137 @@
use std::{fmt, rc::Rc};
use num_bigint::BigInt;
use crate::{
builtins::{error_builtin::ToError, type_error_builtin::ToTypeError},
native_function::{native_fn, NativeFunction},
vs_array::VsArray,
vs_class::VsClass,
vs_value::{dynamic_make_mut, ToDynamicVal, ToVal, Val, VsType},
LoadFunctionResult, ValTrait,
};
use super::iteration_result::IterationResult;
#[derive(Clone)]
pub struct ArrayEntriesIterator {
pub array: Rc<VsArray>,
pub index: usize,
}
impl ArrayEntriesIterator {
pub fn new(array: Rc<VsArray>) -> ArrayEntriesIterator {
ArrayEntriesIterator { array, index: 0 }
}
}
impl ValTrait for ArrayEntriesIterator {
fn typeof_(&self) -> VsType {
VsType::Object
}
fn to_number(&self) -> f64 {
core::f64::NAN
}
fn to_index(&self) -> Option<usize> {
None
}
fn is_primitive(&self) -> bool {
false
}
fn is_truthy(&self) -> bool {
true
}
fn is_nullish(&self) -> bool {
false
}
fn bind(&self, _params: Vec<Val>) -> Option<Val> {
None
}
fn as_bigint_data(&self) -> Option<BigInt> {
None
}
fn as_array_data(&self) -> Option<Rc<VsArray>> {
None
}
fn as_class_data(&self) -> Option<Rc<VsClass>> {
None
}
fn load_function(&self) -> LoadFunctionResult {
LoadFunctionResult::NotAFunction
}
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> {
Err("Cannot assign to subscript of array iterator".to_type_error())
}
fn pretty_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "\x1b[36m[ArrayEntriesIterator]\x1b[39m")
}
fn codify(&self) -> String {
format!(
"ArrayEntriesIterator({{ array: {}, index: {} }})",
Val::Array(self.array.clone()).codify(),
self.index
)
}
}
impl fmt::Display for ArrayEntriesIterator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
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::<ArrayEntriesIterator>()
.ok_or_else(|| "ArrayEntriesIterator.next called on different object".to_type_error())?;
match iter.array.elements.get(iter.index) {
Some(item) => {
let res = Ok(
IterationResult {
value: vec![(iter.index as f64).to_val(), item.clone()].to_val(),
done: false,
}
.to_dynamic_val(),
);
iter.index += 1;
res
}
None => Ok(
IterationResult {
value: Val::Undefined,
done: true,
}
.to_dynamic_val(),
),
}
});

View File

@@ -1,3 +1,4 @@
pub mod array_entries_iterator;
pub mod array_iterator;
pub mod iteration_result;
pub mod string_iterator;

View File

@@ -148,10 +148,8 @@ static NEXT: NativeFunction = native_fn(|mut this, _| {
.downcast_mut::<StringIterator>()
.ok_or_else(|| "StringIterator.next called on different object".to_type_error())?;
let char = iter.next();
Ok(
match char {
match iter.next() {
Some(c) => IterationResult {
value: c.to_val(),
done: false,

View File

@@ -661,11 +661,9 @@ static VALUE_OF: NativeFunction = native_fn(|this, _params| {
})
});
static VALUES: NativeFunction = native_fn(|this, _params| {
Ok(match this.get() {
Val::String(string_data) => StringIterator::new(string_data.clone()).to_dynamic_val(),
_ => return Err("string indirection".to_error()),
})
static VALUES: NativeFunction = native_fn(|this, _params| match this.get() {
Val::String(string_data) => Ok(StringIterator::new(string_data.clone()).to_dynamic_val()),
_ => Err("string indirection".to_error()),
});
/**

View File

@@ -12,6 +12,7 @@ use crate::array_higher_functions::{
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::iteration::array_entries_iterator::ArrayEntriesIterator;
use crate::iteration::array_iterator::ArrayIterator;
use crate::native_function::{native_fn, NativeFunction};
use crate::operations::op_triple_eq_impl;
@@ -272,11 +273,9 @@ static COPY_WITHIN: NativeFunction = native_fn(|mut this, params| {
})
});
static ENTRIES: NativeFunction = native_fn(|this, _params| {
match this.get() {
Val::Array(_array_data) => return Err("TODO: iterators".to_error()),
_ => return Err("array indirection".to_error()),
};
static ENTRIES: NativeFunction = native_fn(|this, _params| match this.get() {
Val::Array(array_data) => Ok(ArrayEntriesIterator::new(array_data.clone()).to_dynamic_val()),
_ => Err("array indirection".to_error()),
});
static FILL: NativeFunction = native_fn(|mut this, params| {
@@ -646,9 +645,7 @@ static UNSHIFT: NativeFunction = native_fn(|mut this, params| {
})
});
static VALUES: NativeFunction = native_fn(|this, _params| {
Ok(match this.get() {
Val::Array(array_data) => ArrayIterator::new(array_data.clone()).to_dynamic_val(),
_ => return Err("array indirection".to_error()),
})
static VALUES: NativeFunction = native_fn(|this, _params| match this.get() {
Val::Array(array_data) => Ok(ArrayIterator::new(array_data.clone()).to_dynamic_val()),
_ => Err("array indirection".to_error()),
});