diff --git a/vstc/src/db_command.rs b/vstc/src/db_command.rs index d88908f..bb7e321 100644 --- a/vstc/src/db_command.rs +++ b/vstc/src/db_command.rs @@ -1,13 +1,16 @@ use std::{process::exit, rc::Rc}; use storage::{storage_head_ptr, SledBackend, Storage, StorageReader}; -use valuescript_compiler::asm; +use valuescript_compiler::{asm, assemble, compile_str}; use valuescript_vm::{ vs_value::{ToVal, Val}, - DecoderMaker, VirtualMachine, + Bytecode, DecoderMaker, VirtualMachine, }; -use crate::to_bytecode::{format_from_path, to_bytecode}; +use crate::{ + handle_diagnostics_cli::handle_diagnostics_cli, + to_bytecode::{format_from_path, to_bytecode}, +}; pub fn db_command(args: &[String]) { let mut help_case = false; @@ -40,11 +43,10 @@ pub fn db_command(args: &[String]) { Some("new") => db_new(&path, args.get(4..).unwrap_or_default()), Some("call") => db_call(&path, args.get(4..).unwrap_or_default()), Some("-i") => println!("TODO: use database {} interactively", path), - arg => { + arg => 'b: { if let Some(arg) = arg { if arg.starts_with("this.") { - println!("TODO: on database {}, run {}", path, arg); - return; + break 'b db_run_inline(&path, arg); } } @@ -171,3 +173,46 @@ fn db_call(path: &str, args: &[String]) { .set_head(storage_head_ptr(b"state"), &instance) .unwrap(); } + +fn db_run_inline(path: &str, source: &str) { + let mut storage = Storage::new(SledBackend::open(path).unwrap()); + + let mut vm = VirtualMachine::default(); + + let mut instance = storage + .get_head::(storage_head_ptr(b"state")) + .unwrap() + .unwrap(); + + let compile_result = compile_str(&format!( + "export default function() {{ return (\n {}\n); }}", + source + )); + + for (path, diagnostics) in compile_result.diagnostics.iter() { + // TODO: Fix exit call + handle_diagnostics_cli(&path.path, diagnostics); + } + + let bytecode = Rc::new(Bytecode::new(assemble( + &compile_result + .module + .expect("Should have exited if module is None"), + ))); + + let fn_ = bytecode.decoder(0).decode_val(&mut vec![]); + + match vm.run(None, &mut instance, fn_, vec![]) { + Ok(res) => { + println!("{}", res.pretty()); + } + Err(err) => { + println!("Uncaught exception: {}", err.pretty()); + exit(1); + } + } + + storage + .set_head(storage_head_ptr(b"state"), &instance) + .unwrap(); +} diff --git a/vstc/src/handle_diagnostics_cli.rs b/vstc/src/handle_diagnostics_cli.rs index 5bdee16..0cab3d2 100644 --- a/vstc/src/handle_diagnostics_cli.rs +++ b/vstc/src/handle_diagnostics_cli.rs @@ -6,25 +6,45 @@ use url::Url; use valuescript_compiler::{Diagnostic, DiagnosticLevel}; pub fn handle_diagnostics_cli(file_path: &String, diagnostics: &Vec) { - let current_dir = std::env::current_dir().expect("Failed to get current directory"); - let abs_path = PathBuf::from(file_path); - let path = abs_path.strip_prefix(¤t_dir).unwrap_or(&abs_path); + let path = 'b: { + if file_path == "(str)" { + // TODO: Fix this hack + break 'b None; + } + + let current_dir = std::env::current_dir().expect("Failed to get current directory"); + let abs_path = PathBuf::from(file_path); + + Some(match abs_path.strip_prefix(¤t_dir) { + Ok(p) => p.into(), + Err(_) => abs_path, + }) + }; + + let path_str = match path { + Some(path) => path.to_string_lossy().to_string(), + None => file_path.clone(), + }; let mut level_counts = HashMap::::new(); - let text = std::fs::read_to_string(file_path).unwrap(); + let text = if file_path == "(str)" { + None + } else { + Some(std::fs::read_to_string(file_path).unwrap()) + }; + let mut lines = Vec::::new(); for diagnostic in diagnostics { - let (line, col) = pos_to_line_col(&text, diagnostic.span.lo.0); + let (line, col) = match &text { + Some(text) => pos_to_line_col(text, diagnostic.span.lo.0), + None => (0, 0), + }; let line = format!( "{}:{}:{}: {}: {}", - path.display(), - line, - col, - diagnostic.level, - diagnostic.message + path_str, line, col, diagnostic.level, diagnostic.message ); println!("{}", line);