mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-01-14 07:57:57 -05:00
Implement bind
This commit is contained in:
@@ -92,7 +92,17 @@ impl BytecodeDecoder {
|
||||
String => Val::String(Rc::new(
|
||||
self.decode_string()
|
||||
)),
|
||||
Array => std::panic!("Not implemented"),
|
||||
Array => {
|
||||
let mut vals: Vec<Val> = Vec::new();
|
||||
|
||||
while self.peek_type() != BytecodeType::End {
|
||||
vals.push(self.decode_val(registers));
|
||||
}
|
||||
|
||||
self.decode_byte(); // End (TODO: assert)
|
||||
|
||||
Val::Array(Rc::new(vals))
|
||||
},
|
||||
Object => std::panic!("Not implemented"),
|
||||
Function => self.decode_function_header(),
|
||||
Instance => std::panic!("Not implemented"),
|
||||
@@ -185,6 +195,7 @@ impl BytecodeDecoder {
|
||||
register_count: register_count,
|
||||
parameter_count: parameter_count,
|
||||
start: self.pos,
|
||||
binds: Vec::new(),
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ pub struct VirtualMachine {
|
||||
pub struct StackFrame {
|
||||
pub decoder: BytecodeDecoder,
|
||||
pub registers: Vec<Val>,
|
||||
pub param_start: usize,
|
||||
pub param_end: usize,
|
||||
pub this_target: Option<usize>,
|
||||
pub return_target: Option<usize>,
|
||||
}
|
||||
@@ -56,6 +58,8 @@ impl VirtualMachine {
|
||||
pos: 0,
|
||||
},
|
||||
registers: registers,
|
||||
param_start: 2,
|
||||
param_end: 2,
|
||||
return_target: Some(0),
|
||||
this_target: Some(1),
|
||||
};
|
||||
@@ -91,7 +95,12 @@ impl VirtualMachine {
|
||||
frame.registers[register_index] = val;
|
||||
},
|
||||
|
||||
OpDec => std::panic!("Instruction not implemented: OpDec"),
|
||||
OpDec => {
|
||||
let register_index = frame.decoder.decode_register_index().unwrap();
|
||||
let mut val = frame.registers[register_index].clone();
|
||||
val = operations::op_minus(&val, &Val::Number(1_f64));
|
||||
frame.registers[register_index] = val;
|
||||
},
|
||||
|
||||
OpPlus => {
|
||||
let left = frame.decoder.decode_val(&frame.registers);
|
||||
@@ -252,7 +261,31 @@ impl VirtualMachine {
|
||||
self.stack.push(new_frame);
|
||||
}
|
||||
|
||||
Bind => std::panic!("Instruction not implemented: Bind"),
|
||||
Bind => {
|
||||
let fn_val = frame.decoder.decode_val(&frame.registers);
|
||||
let params = frame.decoder.decode_val(&frame.registers);
|
||||
let register_index = frame.decoder.decode_register_index();
|
||||
|
||||
let params_array = params.as_array();
|
||||
|
||||
if params_array.is_none() {
|
||||
// Not sure this needs to be an exception in future since compiled
|
||||
// code should never violate this
|
||||
std::panic!("bind params should always be array")
|
||||
}
|
||||
|
||||
let bound_fn = fn_val.bind((*params_array.unwrap()).clone());
|
||||
|
||||
if bound_fn.is_none() {
|
||||
// Not sure this needs to be an exception in future since compiled
|
||||
// code should never violate this
|
||||
std::panic!("fn parameter of bind should always be bindable");
|
||||
}
|
||||
|
||||
if register_index.is_some() {
|
||||
frame.registers[register_index.unwrap()] = bound_fn.unwrap();
|
||||
}
|
||||
},
|
||||
|
||||
Sub => std::panic!("Instruction not implemented: Sub"),
|
||||
|
||||
@@ -300,17 +333,12 @@ fn load_parameters(
|
||||
std::panic!("Not implemented: call instruction not using inline array");
|
||||
}
|
||||
|
||||
// Params start at 2 since 0:return, 1:this
|
||||
let mut reg_i = 2;
|
||||
let mut reg_i = new_frame.param_start;
|
||||
|
||||
while frame.decoder.peek_type() != BytecodeType::End {
|
||||
let val = frame.decoder.decode_val(&frame.registers);
|
||||
|
||||
if reg_i < new_frame.registers.len() {
|
||||
// TODO: We should also stop writing into registers when hitting the
|
||||
// parameter count. This won't matter for correctly constructed
|
||||
// bytecode but hand-written assembly/bytecode may violate
|
||||
// optimization assumptions.
|
||||
if reg_i < new_frame.param_end {
|
||||
new_frame.registers[reg_i] = val;
|
||||
reg_i += 1;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::vs_value::VsType;
|
||||
use super::vs_value::Val;
|
||||
use super::vs_value::ValTrait;
|
||||
use super::virtual_machine::StackFrame;
|
||||
use super::bytecode_decoder::BytecodeDecoder;
|
||||
|
||||
@@ -11,33 +9,37 @@ pub struct VsFunction {
|
||||
pub register_count: usize,
|
||||
pub parameter_count: usize,
|
||||
pub start: usize,
|
||||
pub binds: Vec<Val>,
|
||||
}
|
||||
|
||||
impl ValTrait for VsFunction {
|
||||
fn typeof_(&self) -> VsType {
|
||||
return VsType::Function;
|
||||
impl VsFunction {
|
||||
pub fn bind(&self, params: Vec<Val>) -> VsFunction {
|
||||
let mut new_binds = self.binds.clone();
|
||||
|
||||
for p in params {
|
||||
new_binds.push(p);
|
||||
}
|
||||
|
||||
return VsFunction {
|
||||
bytecode: self.bytecode.clone(),
|
||||
register_count: self.register_count,
|
||||
parameter_count: self.parameter_count,
|
||||
start: self.start,
|
||||
binds: new_binds,
|
||||
};
|
||||
}
|
||||
|
||||
fn val_to_string(&self) -> String {
|
||||
return "[function]".to_string();
|
||||
}
|
||||
|
||||
fn to_number(&self) -> f64 {
|
||||
return f64::NAN;
|
||||
}
|
||||
|
||||
fn is_primitive(&self) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
fn to_primitive(&self) -> Val {
|
||||
return Val::String(Rc::new(self.val_to_string()));
|
||||
}
|
||||
|
||||
fn make_frame(&self) -> Option<StackFrame> {
|
||||
pub fn make_frame(&self) -> Option<StackFrame> {
|
||||
let mut registers: Vec<Val> = Vec::with_capacity(self.register_count - 1);
|
||||
|
||||
for _ in 0..(self.register_count - 1) {
|
||||
|
||||
registers.push(Val::Undefined);
|
||||
registers.push(Val::Undefined);
|
||||
|
||||
for bind_val in &self.binds {
|
||||
registers.push(bind_val.clone());
|
||||
}
|
||||
|
||||
while registers.len() < registers.capacity() {
|
||||
registers.push(Val::Undefined);
|
||||
}
|
||||
|
||||
@@ -47,12 +49,10 @@ impl ValTrait for VsFunction {
|
||||
pos: self.start,
|
||||
},
|
||||
registers: registers,
|
||||
param_start: self.binds.len() + 2,
|
||||
param_end: self.parameter_count + 2,
|
||||
this_target: None,
|
||||
return_target: None,
|
||||
});
|
||||
}
|
||||
|
||||
fn is_truthy(&self) -> bool {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,10 @@ impl ValTrait for VsPointer {
|
||||
return self.decode().to_number();
|
||||
}
|
||||
|
||||
fn as_array(&self) -> Option<Rc<Vec<Val>>> {
|
||||
return self.decode().as_array();
|
||||
}
|
||||
|
||||
fn is_primitive(&self) -> bool {
|
||||
return match self.typeof_() {
|
||||
Undefined => true,
|
||||
@@ -95,6 +99,10 @@ impl ValTrait for VsPointer {
|
||||
return self.decode().to_primitive();
|
||||
}
|
||||
|
||||
fn bind(&self, params: Vec<Val>) -> Option<Val> {
|
||||
return self.decode().bind(params);
|
||||
}
|
||||
|
||||
fn make_frame(&self) -> Option<StackFrame> {
|
||||
return self.decode().make_frame();
|
||||
}
|
||||
|
||||
@@ -35,9 +35,11 @@ pub trait ValTrait {
|
||||
fn typeof_(&self) -> VsType;
|
||||
fn val_to_string(&self) -> String;
|
||||
fn to_number(&self) -> f64;
|
||||
fn as_array(&self) -> Option<Rc<Vec<Val>>>;
|
||||
fn is_primitive(&self) -> bool;
|
||||
fn to_primitive(&self) -> Val;
|
||||
fn is_truthy(&self) -> bool;
|
||||
fn bind(&self, params: Vec<Val>) -> Option<Val>;
|
||||
|
||||
fn make_frame(&self) -> Option<StackFrame>;
|
||||
}
|
||||
@@ -114,6 +116,17 @@ impl ValTrait for Val {
|
||||
};
|
||||
}
|
||||
|
||||
fn as_array(&self) -> Option<Rc<Vec<Val>>> {
|
||||
use Val::*;
|
||||
|
||||
return match self {
|
||||
Array(a) => Some(a.clone()),
|
||||
Custom(val) => val.as_array(),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_primitive(&self) -> bool {
|
||||
use Val::*;
|
||||
|
||||
@@ -156,6 +169,17 @@ impl ValTrait for Val {
|
||||
}
|
||||
}
|
||||
|
||||
fn bind(&self, params: Vec<Val>) -> Option<Val> {
|
||||
use Val::*;
|
||||
|
||||
return match self {
|
||||
Function(f) => Some(Val::Function(Rc::new(f.bind(params)))),
|
||||
Custom(val) => val.bind(params),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn make_frame(&self) -> Option<StackFrame> {
|
||||
use Val::*;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user