Simplify vm.run

This commit is contained in:
Andrew Morris
2023-11-02 11:36:25 +11:00
parent a5e76355f7
commit 32358b2dd6
9 changed files with 132 additions and 68 deletions

View File

@@ -2,12 +2,15 @@ use std::{
collections::HashMap,
fmt::Write,
hash::{Hash as HashTrait, Hasher},
rc::Rc,
};
use num_bigint::BigInt;
use valuescript_vm::{vs_value::Val, Bytecode, DecoderMaker};
use crate::{
assembler::ValueType, expression_compiler::CompiledExpression, instruction::RegisterVisitMut,
assemble, assembler::ValueType, expression_compiler::CompiledExpression,
instruction::RegisterVisitMut, parse_module,
};
pub use crate::instruction::{Instruction, InstructionFieldMut};
@@ -329,6 +332,14 @@ pub struct Pointer {
pub name: String,
}
impl From<&str> for Pointer {
fn from(name: &str) -> Self {
Pointer {
name: name.to_string(),
}
}
}
impl StructuredFormattable for Pointer {
fn structured_fmt(&self, sf: &mut StructuredFormatter<'_, '_>) -> std::fmt::Result {
sf.write("@")?;
@@ -854,3 +865,9 @@ impl Object {
result
}
}
pub fn inline(source: &str) -> Val {
let bytecode = Rc::new(Bytecode::new(assemble(&parse_module(source))));
bytecode.decoder(0).decode_val(&mut vec![])
}

View File

@@ -27,3 +27,21 @@ where
result
}
pub fn compile_str(source: &str) -> CompileResult {
compile(
ResolvedPath {
path: "(str)".into(),
},
|path| {
if path == "(str)" {
Ok(source.into())
} else {
Err(format!(
"Unknown path {} (no filesystem access for compile_str)",
path
))
}
},
)
}

View File

@@ -24,8 +24,8 @@ mod visit_pointers;
pub use assembler::assemble;
pub use assembly_parser::parse_module;
pub use compile::compile;
pub use compile::CompileResult;
pub use compile::{compile, compile_str};
pub use diagnostic::Diagnostic;
pub use diagnostic::DiagnosticLevel;
pub use gather_modules::gather_modules;

View File

@@ -1,54 +1,57 @@
use std::{process::exit, rc::Rc};
use valuescript_vm::{Bytecode, VirtualMachine};
use valuescript_vm::{vs_value::Val, Bytecode, DecoderMaker, VirtualMachine};
pub fn main() {
let bytecode = Rc::new(Bytecode::new(vec![
//
// This is the compiled bytecode for inputs/passing/projEuler/p28.ts.
//
// Using `RUSTFLAGS="-C opt-level=s" cargo build --release` it currently compiles to 534KiB.
// A program with just println!("Test") is 315KiB, so we might be able to get down to around
// 219KiB by simplifying the way we print the result.
//
// Since we're still in early development, the bytecode is subject to change, which means this
// bytecode might break.
//
// If you need to fix it, or use a different program, use vstc:
// vstc compile program.ts
// vstc assemble out.vsm
// # Output is in out.vsb. Use the xxd program (or otherwise) to see the bytes.
//
// Another option is to checkout the commit from when this was originally written:
// git checkout 4e77747ae67e0ef27f9841111058599c8e916a2f
// cargo build
// ./target/debug/valuescript_program_embed
//
0x0d, 0x05, 0x00, 0x0a, 0x00, 0x0b, 0x08, 0x00, 0x21, 0x0d, 0x9c, 0x00, 0x09, 0x09, 0x06, 0x01,
0x06, 0x09, 0x06, 0x19, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x7f, 0x40, 0x00, 0x02,
0x05, 0x0e, 0x02, 0x06, 0x01, 0x03, 0x21, 0x0d, 0x9c, 0x00, 0x09, 0x09, 0x06, 0x01, 0x06, 0x03,
0x06, 0x0d, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x7f, 0x40, 0x00, 0x02, 0x05, 0x0e,
0x02, 0x06, 0x01, 0x04, 0x21, 0x0d, 0x9c, 0x00, 0x09, 0x09, 0x06, 0x01, 0x06, 0x05, 0x06, 0x11,
0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x7f, 0x40, 0x00, 0x02, 0x05, 0x0e, 0x02, 0x06,
0x01, 0x05, 0x21, 0x0d, 0x9c, 0x00, 0x09, 0x09, 0x06, 0x01, 0x06, 0x07, 0x06, 0x15, 0x00, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x7f, 0x40, 0x00, 0x02, 0x05, 0x0e, 0x02, 0x06, 0x01, 0x06,
0x26, 0x09, 0x06, 0x01, 0x0e, 0x03, 0x0e, 0x04, 0x0e, 0x05, 0x0e, 0x06, 0x00, 0x08, 0x06, 0x72,
0x65, 0x64, 0x75, 0x63, 0x65, 0x09, 0x0d, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x08, 0x02, 0x26,
0x0e, 0x02, 0x08, 0x06, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x09, 0x0d, 0x1e, 0x01, 0x00, 0x04,
0x01, 0x06, 0x03, 0x05, 0x11, 0x0e, 0x05, 0x0e, 0x03, 0x06, 0x10, 0x0e, 0x06, 0x06, 0x28, 0x0e,
0x06, 0xe1, 0x00, 0x21, 0x0d, 0xe6, 0x00, 0x09, 0x0e, 0x02, 0x00, 0x02, 0x24, 0x0e, 0x02, 0x06,
0x02, 0x06, 0x04, 0x0e, 0x04, 0x0e, 0x06, 0x04, 0x01, 0x0e, 0x05, 0x06, 0x02, 0x05, 0x27, 0xb4,
0x00, 0x01, 0x0e, 0x04, 0x00, 0x00, 0x0b, 0x09, 0x01, 0x24, 0x0e, 0x02, 0x06, 0x00, 0x03, 0x24,
0x0e, 0x02, 0x06, 0x01, 0x04, 0x24, 0x0e, 0x02, 0x06, 0x02, 0x05, 0x06, 0x06, 0x03, 0x0e, 0x05,
0x02, 0x06, 0x06, 0x03, 0x0e, 0x04, 0x06, 0x05, 0x0e, 0x02, 0x0e, 0x06, 0x07, 0x04, 0x0e, 0x07,
0x0e, 0x03, 0x06, 0x01, 0x09, 0x0e, 0x04, 0x0e, 0x05, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x0b, 0x05,
0x02, 0x04, 0x0e, 0x02, 0x0e, 0x03, 0x00, 0x00,
]));
let mut vm = VirtualMachine::default();
let result = vm.run(
Rc::new(Bytecode::new(vec![
//
// This is the compiled bytecode for inputs/passing/projEuler/p28.ts.
//
// Using `RUSTFLAGS="-C opt-level=s" cargo build --release` it currently compiles to 534KiB.
// A program with just println!("Test") is 315KiB, so we might be able to get down to around
// 219KiB by simplifying the way we print the result.
//
// Since we're still in early development, the bytecode is subject to change, which means this
// bytecode might break.
//
// If you need to fix it, or use a different program, use vstc:
// vstc compile program.ts
// vstc assemble out.vsm
// # Output is in out.vsb. Use the xxd program (or otherwise) to see the bytes.
//
// Another option is to checkout the commit from when this was originally written:
// git checkout 4e77747ae67e0ef27f9841111058599c8e916a2f
// cargo build
// ./target/debug/valuescript_program_embed
//
0x0d, 0x05, 0x00, 0x0a, 0x00, 0x0b, 0x08, 0x00, 0x21, 0x0d, 0x9c, 0x00, 0x09, 0x09, 0x06,
0x01, 0x06, 0x09, 0x06, 0x19, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x7f, 0x40,
0x00, 0x02, 0x05, 0x0e, 0x02, 0x06, 0x01, 0x03, 0x21, 0x0d, 0x9c, 0x00, 0x09, 0x09, 0x06,
0x01, 0x06, 0x03, 0x06, 0x0d, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x7f, 0x40,
0x00, 0x02, 0x05, 0x0e, 0x02, 0x06, 0x01, 0x04, 0x21, 0x0d, 0x9c, 0x00, 0x09, 0x09, 0x06,
0x01, 0x06, 0x05, 0x06, 0x11, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x7f, 0x40,
0x00, 0x02, 0x05, 0x0e, 0x02, 0x06, 0x01, 0x05, 0x21, 0x0d, 0x9c, 0x00, 0x09, 0x09, 0x06,
0x01, 0x06, 0x07, 0x06, 0x15, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x7f, 0x40,
0x00, 0x02, 0x05, 0x0e, 0x02, 0x06, 0x01, 0x06, 0x26, 0x09, 0x06, 0x01, 0x0e, 0x03, 0x0e,
0x04, 0x0e, 0x05, 0x0e, 0x06, 0x00, 0x08, 0x06, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x09,
0x0d, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x08, 0x02, 0x26, 0x0e, 0x02, 0x08, 0x06, 0x72,
0x65, 0x64, 0x75, 0x63, 0x65, 0x09, 0x0d, 0x1e, 0x01, 0x00, 0x04, 0x01, 0x06, 0x03, 0x05,
0x11, 0x0e, 0x05, 0x0e, 0x03, 0x06, 0x10, 0x0e, 0x06, 0x06, 0x28, 0x0e, 0x06, 0xe1, 0x00,
0x21, 0x0d, 0xe6, 0x00, 0x09, 0x0e, 0x02, 0x00, 0x02, 0x24, 0x0e, 0x02, 0x06, 0x02, 0x06,
0x04, 0x0e, 0x04, 0x0e, 0x06, 0x04, 0x01, 0x0e, 0x05, 0x06, 0x02, 0x05, 0x27, 0xb4, 0x00,
0x01, 0x0e, 0x04, 0x00, 0x00, 0x0b, 0x09, 0x01, 0x24, 0x0e, 0x02, 0x06, 0x00, 0x03, 0x24,
0x0e, 0x02, 0x06, 0x01, 0x04, 0x24, 0x0e, 0x02, 0x06, 0x02, 0x05, 0x06, 0x06, 0x03, 0x0e,
0x05, 0x02, 0x06, 0x06, 0x03, 0x0e, 0x04, 0x06, 0x05, 0x0e, 0x02, 0x0e, 0x06, 0x07, 0x04,
0x0e, 0x07, 0x0e, 0x03, 0x06, 0x01, 0x09, 0x0e, 0x04, 0x0e, 0x05, 0x0e, 0x06, 0x00, 0x00,
0x00, 0x0b, 0x05, 0x02, 0x04, 0x0e, 0x02, 0x0e, 0x03, 0x00, 0x00,
])),
None,
&[],
&mut Val::Undefined,
bytecode.decoder(0).decode_val(&mut vec![]),
vec![],
);
match result {

View File

@@ -29,7 +29,7 @@ mod vs_storage_ptr;
mod vs_symbol;
pub mod vs_value;
pub use bytecode::Bytecode;
pub use bytecode::{Bytecode, DecoderMaker};
pub use string_methods::unicode_at;
pub use virtual_machine::VirtualMachine;
pub use vs_symbol::VsSymbol;

View File

@@ -1,9 +1,11 @@
use std::mem::take;
use std::rc::Rc;
use crate::builtins::internal_error_builtin::ToInternalError;
use crate::bytecode::Bytecode;
use crate::bytecode::DecoderMaker;
use crate::first_stack_frame::FirstStackFrame;
use crate::stack_frame::CallResult;
use crate::stack_frame::FrameStepOk;
use crate::stack_frame::StackFrame;
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
@@ -25,27 +27,26 @@ impl Default for VirtualMachine {
impl VirtualMachine {
pub fn run(
&mut self,
bytecode: Rc<Bytecode>,
step_limit: Option<usize>,
params: &[Val],
this: &mut Val,
fn_: Val,
args: Vec<Val>,
) -> Result<Val, Val> {
let mut bd = bytecode.decoder(0);
let main_fn = bd.decode_val(&mut Vec::new());
let mut frame = match main_fn.load_function() {
let mut frame = match fn_.load_function() {
LoadFunctionResult::StackFrame(f) => f,
_ => return Err("bytecode does start with function".to_internal_error()),
};
for p in params {
frame.write_param(p.clone());
frame.write_param(take(this));
for a in args {
frame.write_param(a);
}
self.push(frame);
match step_limit {
Some(step_limit) => {
let res = match step_limit {
Some(step_limit) => 'b: {
let mut step_count = 0;
while step_count < step_limit {
@@ -53,20 +54,29 @@ impl VirtualMachine {
step_count += 1;
if self.stack.is_empty() {
return Ok(self.frame.get_call_result().return_);
break 'b self.frame.get_call_result();
}
}
Err("step limit reached".to_internal_error())
return Err("step limit reached".to_internal_error());
}
None => {
while !self.stack.is_empty() {
self.step()?;
}
Ok(self.frame.get_call_result().return_)
self.frame.get_call_result()
}
}
};
let CallResult {
return_,
this: updated_this,
} = res;
*this = updated_this;
Ok(return_)
}
pub fn step(&mut self) -> Result<(), Val> {

View File

@@ -8,7 +8,7 @@ use valuescript_compiler::{
};
use valuescript_vm::{
vs_value::{ToVal, Val},
Bytecode, LoadFunctionResult, ValTrait, VirtualMachine,
Bytecode, DecoderMaker, LoadFunctionResult, ValTrait, VirtualMachine,
};
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
@@ -130,7 +130,12 @@ fn run_to_result(entry_point: &str, read_file: &js_sys::Function, args: &str) ->
}
};
let vm_result = vm.run(bytecode, None, &val_args);
let vm_result = vm.run(
None,
&mut Val::Undefined,
bytecode.decoder(0).decode_val(&mut vec![]),
val_args,
);
RunResult {
diagnostics: HashMap::default(),

View File

@@ -1,8 +1,8 @@
use std::process::exit;
use std::rc::Rc;
use valuescript_vm::vs_value::Val;
use valuescript_vm::VirtualMachine;
use valuescript_vm::{vs_value::Val, DecoderMaker};
use crate::to_bytecode::{format_from_path, to_bytecode, RunFormat};
@@ -41,7 +41,12 @@ pub fn run_command(args: &Vec<String>) {
.map(|a| Val::String(Rc::from(a.clone())))
.collect();
match vm.run(bytecode, None, &val_args) {
match vm.run(
None,
&mut Val::Undefined,
bytecode.decoder(0).decode_val(&mut vec![]),
val_args,
) {
Ok(Val::Undefined) => {}
Ok(result) => {
println!("{}", result.pretty());

View File

@@ -9,8 +9,9 @@ mod tests {
use valuescript_compiler::asm::Structured;
use valuescript_compiler::compile;
use valuescript_compiler::{assemble, parse_module};
use valuescript_vm::VirtualMachine;
use valuescript_vm::vs_value::Val;
use valuescript_vm::{Bytecode, ValTrait};
use valuescript_vm::{DecoderMaker, VirtualMachine};
use crate::handle_diagnostics_cli::handle_diagnostics_cli;
use crate::resolve_entry_path::resolve_entry_path;
@@ -111,7 +112,12 @@ mod tests {
let mut vm = VirtualMachine::default();
let result = vm.run(bytecode, Some(2_000_000), &[]);
let result = vm.run(
Some(2_000_000),
&mut Val::Undefined,
bytecode.decoder(0).decode_val(&mut vec![]),
vec![],
);
let result_string = match result {
Ok(val) => val.codify(),