Array.prototype.filter

This commit is contained in:
Andrew Morris
2022-05-30 12:05:06 +10:00
parent e2daaad3f9
commit bb38559cba
3 changed files with 114 additions and 11 deletions

View File

@@ -0,0 +1,112 @@
use std::rc::Rc;
use super::super::vs_value::{Val, ValTrait, LoadFunctionResult};
use super::super::vs_array::VsArray;
use super::super::native_frame_function::NativeFrameFunction;
use super::super::stack_frame::{StackFrameTrait, FrameStepResult, CallResult};
pub static FILTER: NativeFrameFunction = NativeFrameFunction {
make_frame: || Box::new(FilterFrame {
this: None,
this_arg: Val::Undefined,
condition_fn: Val::Void,
param_i: 0,
array_i: 0,
filter_results: Vec::new(),
}),
};
struct FilterFrame {
this: Option<Rc<VsArray>>,
this_arg: Val,
condition_fn: Val,
param_i: usize,
array_i: usize,
filter_results: Vec<Val>,
}
impl StackFrameTrait for FilterFrame {
fn write_this(&mut self, this: Val) {
self.this = this.as_array_data();
}
fn write_param(&mut self, param: Val) {
match self.param_i {
0 => { self.condition_fn = param; }
1 => { self.this_arg = param; }
_ => {},
};
self.param_i += 1;
}
fn step(&mut self) -> FrameStepResult {
let array_data = match &self.this {
None => std::panic!("Not implemented: exception: filter called on non-array"),
Some(ad) => ad,
};
let array_i = self.array_i;
self.array_i += 1;
match array_data.elements.get(array_i) {
Some(el) => match el {
Val::Void => {
return FrameStepResult::Continue;
},
_ => match self.condition_fn.load_function() {
LoadFunctionResult::NotAFunction =>
std::panic!("Not implemented: exception: filter fn is not a function")
,
LoadFunctionResult::NativeFunction(native_fn) => {
let cond_result = native_fn(
&mut self.this_arg.clone(),
vec![
el.clone(),
Val::Number(array_i as f64),
Val::Array(array_data.clone()),
],
);
if cond_result.is_truthy() {
self.filter_results.push(el.clone());
}
return FrameStepResult::Continue;
},
LoadFunctionResult::StackFrame(mut new_frame) => {
new_frame.write_this(self.this_arg.clone());
new_frame.write_param(el.clone());
new_frame.write_param(Val::Number(array_i as f64));
new_frame.write_param(Val::Array(array_data.clone()));
return FrameStepResult::Push(new_frame);
},
},
},
None => {
let mut return_elements = Vec::new();
std::mem::swap(&mut return_elements, &mut self.filter_results);
return FrameStepResult::Pop(CallResult {
return_: Val::Array(Rc::new(VsArray::from(return_elements))),
this: Val::Array(array_data.clone()),
});
},
};
}
fn apply_call_result(&mut self, call_result: CallResult) {
if call_result.return_.is_truthy() {
let array_data = match &self.this {
None => std::panic!("Not implemented: exception: filter called on non-array"),
Some(ad) => ad,
};
self.filter_results.push(array_data.elements[self.array_i - 1].clone());
}
}
fn get_call_result(&mut self) -> CallResult {
std::panic!("Not appropriate for FilterFrame")
}
}

View File

@@ -1,3 +1,4 @@
pub mod array_map;
pub mod array_every;
pub mod array_some;
pub mod array_filter;

View File

@@ -14,6 +14,7 @@ use super::operations::op_triple_eq_impl;
use super::array_higher_functions::array_map::MAP;
use super::array_higher_functions::array_every::EVERY;
use super::array_higher_functions::array_some::SOME;
use super::array_higher_functions::array_filter::FILTER;
#[derive(Clone)]
pub struct VsArray {
@@ -305,17 +306,6 @@ static FILL: NativeFunction = NativeFunction {
}
};
static FILTER: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
Val::Array(_array_data) => {
std::panic!("Not implemented: FILTER");
},
_ => std::panic!("Not implemented: exceptions/array indirection"),
};
}
};
static FIND: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {