Array.prototype.map

This commit is contained in:
Andrew Morris
2022-05-30 10:31:43 +10:00
parent c5e8317985
commit 928d9f7503
5 changed files with 135 additions and 11 deletions

View File

@@ -0,0 +1,80 @@
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 MAP: NativeFrameFunction = NativeFrameFunction {
make_frame: || Box::new(MapFrame {
this: None,
mapper: Val::Void,
param_i: 0,
map_results: Vec::new(),
}),
};
struct MapFrame {
this: Option<Rc<VsArray>>,
mapper: Val,
param_i: usize,
map_results: Vec<Val>,
}
impl StackFrameTrait for MapFrame {
fn write_this(&mut self, this: Val) {
self.this = this.as_array_data();
}
fn write_param(&mut self, param: Val) {
if self.param_i == 0 {
self.mapper = param;
}
self.param_i += 1;
}
fn step(&mut self) -> FrameStepResult {
let array_data = match &self.this {
None => std::panic!("Not implemented: exception: map called on non-array"),
Some(ad) => ad,
};
match array_data.elements.get(self.map_results.len()) {
Some(el) => match self.mapper.load_function() {
LoadFunctionResult::NotAFunction =>
std::panic!("Not implemented: exception: map fn is not a function")
,
LoadFunctionResult::NativeFunction(native_fn) => {
self.map_results.push(native_fn(
&mut Val::Undefined,
vec![el.clone()],
));
return FrameStepResult::Continue;
},
LoadFunctionResult::StackFrame(mut new_frame) => {
new_frame.write_param(el.clone());
return FrameStepResult::Push(new_frame);
},
},
None => {
let mut return_elements = Vec::new();
std::mem::swap(&mut return_elements, &mut self.map_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) {
self.map_results.push(call_result.return_);
}
fn get_call_result(&mut self) -> CallResult {
std::panic!("Not appropriate for MapFrame")
}
}

View File

@@ -0,0 +1 @@
pub mod array_map;

View File

@@ -14,5 +14,7 @@ mod vs_class;
mod bytecode_stack_frame;
mod stack_frame;
mod first_stack_frame;
mod array_higher_functions;
mod native_frame_function;
pub use virtual_machine::VirtualMachine;

View File

@@ -0,0 +1,51 @@
use std::rc::Rc;
use super::vs_value::{
Val,
VsType,
ValTrait,
LoadFunctionResult,
};
use super::vs_object::VsObject;
use super::vs_array::VsArray;
use super::vs_class::VsClass;
use super::stack_frame::StackFrame;
pub struct NativeFrameFunction {
pub make_frame: fn() -> StackFrame,
}
impl ValTrait for NativeFrameFunction {
fn typeof_(&self) -> VsType { VsType::Function }
fn val_to_string(&self) -> String { "function() { [native code] }".to_string() }
fn to_number(&self) -> f64 { f64::NAN }
fn to_index(&self) -> Option<usize> { None }
fn is_primitive(&self) -> bool { false }
fn to_primitive(&self) -> Val { Val::String(Rc::new(self.val_to_string())) }
fn is_truthy(&self) -> bool { true }
fn is_nullish(&self) -> bool { false }
fn bind(&self, _params: Vec<Val>) -> Option<Val> {
std::panic!("Not implemented");
}
fn as_array_data(&self) -> Option<Rc<VsArray>> { None }
fn as_object_data(&self) -> Option<Rc<VsObject>> { None }
fn as_class_data(&self) -> Option<Rc<VsClass>> { None }
fn load_function(&self) -> LoadFunctionResult {
LoadFunctionResult::StackFrame((self.make_frame)())
}
fn sub(&self, _key: Val) -> Val {
std::panic!("Not implemented");
}
fn submov(&mut self, _key: Val, _value: Val) {
std::panic!("Not implemented: exceptions");
}
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "\x1b[36m[Function]\x1b[39m")
}
}

View File

@@ -11,6 +11,7 @@ use super::vs_object::VsObject;
use super::vs_class::VsClass;
use super::native_function::NativeFunction;
use super::operations::op_triple_eq_impl;
use super::array_higher_functions::array_map::MAP;
#[derive(Clone)]
pub struct VsArray {
@@ -499,17 +500,6 @@ static LAST_INDEX_OF: NativeFunction = NativeFunction {
}
};
static MAP: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {
Val::Array(_array_data) => {
std::panic!("Not implemented: MAP");
},
_ => std::panic!("Not implemented: exceptions/array indirection"),
};
}
};
static POP: NativeFunction = NativeFunction {
fn_: |this: &mut Val, _params: Vec<Val>| -> Val {
match this {