mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-01-08 21:18:04 -05:00
Simplify vm.run
This commit is contained in:
@@ -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![])
|
||||
}
|
||||
|
||||
@@ -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
|
||||
))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user