Add and use run_linked

This commit is contained in:
Andrew Morris
2023-03-28 16:25:30 +11:00
parent 683fd182fa
commit aaf89e2cab
10 changed files with 367 additions and 81 deletions

View File

@@ -1,6 +1,10 @@
use std::collections::HashMap;
use wasm_bindgen::prelude::*;
use valuescript_compiler::{CompilerOutput, Diagnostic, DiagnosticLevel};
use valuescript_compiler::{
assemble, compile as compile_internal, CompilerOutput, Diagnostic, DiagnosticLevel, ResolvedPath,
};
use valuescript_vm::ValTrait;
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
@@ -9,9 +13,15 @@ use valuescript_vm::ValTrait;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
extern "C" {
fn js_get_error_message(e: &JsValue) -> String;
fn js_console_log(s: &str);
}
#[derive(serde::Serialize)]
struct RunResult {
diagnostics: Vec<valuescript_compiler::Diagnostic>,
diagnostics: HashMap<String, Vec<Diagnostic>>,
output: Result<String, String>,
}
@@ -30,7 +40,9 @@ fn run_to_result(source: &str) -> RunResult {
if have_compiler_errors {
return RunResult {
diagnostics: compiler_output.diagnostics,
diagnostics: vec![("(unknown)".into(), compiler_output.diagnostics)]
.into_iter()
.collect(),
output: Err("Compile failed".into()),
};
}
@@ -41,7 +53,9 @@ fn run_to_result(source: &str) -> RunResult {
let result = vm.run(&bytecode, &[]);
RunResult {
diagnostics: compiler_output.diagnostics,
diagnostics: vec![("(unknown)".into(), compiler_output.diagnostics)]
.into_iter()
.collect(),
output: match result {
Ok(result) => Ok(result.codify()),
Err(err) => Err(err.codify()),
@@ -51,14 +65,16 @@ fn run_to_result(source: &str) -> RunResult {
#[derive(serde::Serialize)]
struct CompilerOutputWasm {
diagnostics: Vec<Diagnostic>,
diagnostics: HashMap<String, Vec<Diagnostic>>,
assembly: Vec<String>,
}
impl CompilerOutputWasm {
fn from_compiler_output(output: CompilerOutput) -> CompilerOutputWasm {
CompilerOutputWasm {
diagnostics: output.diagnostics,
diagnostics: vec![("(unknown)".into(), output.diagnostics)]
.into_iter()
.collect(),
assembly: output.module.as_lines(),
}
}
@@ -77,3 +93,61 @@ pub fn run(source: &str) -> String {
let result = run_to_result(source);
serde_json::to_string(&result).expect("Failed json serialization")
}
fn run_linked_to_result(entry_point: &str, read_file: &js_sys::Function) -> RunResult {
let compile_result = compile_internal(ResolvedPath::from(entry_point.to_string()), |path| {
let call_result = read_file.call1(&JsValue::UNDEFINED, &JsValue::from_str(path));
match call_result {
Ok(result) => result
.as_string()
.ok_or_else(|| "read_file from JS produced non-string".into()),
Err(err) => Err(js_get_error_message(&err)),
}
});
let diagnostic_len = compile_result
.diagnostics
.iter()
.map(|(_, v)| v.len())
.sum::<usize>();
if diagnostic_len > 0 {
return RunResult {
diagnostics: compile_result
.diagnostics // TODO: Avoid conversion
.into_iter()
.map(|(path, diagnostics)| (path.to_string(), diagnostics))
.collect(),
output: Err("Compile failed".into()),
};
}
let module = match compile_result.module {
Some(module) => module,
None => {
return RunResult {
diagnostics: HashMap::default(),
output: Err("Compilation did not emit module".into()),
}
}
};
let mut vm = valuescript_vm::VirtualMachine::new();
let vm_result = vm.run(&assemble(&module), &[]);
RunResult {
diagnostics: HashMap::default(),
output: match vm_result {
Ok(result) => Ok(result.codify()),
Err(err) => Err(err.codify()),
},
}
}
#[wasm_bindgen]
pub fn run_linked(entry_point: &str, read_file: &js_sys::Function) -> String {
let result = run_linked_to_result(entry_point, read_file);
serde_json::to_string(&result).expect("Failed json serialization")
}