Add native_function

This commit is contained in:
Andrew Morris
2022-05-20 11:28:38 +10:00
parent ca5ef43ee2
commit 0a0c3e98d3
6 changed files with 92 additions and 46 deletions

View File

@@ -7,5 +7,6 @@ mod virtual_machine;
mod instruction;
mod vs_object;
mod vs_array;
mod native_function;
pub use virtual_machine::VirtualMachine;

View File

@@ -0,0 +1,44 @@
use std::rc::Rc;
use super::vs_value::{
Val,
VsType,
ValTrait,
LoadFunctionResult,
};
use super::vs_object::VsObject;
use super::vs_array::VsArray;
pub struct NativeFunction {
fn_: fn(this: &mut Val, params: Vec<Val>) -> Val,
}
impl ValTrait for NativeFunction {
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 load_function(&self) -> LoadFunctionResult {
LoadFunctionResult::NativeFunction(self.fn_)
}
fn sub(&self, _key: Val) -> Val {
std::panic!("Not implemented");
}
fn submov(&mut self, _key: Val, _value: Val) {
std::panic!("Not implemented: exceptions");
}
}

View File

@@ -279,7 +279,7 @@ pub fn op_sub(left: Val, right: Val) -> Val {
},
Val::Function(_) => Val::Undefined,
Val::Static(s) => s.sub(right),
Val::Custom(custom_data) => op_sub(custom_data.resolve(), right),
Val::Custom(custom_data) => custom_data.sub(right),
}
}
@@ -318,10 +318,6 @@ pub fn op_submov(target: &mut Val, subscript: Val, value: Val) {
},
Val::Function(_) => std::panic!("Not implemented: function subscript assignment"),
Val::Static(_) => std::panic!("Not implemented: exceptions"),
Val::Custom(custom_data) => {
let mut resolved_target = custom_data.resolve();
op_submov(&mut resolved_target, subscript, value);
*target = resolved_target;
},
Val::Custom(_) => std::panic!("Not implemented"),
}
}

View File

@@ -4,8 +4,6 @@ use super::vs_value::{
Val,
VsType,
ValTrait,
StaticValExtraTrait,
StaticValTrait,
LoadFunctionResult,
};
use super::vs_object::VsObject;
@@ -42,8 +40,6 @@ impl ValTrait for ArrayPrototype {
fn is_truthy(&self) -> bool { true }
fn is_nullish(&self) -> bool { false }
fn resolve(&self) -> Val { Val::Static(&ARRAY_PROTOTYPE) }
fn bind(&self, _params: Vec<Val>) -> Option<Val> { None }
fn as_array_data(&self) -> Option<Rc<VsArray>> { None }
@@ -52,14 +48,14 @@ impl ValTrait for ArrayPrototype {
fn load_function(&self) -> LoadFunctionResult {
LoadFunctionResult::NotAFunction
}
}
impl StaticValExtraTrait for ArrayPrototype {
fn sub(&self, key: Val) -> Val {
match key.val_to_string().as_str() {
_ => Val::Undefined,
}
}
}
impl StaticValTrait for ArrayPrototype {}
fn submov(&mut self, key: Val, value: Val) {
std::panic!("Not implemented: exceptions");
}
}

View File

@@ -20,6 +20,27 @@ impl VsPointer {
resolved: RefCell::new(None),
}));
}
fn resolve(&self) -> Val {
let mut resolved = self.resolved.borrow_mut();
if resolved.is_some() {
return resolved.clone().unwrap();
}
let mut bd = BytecodeDecoder {
data: self.bytecode.clone(),
pos: self.pos,
};
let val = bd.decode_val(&Vec::new());
// TODO: Check that this actually inserts into the cell and not just a copy
// somehow
*resolved = Some(val.clone());
return val;
}
}
impl ValTrait for VsPointer {
@@ -76,27 +97,6 @@ impl ValTrait for VsPointer {
return self.resolve().to_primitive();
}
fn resolve(&self) -> Val {
let mut resolved = self.resolved.borrow_mut();
if resolved.is_some() {
return resolved.clone().unwrap();
}
let mut bd = BytecodeDecoder {
data: self.bytecode.clone(),
pos: self.pos,
};
let val = bd.decode_val(&Vec::new());
// TODO: Check that this actually inserts into the cell and not just a copy
// somehow
*resolved = Some(val.clone());
return val;
}
fn bind(&self, params: Vec<Val>) -> Option<Val> {
return self.resolve().bind(params);
}
@@ -120,4 +120,12 @@ impl ValTrait for VsPointer {
fn load_function(&self) -> LoadFunctionResult {
return self.resolve().load_function();
}
fn sub(&self, subscript: Val) -> Val {
return self.resolve().sub(subscript);
}
fn submov(&mut self, subscript: Val, value: Val) {
std::panic!("Not implemented");
}
}

View File

@@ -5,6 +5,7 @@ use super::vs_function::VsFunction;
use super::virtual_machine::StackFrame;
use super::vs_object::VsObject;
use super::vs_array::VsArray;
use super::operations::{op_sub, op_submov};
#[derive(Clone)]
pub enum Val {
@@ -17,7 +18,7 @@ pub enum Val {
Array(Rc<VsArray>),
Object(Rc<VsObject>),
Function(Rc<VsFunction>),
Static(&'static dyn StaticValTrait),
Static(&'static dyn ValTrait),
Custom(Rc<dyn ValTrait>),
}
@@ -49,22 +50,17 @@ pub trait ValTrait {
fn is_truthy(&self) -> bool;
fn is_nullish(&self) -> bool;
fn resolve(&self) -> Val;
fn bind(&self, params: Vec<Val>) -> Option<Val>;
fn as_array_data(&self) -> Option<Rc<VsArray>>;
fn as_object_data(&self) -> Option<Rc<VsObject>>;
fn load_function(&self) -> LoadFunctionResult;
}
pub trait StaticValExtraTrait {
fn sub(&self, key: Val) -> Val;
fn submov(&mut self, key: Val, value: Val);
}
pub trait StaticValTrait: ValTrait + StaticValExtraTrait {}
impl ValTrait for Val {
fn typeof_(&self) -> VsType {
use Val::*;
@@ -223,10 +219,6 @@ impl ValTrait for Val {
};
}
fn resolve(&self) -> Val {
std::panic!("Unexpected resolve call on plain Val")
}
fn bind(&self, params: Vec<Val>) -> Option<Val> {
use Val::*;
@@ -270,6 +262,15 @@ impl ValTrait for Val {
_ => LoadFunctionResult::NotAFunction,
}
}
fn sub(&self, key: Val) -> Val {
// TODO: Avoid cloning?
return op_sub(self.clone(), key);
}
fn submov(&mut self, key: Val, value: Val) {
op_submov(self, key, value);
}
}
impl std::fmt::Display for Val {