Refactor full_*_raw functions, deduplicate things

This commit is contained in:
Andrew Morris
2023-02-26 21:20:05 +11:00
parent 6c56d13d84
commit fadd312686
3 changed files with 43 additions and 102 deletions

View File

@@ -10,10 +10,12 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
pub fn compile(source: &str) -> String {
return vstc::compile::full_compile_raw(source);
let output = vstc::compile::compile(source);
return serde_json::to_string(&output).expect("Failed json serialization");
}
#[wasm_bindgen]
pub fn run(source: &str) -> String {
return vstc::run::full_run_raw(source);
let run_result = vstc::run::run(source);
return serde_json::to_string(&run_result).expect("Failed json serialization");
}

View File

@@ -1,7 +1,6 @@
use std::cell::RefCell;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::process::exit;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
@@ -25,8 +24,17 @@ pub fn command(args: &Vec<String>) {
exit(1);
}
let program = parse(&args[2]);
let compiler_output = compile(&program);
let source = std::fs::read_to_string(&args[2]).expect("Failed to read file");
let (program_optional, parse_diagnostics) = parse(&source);
handle_diagnostics_cli(&args[2], &parse_diagnostics);
let program = match program_optional {
Some(program) => program,
None => exit(1),
};
let compiler_output = compile_program(&program);
handle_diagnostics_cli(&args[2], &compiler_output.diagnostics);
@@ -62,24 +70,22 @@ impl Emitter for DiagnosticCollector {
}
}
pub fn parse(file_path: &String) -> swc_ecma_ast::Program {
pub fn parse(source: &str) -> (Option<swc_ecma_ast::Program>, Vec<Diagnostic>) {
let source_map = Arc::<SourceMap>::default();
let diagnostics = Arc::new(Mutex::new(Vec::<Diagnostic>::new()));
let diagnostics_arc = Arc::new(Mutex::new(Vec::<Diagnostic>::new()));
let handler = Handler::with_emitter(
true,
false,
Box::new(DiagnosticCollector {
diagnostics: diagnostics.clone(),
diagnostics: diagnostics_arc.clone(),
}),
);
let swc_compiler = swc::Compiler::new(source_map.clone());
let file = source_map
.load_file(Path::new(&file_path))
.expect("failed to load file");
let file = source_map.new_source_file(FileName::Anon, source.into());
let result = swc_compiler.parse_js(
file,
@@ -90,18 +96,19 @@ pub fn parse(file_path: &String) -> swc_ecma_ast::Program {
None,
);
handle_diagnostics_cli(file_path, &*diagnostics.lock().unwrap());
let mut diagnostics = Vec::<Diagnostic>::new();
std::mem::swap(&mut diagnostics, &mut *diagnostics_arc.lock().unwrap());
return result.expect("Parse failed");
return (result.ok(), diagnostics);
}
#[derive(serde::Serialize)]
#[derive(Default, serde::Serialize)]
pub struct CompilerOutput {
pub diagnostics: Vec<Diagnostic>,
pub assembly: Vec<String>,
}
pub fn compile(program: &swc_ecma_ast::Program) -> CompilerOutput {
pub fn compile_program(program: &swc_ecma_ast::Program) -> CompilerOutput {
let mut compiler = Compiler::default();
compiler.compile_program(&program);
@@ -126,47 +133,18 @@ pub fn compile(program: &swc_ecma_ast::Program) -> CompilerOutput {
};
}
pub fn full_compile_raw(source: &str) -> String {
let source_map = Arc::<SourceMap>::default();
pub fn compile(source: &str) -> CompilerOutput {
let (program_optional, mut diagnostics) = parse(source);
let diagnostics = Arc::new(Mutex::new(Vec::<Diagnostic>::new()));
let handler = Handler::with_emitter(
true,
false,
Box::new(DiagnosticCollector {
diagnostics: diagnostics.clone(),
}),
);
let swc_compiler = swc::Compiler::new(source_map.clone());
let file = source_map.new_source_file(FileName::Anon, source.into());
let result = swc_compiler.parse_js(
file,
&handler,
EsVersion::Es2022,
Syntax::Typescript(TsConfig::default()),
swc::config::IsModule::Bool(true),
None,
);
let compiler_output = match result {
Ok(program) => compile(&program),
Err(_) => {
let mut res = CompilerOutput {
diagnostics: vec![],
assembly: Vec::<String>::new(),
};
std::mem::swap(&mut res.diagnostics, &mut *diagnostics.lock().unwrap());
res
}
let mut compiler_output = match program_optional {
Some(program) => compile_program(&program),
None => CompilerOutput::default(),
};
return serde_json::to_string(&compiler_output).expect("Failed json serialization");
diagnostics.append(&mut compiler_output.diagnostics);
compiler_output.diagnostics = diagnostics;
return compiler_output;
}
#[derive(Default)]

View File

@@ -15,7 +15,7 @@ use swc_ecma_parser::TsConfig;
use super::assemble::assemble;
use super::compile::compile;
use super::compile::parse;
use super::compile::compile_program;
use super::diagnostic::handle_diagnostics_cli;
use super::diagnostic::Diagnostic;
use super::diagnostic::DiagnosticLevel;
@@ -62,38 +62,8 @@ pub struct RunResult {
pub output: Result<String, String>,
}
pub fn full_run_raw(source: &str) -> String {
let source_map = Arc::<SourceMap>::default();
let handler = Handler::with_emitter(true, false, Box::new(VsEmitter {}));
let swc_compiler = swc::Compiler::new(source_map.clone());
let file = source_map.new_source_file(FileName::Anon, source.into());
let result = swc_compiler.parse_js(
file,
&handler,
EsVersion::Es2022,
Syntax::Typescript(TsConfig::default()),
swc::config::IsModule::Bool(true),
None,
);
let compiler_output = match result {
Ok(program) => compile(&program),
Err(err) => {
return serde_json::to_string(&RunResult {
diagnostics: vec![Diagnostic {
level: DiagnosticLevel::Error,
message: err.to_string(),
span: swc_common::DUMMY_SP,
}],
output: Err("Parse failed".into()),
})
.expect("Failed to serialize RunResult");
}
};
pub fn run(source: &str) -> RunResult {
let compiler_output = compile(source);
let mut have_compiler_errors = false;
@@ -106,11 +76,10 @@ pub fn full_run_raw(source: &str) -> String {
}
if have_compiler_errors {
return serde_json::to_string(&RunResult {
return RunResult {
diagnostics: compiler_output.diagnostics,
output: Err("Compile failed".into()),
})
.expect("Failed to serialize RunResult");
};
}
let bytecode = assemble(compiler_output.assembly.join("\n").as_str());
@@ -118,11 +87,10 @@ pub fn full_run_raw(source: &str) -> String {
let mut vm = VirtualMachine::new();
let result = vm.run(&bytecode, &[]);
return serde_json::to_string(&RunResult {
return RunResult {
diagnostics: compiler_output.diagnostics,
output: Ok(result.codify()),
})
.expect("Failed to serialize RunResult");
};
}
enum RunFormat {
@@ -160,18 +128,11 @@ fn format_from_path(file_path: &String) -> RunFormat {
fn to_bytecode(format: RunFormat, file_path: &String) -> Rc<Vec<u8>> {
return match format {
RunFormat::TypeScript => {
let ast = parse(file_path);
let compiler_output = compile(&ast);
let source = std::fs::read_to_string(file_path).expect("Failed to read file");
let compiler_output = compile(&source);
handle_diagnostics_cli(file_path, &compiler_output.diagnostics);
let mut assembly = String::new();
for line in compiler_output.assembly {
assembly.push_str(&line);
assembly.push('\n');
}
return assemble(&assembly);
return assemble(&compiler_output.assembly.join("\n"));
}
RunFormat::Assembly => {