From fadd31268656ac9342a8e6d02b100743255c7e20 Mon Sep 17 00:00:00 2001 From: Andrew Morris Date: Sun, 26 Feb 2023 21:20:05 +1100 Subject: [PATCH] Refactor full_*_raw functions, deduplicate things --- src/lib.rs | 6 ++-- src/vstc/compile.rs | 80 ++++++++++++++++----------------------------- src/vstc/run.rs | 59 ++++++--------------------------- 3 files changed, 43 insertions(+), 102 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1b9bf9a..f24c411 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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"); } diff --git a/src/vstc/compile.rs b/src/vstc/compile.rs index 9fee977..a6efcd4 100644 --- a/src/vstc/compile.rs +++ b/src/vstc/compile.rs @@ -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) { 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, Vec) { let source_map = Arc::::default(); - let diagnostics = Arc::new(Mutex::new(Vec::::new())); + let diagnostics_arc = Arc::new(Mutex::new(Vec::::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::::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, pub assembly: Vec, } -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::::default(); +pub fn compile(source: &str) -> CompilerOutput { + let (program_optional, mut diagnostics) = parse(source); - let diagnostics = Arc::new(Mutex::new(Vec::::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::::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)] diff --git a/src/vstc/run.rs b/src/vstc/run.rs index 674b416..b5452eb 100644 --- a/src/vstc/run.rs +++ b/src/vstc/run.rs @@ -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, } -pub fn full_run_raw(source: &str) -> String { - let source_map = Arc::::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> { 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 => {