From 44759d16a8fc63f7196cd0b9608328d022743888 Mon Sep 17 00:00:00 2001 From: Andrew Morris Date: Mon, 27 Feb 2023 12:35:37 +1100 Subject: [PATCH] Reorganize using workspaces --- Cargo.lock | 36 +++- Cargo.toml | 48 +---- src/lib.rs | 21 -- src/main.rs | 42 ---- src/vstc/mod.rs | 11 -- swc_demo/Cargo.toml | 12 ++ swc_demo/src/main.rs | 41 ++++ valuescript_compiler/Cargo.toml | 16 ++ .../src}/assemble.rs | 179 ++++++++---------- .../src}/capture_finder.rs | 0 .../src}/compile.rs | 45 +---- .../src}/diagnostic.rs | 47 ----- .../src}/expression_compiler.rs | 0 .../src}/function_compiler.rs | 0 valuescript_compiler/src/lib.rs | 14 ++ .../src}/name_allocator.rs | 0 .../src}/scope.rs | 0 .../src}/scope_analysis.rs | 5 + valuescript_vm/Cargo.toml | 8 + .../array_higher_functions/array_every.rs | 0 .../array_higher_functions/array_filter.rs | 0 .../src}/array_higher_functions/array_find.rs | 0 .../array_find_index.rs | 0 .../array_higher_functions/array_flat_map.rs | 0 .../src}/array_higher_functions/array_map.rs | 0 .../array_mapping_frame.rs | 0 .../array_higher_functions/array_reduce.rs | 0 .../array_reduce_right.rs | 0 .../src}/array_higher_functions/array_some.rs | 0 .../src}/array_higher_functions/array_sort.rs | 0 .../src}/array_higher_functions/mod.rs | 0 .../src}/builtins.rs | 0 .../src}/bytecode_decoder.rs | 0 .../src}/bytecode_stack_frame.rs | 0 .../src}/debug.rs | 0 .../src}/first_stack_frame.rs | 0 .../src}/instruction.rs | 0 .../mod.rs => valuescript_vm/src/lib.rs | 34 ++-- .../src}/math.rs | 0 .../src}/native_frame_function.rs | 0 .../src}/native_function.rs | 0 .../src}/operations.rs | 0 .../src}/stack_frame.rs | 0 .../src}/virtual_machine.rs | 10 +- .../src}/vs_array.rs | 0 .../src}/vs_class.rs | 0 .../src}/vs_function.rs | 0 .../src}/vs_object.rs | 0 .../src}/vs_pointer.rs | 0 .../src}/vs_value.rs | 42 ++-- valuescript_wasm/Cargo.toml | 33 ++++ valuescript_wasm/src/lib.rs | 59 ++++++ vstc/Cargo.toml | 10 + vstc/src/assemble_command.rs | 43 +++++ vstc/src/compile_command.rs | 37 ++++ vstc/src/handle_diagnostics_cli.rs | 48 +++++ {src/vstc => vstc/src}/main.rs | 25 ++- src/vstc/run.rs => vstc/src/run_command.rs | 54 +----- website/src/playground/vslib/index.ts | 7 + 59 files changed, 515 insertions(+), 412 deletions(-) delete mode 100644 src/lib.rs delete mode 100644 src/main.rs delete mode 100644 src/vstc/mod.rs create mode 100644 swc_demo/Cargo.toml create mode 100644 swc_demo/src/main.rs create mode 100644 valuescript_compiler/Cargo.toml rename {src/vstc => valuescript_compiler/src}/assemble.rs (88%) rename {src/vstc => valuescript_compiler/src}/capture_finder.rs (100%) rename {src/vstc => valuescript_compiler/src}/compile.rs (96%) rename {src/vstc => valuescript_compiler/src}/diagnostic.rs (59%) rename {src/vstc => valuescript_compiler/src}/expression_compiler.rs (100%) rename {src/vstc => valuescript_compiler/src}/function_compiler.rs (100%) create mode 100644 valuescript_compiler/src/lib.rs rename {src/vstc => valuescript_compiler/src}/name_allocator.rs (100%) rename {src/vstc => valuescript_compiler/src}/scope.rs (100%) rename {src/vstc => valuescript_compiler/src}/scope_analysis.rs (99%) create mode 100644 valuescript_vm/Cargo.toml rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/array_every.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/array_filter.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/array_find.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/array_find_index.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/array_flat_map.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/array_map.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/array_mapping_frame.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/array_reduce.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/array_reduce_right.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/array_some.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/array_sort.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/array_higher_functions/mod.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/builtins.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/bytecode_decoder.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/bytecode_stack_frame.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/debug.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/first_stack_frame.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/instruction.rs (100%) rename src/vstc/virtual_machine/mod.rs => valuescript_vm/src/lib.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/math.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/native_frame_function.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/native_function.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/operations.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/stack_frame.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/virtual_machine.rs (90%) rename {src/vstc/virtual_machine => valuescript_vm/src}/vs_array.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/vs_class.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/vs_function.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/vs_object.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/vs_pointer.rs (100%) rename {src/vstc/virtual_machine => valuescript_vm/src}/vs_value.rs (96%) create mode 100644 valuescript_wasm/Cargo.toml create mode 100644 valuescript_wasm/src/lib.rs create mode 100644 vstc/Cargo.toml create mode 100644 vstc/src/assemble_command.rs create mode 100644 vstc/src/compile_command.rs create mode 100644 vstc/src/handle_diagnostics_cli.rs rename {src/vstc => vstc/src}/main.rs (84%) rename src/vstc/run.rs => vstc/src/run_command.rs (69%) diff --git a/Cargo.lock b/Cargo.lock index a15c91d..0c28ce0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1446,6 +1446,16 @@ dependencies = [ "url", ] +[[package]] +name = "swc_demo" +version = "0.1.0" +dependencies = [ + "swc", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", +] + [[package]] name = "swc_ecma_ast" version = "0.76.0" @@ -2147,10 +2157,9 @@ dependencies = [ ] [[package]] -name = "value_script" +name = "valuescript_compiler" version = "0.1.0" dependencies = [ - "console_error_panic_hook", "queues", "serde", "serde_json", @@ -2159,6 +2168,21 @@ dependencies = [ "swc_common", "swc_ecma_ast", "swc_ecma_parser", +] + +[[package]] +name = "valuescript_vm" +version = "0.1.0" + +[[package]] +name = "valuescript_wasm" +version = "0.1.0" +dependencies = [ + "console_error_panic_hook", + "serde", + "serde_json", + "valuescript_compiler", + "valuescript_vm", "wasm-bindgen", "wasm-bindgen-test", "wee_alloc", @@ -2176,6 +2200,14 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "vstc" +version = "0.1.0" +dependencies = [ + "valuescript_compiler", + "valuescript_vm", +] + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index ceef00c..5d92532 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,41 +1,9 @@ -[package] -name = "value_script" -version = "0.1.0" -edition = "2021" +[workspace] -[[bin]] -name = "vstc" -path = "src/vstc/main.rs" -test = false -bench = false - -[lib] -crate-type = ["cdylib", "rlib"] - -[dependencies] -queues = "1.0.2" -serde = "1.0" -serde_json = "1.0" -swc_common = { version = "0.17.22", features=["tty-emitter"] } -swc_ecma_parser = "0.102.2" -swc = "0.168.3" -swc_ecma_ast = "0.76.0" -swc_atoms = "0.2" - -# wasm-related - -wasm-bindgen = "0.2.63" - -# The `console_error_panic_hook` crate provides better debugging of panics by -# logging them with `console.error`. This is great for development, but requires -# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for -# code size when deploying. -console_error_panic_hook = { version = "0.1.6", optional = true } - -# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size -# compared to the default allocator's ~10K. It is slower than the default -# allocator, however. -wee_alloc = { version = "0.4.5", optional = true } - -[dev-dependencies] -wasm-bindgen-test = "0.3.13" +members = [ + "valuescript_vm", + "valuescript_compiler", + "valuescript_wasm", + "vstc", + "swc_demo", +] diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index f24c411..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -mod vstc; - -use wasm_bindgen::prelude::*; - -// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global -// allocator. -#[cfg(feature = "wee_alloc")] -#[global_allocator] -static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; - -#[wasm_bindgen] -pub fn compile(source: &str) -> String { - let output = vstc::compile::compile(source); - return serde_json::to_string(&output).expect("Failed json serialization"); -} - -#[wasm_bindgen] -pub fn run(source: &str) -> String { - let run_result = vstc::run::run(source); - return serde_json::to_string(&run_result).expect("Failed json serialization"); -} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e76f931..0000000 --- a/src/main.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::{path::Path, sync::Arc}; -use swc_ecma_ast::{EsVersion}; -use swc_common::{ - errors::{ColorConfig, Handler}, - SourceMap, FileName, -}; -use swc_ecma_parser::{TsConfig, Syntax}; - -fn main() { - let cm = Arc::::default(); - let handler = Handler::with_tty_emitter( - ColorConfig::Auto, - true, - false, - Some(cm.clone()), - ); - let c = swc::Compiler::new(cm.clone()); - // let fm = cm - // .load_file(Path::new("foo.js")) - // .expect("failed to load file"); - let fm = cm.new_source_file( - FileName::Custom("test.js".into()), - " - function foo(x: number) { - if (x < 3) { - return 'lt3'; - } - - return 'nlt3'; - } - ".into(), - ); - let result = c.parse_js( - fm, - &handler, - EsVersion::Es2020, - Syntax::Typescript(TsConfig::default()), - swc::config::IsModule::Bool(true), - None, - ); - dbg!(result); -} diff --git a/src/vstc/mod.rs b/src/vstc/mod.rs deleted file mode 100644 index e19f7a2..0000000 --- a/src/vstc/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -mod assemble; -mod capture_finder; -pub mod compile; -pub mod diagnostic; -mod expression_compiler; -mod function_compiler; -mod name_allocator; -pub mod run; -mod scope; -pub mod scope_analysis; -pub mod virtual_machine; diff --git a/swc_demo/Cargo.toml b/swc_demo/Cargo.toml new file mode 100644 index 0000000..0c141c5 --- /dev/null +++ b/swc_demo/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "swc_demo" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +swc_common = { version = "0.17.22", features=["tty-emitter"] } +swc_ecma_parser = "0.102.2" +swc = "0.168.3" +swc_ecma_ast = "0.76.0" diff --git a/swc_demo/src/main.rs b/swc_demo/src/main.rs new file mode 100644 index 0000000..b861c35 --- /dev/null +++ b/swc_demo/src/main.rs @@ -0,0 +1,41 @@ +use std::sync::Arc; +use swc_common::{ + errors::{ColorConfig, Handler}, + FileName, SourceMap, +}; +use swc_ecma_ast::EsVersion; +use swc_ecma_parser::{Syntax, TsConfig}; + +fn main() { + let cm = Arc::::default(); + let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(cm.clone())); + let c = swc::Compiler::new(cm.clone()); + // let fm = cm + // .load_file(Path::new("foo.js")) + // .expect("failed to load file"); + let fm = cm.new_source_file( + FileName::Custom("test.js".into()), + " + function foo(x: number) { + if (x < 3) { + return 'lt3'; + } + + return 'nlt3'; + } + " + .into(), + ); + let result = c.parse_js( + fm, + &handler, + EsVersion::Es2020, + Syntax::Typescript(TsConfig::default()), + swc::config::IsModule::Bool(true), + None, + ); + + dbg!(&result); + + drop(result); +} diff --git a/valuescript_compiler/Cargo.toml b/valuescript_compiler/Cargo.toml new file mode 100644 index 0000000..0de369c --- /dev/null +++ b/valuescript_compiler/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "valuescript_compiler" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = "1.0" +serde_json = "1.0" +swc_atoms = "0.2" +swc_common = { version = "0.17.22", features=["tty-emitter"] } +swc_ecma_parser = "0.102.2" +swc = "0.168.3" +swc_ecma_ast = "0.76.0" +queues = "1.0.2" diff --git a/src/vstc/assemble.rs b/valuescript_compiler/src/assemble.rs similarity index 88% rename from src/vstc/assemble.rs rename to valuescript_compiler/src/assemble.rs index 90d6268..135bcc2 100644 --- a/src/vstc/assemble.rs +++ b/valuescript_compiler/src/assemble.rs @@ -1,48 +1,7 @@ -use std::rc::Rc; -use std::process::exit; use std::collections::HashMap; +use std::rc::Rc; use std::str::FromStr; -pub fn command(args: &Vec) { - if args.len() != 3 { - println!("ERROR: Unrecognized command\n"); - show_help(); - exit(1); - } - - if args[2] == "-h" || args[2] == "--help" { - show_help(); - return; - } - - let read_result = std::fs::read_to_string(&args[2]); - - if read_result.is_err() { - println!("Failed to read file {}", args[2]); - return; - } - - let content = read_result.expect(""); - let output_filename = "out.vsb"; - let bytecode = assemble(&content); - - let write_result = std::fs::write(output_filename, &*bytecode); - - if write_result.is_err() { - println!("Failed to write file {}", output_filename); - std::process::exit(1); - } -} - -fn show_help() { - println!("vstc assemble"); - println!(""); - println!("Convert ValueScript assembly to bytecode"); - println!(""); - println!("USAGE:"); - println!(" vstc assemble "); -} - #[derive(Default)] struct LocationMap { references: HashMap>, @@ -55,8 +14,9 @@ trait LocationMapper { } impl LocationMapper for LocationMap { - fn add_unresolved(&mut self, name: &String, output: &mut Vec){ - self.references + fn add_unresolved(&mut self, name: &String, output: &mut Vec) { + self + .references .entry(name.clone()) .or_default() .push(output.len()); @@ -70,11 +30,7 @@ impl LocationMapper for LocationMap { let location_optional = self.found_locations.get(name); if location_optional.is_none() { - std::panic!( - "Unresolved reference to {} at {}", - name, - ref_locations[0], - ); + std::panic!("Unresolved reference to {} at {}", name, ref_locations[0],); } let location = location_optional.unwrap(); @@ -146,9 +102,11 @@ impl<'a> Assembler<'a> { fn parse_optional_whitespace(&mut self) { loop { match self.pos.peek() { - Some(' ') => {}, - Some('\n') => {}, - _ => { return; } + Some(' ') => {} + Some('\n') => {} + _ => { + return; + } } self.pos.next(); @@ -158,7 +116,10 @@ impl<'a> Assembler<'a> { fn assemble_definition(&mut self) { self.parse_exact("@"); let def_name = self.parse_identifier(); - self.definitions_map.found_locations.insert(def_name, self.output.len()); + self + .definitions_map + .found_locations + .insert(def_name, self.output.len()); self.parse_optional_whitespace(); self.parse_exact("="); self.parse_optional_whitespace(); @@ -257,7 +218,9 @@ impl<'a> Assembler<'a> { let mut res = "".to_string(); let leading_char = match pos.next() { - None => { return None; }, + None => { + return None; + } Some(c) => c, }; @@ -269,7 +232,9 @@ impl<'a> Assembler<'a> { loop { match pos.next() { - None => { break; } + None => { + break; + } Some(c) => { if !is_identifier_char(c) { break; @@ -382,7 +347,9 @@ impl<'a> Assembler<'a> { if next == ")" { self.fn_data.register_count_pos = self.output.len(); self.output.push(0xff); - self.output.push((self.fn_data.register_map.len() - 3) as u8); // TODO: Handle >255 + self + .output + .push((self.fn_data.register_map.len() - 3) as u8); // TODO: Handle >255 break; } @@ -393,7 +360,10 @@ impl<'a> Assembler<'a> { let param_name = self.parse_identifier(); if self.fn_data.register_map.contains_key(param_name.as_str()) { - std::panic!("Unexpected duplicate parameter name at {}", self.get_pos_index()); + std::panic!( + "Unexpected duplicate parameter name at {}", + self.get_pos_index() + ); } self.get_register_index(param_name.as_str()); @@ -404,7 +374,9 @@ impl<'a> Assembler<'a> { if next == ")" { self.fn_data.register_count_pos = self.output.len(); self.output.push(0xff); - self.output.push((self.fn_data.register_map.len() - 3) as u8); // TODO: Handle >255 + self + .output + .push((self.fn_data.register_map.len() - 3) as u8); // TODO: Handle >255 break; } } @@ -415,7 +387,10 @@ impl<'a> Assembler<'a> { loop { self.parse_optional_whitespace(); - let c = *self.pos.peek().expect("Expected instruction, label, or end of function"); + let c = *self + .pos + .peek() + .expect("Expected instruction, label, or end of function"); if c == '}' { self.output.push(Instruction::End as u8); @@ -459,7 +434,7 @@ impl<'a> Assembler<'a> { let instr = self.parse_instruction_word(); self.output.push(instr.clone() as u8); - + for arg in get_instruction_layout(instr) { match arg { InstructionArg::Value => self.assemble_value(), @@ -477,49 +452,44 @@ impl<'a> Assembler<'a> { Some('%') => { self.output.push(ValueType::Register as u8); self.assemble_register(); - }, + } Some('@') => { self.parse_exact("@"); self.output.push(ValueType::Pointer as u8); let definition_name = self.parse_identifier(); - self.definitions_map.add_unresolved(&definition_name, &mut self.output); - }, + self + .definitions_map + .add_unresolved(&definition_name, &mut self.output); + } Some('$') => { self.parse_exact("$"); self.output.push(ValueType::Builtin as u8); self.assemble_builtin(); - }, + } Some('[') => { self.assemble_array(); - }, - Some('-' | '.' | '0' ..= '9') => { + } + Some('-' | '.' | '0'..='9') => { self.assemble_number(); - }, + } Some('"') => { self.assemble_string(); - }, + } Some('{') => { self.assemble_object(); - }, + } Some(ref_c) => { let c = *ref_c; - let parsed = self.parse_one_of(&[ - "void", - "undefined", - "null", - "false", - "true", - "", - ]); - + let parsed = self.parse_one_of(&["void", "undefined", "null", "false", "true", ""]); + match parsed.as_str() { "void" => self.output.push(ValueType::Void as u8), "undefined" => self.output.push(ValueType::Undefined as u8), "null" => self.output.push(ValueType::Null as u8), "false" => self.output.push(ValueType::False as u8), "true" => self.output.push(ValueType::True as u8), - + // TODO: Finish implementing the different values _ => std::panic!( "Unimplemented value type or unexpected character {} at {}", @@ -527,7 +497,7 @@ impl<'a> Assembler<'a> { self.get_pos_index(), ), } - }, + } } } @@ -546,8 +516,8 @@ impl<'a> Assembler<'a> { self.pos.next(); self.output.push(ValueType::End as u8); break; - }, - _ => {}, + } + _ => {} } self.assemble_value(); @@ -610,17 +580,21 @@ impl<'a> Assembler<'a> { advance_chars(&mut self.pos, label_name.len() + 1); - self.fn_data.labels_map.found_locations.insert( - label_name, - self.output.len(), - ); + self + .fn_data + .labels_map + .found_locations + .insert(label_name, self.output.len()); } fn assemble_label_read(&mut self) { self.parse_optional_whitespace(); self.parse_exact(":"); let label_name = self.parse_identifier(); - self.fn_data.labels_map.add_unresolved(&label_name, &mut self.output); + self + .fn_data + .labels_map + .add_unresolved(&label_name, &mut self.output); } fn assemble_number(&mut self) { @@ -628,10 +602,12 @@ impl<'a> Assembler<'a> { loop { match self.pos.peek() { - Some('-' | '.' | 'e' | '0' ..= '9') => { + Some('-' | '.' | 'e' | '0'..='9') => { num_string.push(self.pos.next().unwrap()); } - _ => { break; } + _ => { + break; + } } } @@ -686,7 +662,9 @@ impl<'a> Assembler<'a> { self.parse_exact("@"); self.output.push(ValueType::Pointer as u8); let definition_name = self.parse_identifier(); - self.definitions_map.add_unresolved(&definition_name, &mut self.output); + self + .definitions_map + .add_unresolved(&definition_name, &mut self.output); } else if c == '}' { self.output.push(ValueType::End as u8); self.pos.next(); @@ -721,7 +699,10 @@ impl<'a> Assembler<'a> { if get_result.is_none() { // TODO: Support >255 registers result = (self.fn_data.register_map.len() - 1) as u8; - self.fn_data.register_map.insert(register_name.to_string(), result); + self + .fn_data + .register_map + .insert(register_name.to_string(), result); } else { result = *get_result.unwrap(); } @@ -766,8 +747,7 @@ pub fn assemble(content: &str) -> Rc> { return Rc::new(assembler.output); } -#[derive(Debug)] -#[derive(Clone)] +#[derive(Debug, Clone)] enum Instruction { End = 0x00, Mov = 0x01, @@ -874,20 +854,11 @@ fn get_instruction_layout(instruction: Instruction) -> Vec { } fn is_leading_identifier_char(c: char) -> bool { - return - c == '_' || - ('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z') - ; + return c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); } fn is_identifier_char(c: char) -> bool { - return - c == '_' || - ('0' <= c && c <= '9') || - ('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z') - ; + return c == '_' || ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); } enum ValueType { diff --git a/src/vstc/capture_finder.rs b/valuescript_compiler/src/capture_finder.rs similarity index 100% rename from src/vstc/capture_finder.rs rename to valuescript_compiler/src/capture_finder.rs diff --git a/src/vstc/compile.rs b/valuescript_compiler/src/compile.rs similarity index 96% rename from src/vstc/compile.rs rename to valuescript_compiler/src/compile.rs index a6efcd4..d8c34dc 100644 --- a/src/vstc/compile.rs +++ b/valuescript_compiler/src/compile.rs @@ -1,7 +1,4 @@ use std::cell::RefCell; -use std::fs::File; -use std::io::prelude::*; -use std::process::exit; use std::rc::Rc; use std::sync::{Arc, Mutex}; @@ -10,53 +7,13 @@ use swc_common::{errors::Handler, FileName, SourceMap, Spanned}; use swc_ecma_ast::EsVersion; use swc_ecma_parser::{Syntax, TsConfig}; -use super::diagnostic::{handle_diagnostics_cli, Diagnostic, DiagnosticLevel}; +use super::diagnostic::{Diagnostic, DiagnosticLevel}; use super::expression_compiler::{string_literal, CompiledExpression, ExpressionCompiler}; use super::function_compiler::{FunctionCompiler, Functionish}; use super::name_allocator::NameAllocator; use super::scope::{init_std_scope, MappedName, Scope, ScopeTrait}; use super::scope_analysis::ScopeAnalysis; -pub fn command(args: &Vec) { - if args.len() != 3 { - println!("ERROR: Unrecognized command\n"); - show_help(); - exit(1); - } - - 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); - - let mut file = File::create("out.vsm").expect("Couldn't create out.vsm"); - - for line in compiler_output.assembly { - file - .write_all(line.as_bytes()) - .expect("Failed to write line"); - file.write_all(b"\n").expect("Failed to write line"); - } -} - -fn show_help() { - println!("vstc compile"); - println!(""); - println!("Compile ValueScript"); - println!(""); - println!("USAGE:"); - println!(" vstc compile "); -} - struct DiagnosticCollector { diagnostics: Arc>>, } diff --git a/src/vstc/diagnostic.rs b/valuescript_compiler/src/diagnostic.rs similarity index 59% rename from src/vstc/diagnostic.rs rename to valuescript_compiler/src/diagnostic.rs index c34432f..8f9acb6 100644 --- a/src/vstc/diagnostic.rs +++ b/valuescript_compiler/src/diagnostic.rs @@ -52,50 +52,3 @@ impl Diagnostic { }); } } - -pub fn handle_diagnostics_cli(file_path: &String, diagnostics: &Vec) { - let mut has_error = false; - - let text = std::fs::read_to_string(file_path).unwrap(); - - for diagnostic in diagnostics { - let (line, col) = pos_to_line_col(&text, diagnostic.span.lo.0); - - println!( - "{}:{}:{}: {}: {}", - file_path, line, col, diagnostic.level, diagnostic.message - ); - - match diagnostic.level { - DiagnosticLevel::Error | DiagnosticLevel::InternalError => { - has_error = true; - } - DiagnosticLevel::Lint => {} - DiagnosticLevel::CompilerDebug => {} - } - } - - if has_error { - std::process::exit(1); - } -} - -fn pos_to_line_col(text: &String, pos: u32) -> (u32, u32) { - let mut line = 1u32; - let mut col = 1u32; - - for (i, c) in text.chars().enumerate() { - if i as u32 == pos { - break; - } - - if c == '\n' { - line += 1; - col = 1; - } else { - col += 1; - } - } - - return (line, col); -} diff --git a/src/vstc/expression_compiler.rs b/valuescript_compiler/src/expression_compiler.rs similarity index 100% rename from src/vstc/expression_compiler.rs rename to valuescript_compiler/src/expression_compiler.rs diff --git a/src/vstc/function_compiler.rs b/valuescript_compiler/src/function_compiler.rs similarity index 100% rename from src/vstc/function_compiler.rs rename to valuescript_compiler/src/function_compiler.rs diff --git a/valuescript_compiler/src/lib.rs b/valuescript_compiler/src/lib.rs new file mode 100644 index 0000000..fda0bbe --- /dev/null +++ b/valuescript_compiler/src/lib.rs @@ -0,0 +1,14 @@ +mod assemble; +mod capture_finder; +mod compile; +mod diagnostic; +mod expression_compiler; +mod function_compiler; +mod name_allocator; +mod scope; +mod scope_analysis; + +pub use assemble::assemble; +pub use compile::compile; +pub use diagnostic::Diagnostic; +pub use diagnostic::DiagnosticLevel; diff --git a/src/vstc/name_allocator.rs b/valuescript_compiler/src/name_allocator.rs similarity index 100% rename from src/vstc/name_allocator.rs rename to valuescript_compiler/src/name_allocator.rs diff --git a/src/vstc/scope.rs b/valuescript_compiler/src/scope.rs similarity index 100% rename from src/vstc/scope.rs rename to valuescript_compiler/src/scope.rs diff --git a/src/vstc/scope_analysis.rs b/valuescript_compiler/src/scope_analysis.rs similarity index 99% rename from src/vstc/scope_analysis.rs rename to valuescript_compiler/src/scope_analysis.rs index c5c0c0d..c1af4b7 100644 --- a/src/vstc/scope_analysis.rs +++ b/valuescript_compiler/src/scope_analysis.rs @@ -11,9 +11,14 @@ pub enum NameId { Builtin(Builtin), } +// TODO: Make use of these in the next phase of the compiler, remove the +// allow(dead_code) attributes #[derive(Clone)] pub struct Capture { + #[allow(dead_code)] ref_: swc_common::Span, + + #[allow(dead_code)] captor_id: OwnerId, } diff --git a/valuescript_vm/Cargo.toml b/valuescript_vm/Cargo.toml new file mode 100644 index 0000000..bb0ebde --- /dev/null +++ b/valuescript_vm/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "valuescript_vm" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/vstc/virtual_machine/array_higher_functions/array_every.rs b/valuescript_vm/src/array_higher_functions/array_every.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/array_every.rs rename to valuescript_vm/src/array_higher_functions/array_every.rs diff --git a/src/vstc/virtual_machine/array_higher_functions/array_filter.rs b/valuescript_vm/src/array_higher_functions/array_filter.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/array_filter.rs rename to valuescript_vm/src/array_higher_functions/array_filter.rs diff --git a/src/vstc/virtual_machine/array_higher_functions/array_find.rs b/valuescript_vm/src/array_higher_functions/array_find.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/array_find.rs rename to valuescript_vm/src/array_higher_functions/array_find.rs diff --git a/src/vstc/virtual_machine/array_higher_functions/array_find_index.rs b/valuescript_vm/src/array_higher_functions/array_find_index.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/array_find_index.rs rename to valuescript_vm/src/array_higher_functions/array_find_index.rs diff --git a/src/vstc/virtual_machine/array_higher_functions/array_flat_map.rs b/valuescript_vm/src/array_higher_functions/array_flat_map.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/array_flat_map.rs rename to valuescript_vm/src/array_higher_functions/array_flat_map.rs diff --git a/src/vstc/virtual_machine/array_higher_functions/array_map.rs b/valuescript_vm/src/array_higher_functions/array_map.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/array_map.rs rename to valuescript_vm/src/array_higher_functions/array_map.rs diff --git a/src/vstc/virtual_machine/array_higher_functions/array_mapping_frame.rs b/valuescript_vm/src/array_higher_functions/array_mapping_frame.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/array_mapping_frame.rs rename to valuescript_vm/src/array_higher_functions/array_mapping_frame.rs diff --git a/src/vstc/virtual_machine/array_higher_functions/array_reduce.rs b/valuescript_vm/src/array_higher_functions/array_reduce.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/array_reduce.rs rename to valuescript_vm/src/array_higher_functions/array_reduce.rs diff --git a/src/vstc/virtual_machine/array_higher_functions/array_reduce_right.rs b/valuescript_vm/src/array_higher_functions/array_reduce_right.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/array_reduce_right.rs rename to valuescript_vm/src/array_higher_functions/array_reduce_right.rs diff --git a/src/vstc/virtual_machine/array_higher_functions/array_some.rs b/valuescript_vm/src/array_higher_functions/array_some.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/array_some.rs rename to valuescript_vm/src/array_higher_functions/array_some.rs diff --git a/src/vstc/virtual_machine/array_higher_functions/array_sort.rs b/valuescript_vm/src/array_higher_functions/array_sort.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/array_sort.rs rename to valuescript_vm/src/array_higher_functions/array_sort.rs diff --git a/src/vstc/virtual_machine/array_higher_functions/mod.rs b/valuescript_vm/src/array_higher_functions/mod.rs similarity index 100% rename from src/vstc/virtual_machine/array_higher_functions/mod.rs rename to valuescript_vm/src/array_higher_functions/mod.rs diff --git a/src/vstc/virtual_machine/builtins.rs b/valuescript_vm/src/builtins.rs similarity index 100% rename from src/vstc/virtual_machine/builtins.rs rename to valuescript_vm/src/builtins.rs diff --git a/src/vstc/virtual_machine/bytecode_decoder.rs b/valuescript_vm/src/bytecode_decoder.rs similarity index 100% rename from src/vstc/virtual_machine/bytecode_decoder.rs rename to valuescript_vm/src/bytecode_decoder.rs diff --git a/src/vstc/virtual_machine/bytecode_stack_frame.rs b/valuescript_vm/src/bytecode_stack_frame.rs similarity index 100% rename from src/vstc/virtual_machine/bytecode_stack_frame.rs rename to valuescript_vm/src/bytecode_stack_frame.rs diff --git a/src/vstc/virtual_machine/debug.rs b/valuescript_vm/src/debug.rs similarity index 100% rename from src/vstc/virtual_machine/debug.rs rename to valuescript_vm/src/debug.rs diff --git a/src/vstc/virtual_machine/first_stack_frame.rs b/valuescript_vm/src/first_stack_frame.rs similarity index 100% rename from src/vstc/virtual_machine/first_stack_frame.rs rename to valuescript_vm/src/first_stack_frame.rs diff --git a/src/vstc/virtual_machine/instruction.rs b/valuescript_vm/src/instruction.rs similarity index 100% rename from src/vstc/virtual_machine/instruction.rs rename to valuescript_vm/src/instruction.rs diff --git a/src/vstc/virtual_machine/mod.rs b/valuescript_vm/src/lib.rs similarity index 100% rename from src/vstc/virtual_machine/mod.rs rename to valuescript_vm/src/lib.rs index 5f5420c..6437b4a 100644 --- a/src/vstc/virtual_machine/mod.rs +++ b/valuescript_vm/src/lib.rs @@ -1,22 +1,22 @@ -mod vs_value; -mod vs_function; -mod vs_pointer; -mod operations; -mod bytecode_decoder; -mod virtual_machine; -mod instruction; -mod vs_object; -mod vs_array; -mod native_function; -mod builtins; -mod math; -mod vs_class; -mod bytecode_stack_frame; -mod stack_frame; -mod first_stack_frame; mod array_higher_functions; -mod native_frame_function; +mod builtins; +mod bytecode_decoder; +mod bytecode_stack_frame; mod debug; +mod first_stack_frame; +mod instruction; +mod math; +mod native_frame_function; +mod native_function; +mod operations; +mod stack_frame; +mod virtual_machine; +mod vs_array; +mod vs_class; +mod vs_function; +mod vs_object; +mod vs_pointer; +mod vs_value; pub use virtual_machine::VirtualMachine; pub use vs_value::ValTrait; diff --git a/src/vstc/virtual_machine/math.rs b/valuescript_vm/src/math.rs similarity index 100% rename from src/vstc/virtual_machine/math.rs rename to valuescript_vm/src/math.rs diff --git a/src/vstc/virtual_machine/native_frame_function.rs b/valuescript_vm/src/native_frame_function.rs similarity index 100% rename from src/vstc/virtual_machine/native_frame_function.rs rename to valuescript_vm/src/native_frame_function.rs diff --git a/src/vstc/virtual_machine/native_function.rs b/valuescript_vm/src/native_function.rs similarity index 100% rename from src/vstc/virtual_machine/native_function.rs rename to valuescript_vm/src/native_function.rs diff --git a/src/vstc/virtual_machine/operations.rs b/valuescript_vm/src/operations.rs similarity index 100% rename from src/vstc/virtual_machine/operations.rs rename to valuescript_vm/src/operations.rs diff --git a/src/vstc/virtual_machine/stack_frame.rs b/valuescript_vm/src/stack_frame.rs similarity index 100% rename from src/vstc/virtual_machine/stack_frame.rs rename to valuescript_vm/src/stack_frame.rs diff --git a/src/vstc/virtual_machine/virtual_machine.rs b/valuescript_vm/src/virtual_machine.rs similarity index 90% rename from src/vstc/virtual_machine/virtual_machine.rs rename to valuescript_vm/src/virtual_machine.rs index 24690ec..4845d89 100644 --- a/src/vstc/virtual_machine/virtual_machine.rs +++ b/valuescript_vm/src/virtual_machine.rs @@ -1,9 +1,9 @@ use std::rc::Rc; -use super::vs_value::{Val, ValTrait, LoadFunctionResult}; use super::bytecode_decoder::BytecodeDecoder; -use super::stack_frame::{StackFrame, FrameStepResult}; use super::first_stack_frame::FirstStackFrame; +use super::stack_frame::{FrameStepResult, StackFrame}; +use super::vs_value::{LoadFunctionResult, Val, ValTrait}; pub struct VirtualMachine { pub frame: StackFrame, @@ -50,14 +50,14 @@ impl VirtualMachine { pub fn step(&mut self) { match self.frame.step() { - FrameStepResult::Continue => {}, + FrameStepResult::Continue => {} FrameStepResult::Pop(call_result) => { self.pop(); self.frame.apply_call_result(call_result); - }, + } FrameStepResult::Push(new_frame) => { self.push(new_frame); - }, + } }; } diff --git a/src/vstc/virtual_machine/vs_array.rs b/valuescript_vm/src/vs_array.rs similarity index 100% rename from src/vstc/virtual_machine/vs_array.rs rename to valuescript_vm/src/vs_array.rs diff --git a/src/vstc/virtual_machine/vs_class.rs b/valuescript_vm/src/vs_class.rs similarity index 100% rename from src/vstc/virtual_machine/vs_class.rs rename to valuescript_vm/src/vs_class.rs diff --git a/src/vstc/virtual_machine/vs_function.rs b/valuescript_vm/src/vs_function.rs similarity index 100% rename from src/vstc/virtual_machine/vs_function.rs rename to valuescript_vm/src/vs_function.rs diff --git a/src/vstc/virtual_machine/vs_object.rs b/valuescript_vm/src/vs_object.rs similarity index 100% rename from src/vstc/virtual_machine/vs_object.rs rename to valuescript_vm/src/vs_object.rs diff --git a/src/vstc/virtual_machine/vs_pointer.rs b/valuescript_vm/src/vs_pointer.rs similarity index 100% rename from src/vstc/virtual_machine/vs_pointer.rs rename to valuescript_vm/src/vs_pointer.rs diff --git a/src/vstc/virtual_machine/vs_value.rs b/valuescript_vm/src/vs_value.rs similarity index 96% rename from src/vstc/virtual_machine/vs_value.rs rename to valuescript_vm/src/vs_value.rs index cd6ec89..2c87493 100644 --- a/src/vstc/virtual_machine/vs_value.rs +++ b/valuescript_vm/src/vs_value.rs @@ -1,12 +1,12 @@ use std::rc::Rc; use std::str::FromStr; -use super::vs_function::VsFunction; -use super::vs_object::VsObject; -use super::vs_array::VsArray; -use super::vs_class::VsClass; use super::operations::{op_sub, op_submov}; use super::stack_frame::StackFrame; +use super::vs_array::VsArray; +use super::vs_class::VsClass; +use super::vs_function::VsFunction; +use super::vs_object::VsObject; #[derive(Clone)] pub enum Val { @@ -111,14 +111,16 @@ impl ValTrait for Val { res += ","; match val.typeof_() { - VsType::Undefined => {}, - _ => { res += &val.val_to_string(); }, + VsType::Undefined => {} + _ => { + res += &val.val_to_string(); + } }; } res } - }, + } Object(_) => "[object Object]".to_string(), Function(_) => "[function]".to_string(), Class(_) => "[class]".to_string(), @@ -188,7 +190,7 @@ impl ValTrait for Val { Class(_) => false, Static(val) => val.is_primitive(), // TODO: false? Custom(val) => val.is_primitive(), - } + }; } fn to_primitive(&self) -> Val { @@ -333,7 +335,7 @@ impl ValTrait for Val { res } - }, + } Val::Object(object) => { if object.string_map.len() == 0 { return "{}".into(); @@ -357,7 +359,7 @@ impl ValTrait for Val { res += "}"; res - }, + } Val::Function(_) => "() => { [unavailable] }".to_string(), Val::Class(_) => "class { [unavailable] }".to_string(), Val::Static(val) => val.codify(), @@ -395,15 +397,17 @@ impl std::fmt::Display for Val { } write!(f, " ]") - }, + } Val::Object(object) => { if object.string_map.len() == 0 { return f.write_str("{}"); } match f.write_str("{ ") { - Ok(_) => {}, - Err(e) => { return Err(e); }, + Ok(_) => {} + Err(e) => { + return Err(e); + } }; let mut first = true; @@ -419,7 +423,7 @@ impl std::fmt::Display for Val { } f.write_str(" }") - }, + } Val::Function(_) => write!(f, "\x1b[36m[Function]\x1b[39m"), Val::Class(_) => write!(f, "\x1b[36m[Class]\x1b[39m"), @@ -432,7 +436,7 @@ impl std::fmt::Display for Val { fn number_to_index(x: f64) -> Option { if x < 0_f64 || x != x.floor() { - return None + return None; } return Some(x as usize); @@ -451,8 +455,12 @@ fn stringify_string(str: &String) -> String { }; match escape_seq { - Some(seq) => { res += seq; }, - None => { res.push(c); } + Some(seq) => { + res += seq; + } + None => { + res.push(c); + } }; } diff --git a/valuescript_wasm/Cargo.toml b/valuescript_wasm/Cargo.toml new file mode 100644 index 0000000..9b13c53 --- /dev/null +++ b/valuescript_wasm/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "valuescript_wasm" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = "1.0" +serde_json = "1.0" +valuescript_compiler = { path = "../valuescript_compiler" } +valuescript_vm = { path = "../valuescript_vm" } + +# wasm-related + +wasm-bindgen = "0.2.63" + +# The `console_error_panic_hook` crate provides better debugging of panics by +# logging them with `console.error`. This is great for development, but requires +# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for +# code size when deploying. +console_error_panic_hook = { version = "0.1.6", optional = true } + +# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size +# compared to the default allocator's ~10K. It is slower than the default +# allocator, however. +wee_alloc = { version = "0.4.5", optional = true } + +[dev-dependencies] +wasm-bindgen-test = "0.3.13" diff --git a/valuescript_wasm/src/lib.rs b/valuescript_wasm/src/lib.rs new file mode 100644 index 0000000..9209b7d --- /dev/null +++ b/valuescript_wasm/src/lib.rs @@ -0,0 +1,59 @@ +use wasm_bindgen::prelude::*; + +use valuescript_compiler::DiagnosticLevel; +use valuescript_vm::ValTrait; + +// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global +// allocator. +#[cfg(feature = "wee_alloc")] +#[global_allocator] +static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + +#[derive(serde::Serialize)] +struct RunResult { + diagnostics: Vec, + output: Result, +} + +fn run_to_result(source: &str) -> RunResult { + let compiler_output = valuescript_compiler::compile(source); + + let mut have_compiler_errors = false; + + for diagnostic in &compiler_output.diagnostics { + match diagnostic.level { + DiagnosticLevel::Error => have_compiler_errors = true, + DiagnosticLevel::InternalError => have_compiler_errors = true, + _ => (), + } + } + + if have_compiler_errors { + return RunResult { + diagnostics: compiler_output.diagnostics, + output: Err("Compile failed".into()), + }; + } + + let bytecode = valuescript_compiler::assemble(compiler_output.assembly.join("\n").as_str()); + + let mut vm = valuescript_vm::VirtualMachine::new(); + let result = vm.run(&bytecode, &[]); + + return RunResult { + diagnostics: compiler_output.diagnostics, + output: Ok(result.codify()), + }; +} + +#[wasm_bindgen] +pub fn compile(source: &str) -> String { + let output = valuescript_compiler::compile(source); + return serde_json::to_string(&output).expect("Failed json serialization"); +} + +#[wasm_bindgen] +pub fn run(source: &str) -> String { + let result = run_to_result(source); + return serde_json::to_string(&result).expect("Failed json serialization"); +} diff --git a/vstc/Cargo.toml b/vstc/Cargo.toml new file mode 100644 index 0000000..ceac6f6 --- /dev/null +++ b/vstc/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "vstc" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +valuescript_compiler = { path = "../valuescript_compiler" } +valuescript_vm = { path = "../valuescript_vm" } diff --git a/vstc/src/assemble_command.rs b/vstc/src/assemble_command.rs new file mode 100644 index 0000000..b1435f3 --- /dev/null +++ b/vstc/src/assemble_command.rs @@ -0,0 +1,43 @@ +use std::process::exit; + +use valuescript_compiler::assemble; + +pub fn assemble_command(args: &Vec) { + if args.len() != 3 { + println!("ERROR: Unrecognized command\n"); + show_help(); + exit(1); + } + + if args[2] == "-h" || args[2] == "--help" { + show_help(); + return; + } + + let read_result = std::fs::read_to_string(&args[2]); + + if read_result.is_err() { + println!("Failed to read file {}", args[2]); + return; + } + + let content = read_result.expect(""); + let output_filename = "out.vsb"; + let bytecode = assemble(&content); + + let write_result = std::fs::write(output_filename, &*bytecode); + + if write_result.is_err() { + println!("Failed to write file {}", output_filename); + std::process::exit(1); + } +} + +fn show_help() { + println!("vstc assemble"); + println!(""); + println!("Convert ValueScript assembly to bytecode"); + println!(""); + println!("USAGE:"); + println!(" vstc assemble "); +} diff --git a/vstc/src/compile_command.rs b/vstc/src/compile_command.rs new file mode 100644 index 0000000..3e7bdc5 --- /dev/null +++ b/vstc/src/compile_command.rs @@ -0,0 +1,37 @@ +use std::fs::File; +use std::io::Write; +use std::process::exit; + +use super::handle_diagnostics_cli::handle_diagnostics_cli; +use valuescript_compiler::compile; + +pub fn compile_command(args: &Vec) { + if args.len() != 3 { + println!("ERROR: Unrecognized command\n"); + show_help(); + exit(1); + } + + let source = std::fs::read_to_string(&args[2]).expect("Failed to read file"); + let compiler_output = compile(&source); + + handle_diagnostics_cli(&args[2], &compiler_output.diagnostics); + + let mut file = File::create("out.vsm").expect("Couldn't create out.vsm"); + + for line in compiler_output.assembly { + file + .write_all(line.as_bytes()) + .expect("Failed to write line"); + file.write_all(b"\n").expect("Failed to write line"); + } +} + +fn show_help() { + println!("vstc compile"); + println!(""); + println!("Compile ValueScript"); + println!(""); + println!("USAGE:"); + println!(" vstc compile "); +} diff --git a/vstc/src/handle_diagnostics_cli.rs b/vstc/src/handle_diagnostics_cli.rs new file mode 100644 index 0000000..ade821e --- /dev/null +++ b/vstc/src/handle_diagnostics_cli.rs @@ -0,0 +1,48 @@ +use valuescript_compiler::{Diagnostic, DiagnosticLevel}; + +pub fn handle_diagnostics_cli(file_path: &String, diagnostics: &Vec) { + let mut has_error = false; + + let text = std::fs::read_to_string(file_path).unwrap(); + + for diagnostic in diagnostics { + let (line, col) = pos_to_line_col(&text, diagnostic.span.lo.0); + + println!( + "{}:{}:{}: {}: {}", + file_path, line, col, diagnostic.level, diagnostic.message + ); + + match diagnostic.level { + DiagnosticLevel::Error | DiagnosticLevel::InternalError => { + has_error = true; + } + DiagnosticLevel::Lint => {} + DiagnosticLevel::CompilerDebug => {} + } + } + + if has_error { + std::process::exit(1); + } +} + +fn pos_to_line_col(text: &String, pos: u32) -> (u32, u32) { + let mut line = 1u32; + let mut col = 1u32; + + for (i, c) in text.chars().enumerate() { + if i as u32 == pos { + break; + } + + if c == '\n' { + line += 1; + col = 1; + } else { + col += 1; + } + } + + return (line, col); +} diff --git a/src/vstc/main.rs b/vstc/src/main.rs similarity index 84% rename from src/vstc/main.rs rename to vstc/src/main.rs index 4c03caf..d4f272c 100644 --- a/src/vstc/main.rs +++ b/vstc/src/main.rs @@ -1,18 +1,15 @@ -mod assemble; -mod capture_finder; -mod compile; -mod diagnostic; -mod expression_compiler; -mod function_compiler; -mod name_allocator; -mod run; -mod scope; -mod scope_analysis; -mod virtual_machine; +mod assemble_command; +mod compile_command; +mod handle_diagnostics_cli; +mod run_command; use std::env; use std::process::exit; +use assemble_command::assemble_command; +use compile_command::compile_command; +use run_command::run_command; + fn main() { let args: Vec = env::args().collect(); @@ -26,17 +23,17 @@ fn main() { } if args.len() >= 2 && args[1] == "assemble" { - assemble::command(&args); + assemble_command(&args); return; } if args.len() >= 2 && args[1] == "run" { - run::command(&args); + run_command(&args); return; } if args.len() >= 2 && args[1] == "compile" { - compile::command(&args); + compile_command(&args); return; } diff --git a/src/vstc/run.rs b/vstc/src/run_command.rs similarity index 69% rename from src/vstc/run.rs rename to vstc/src/run_command.rs index 02c0302..1454856 100644 --- a/src/vstc/run.rs +++ b/vstc/src/run_command.rs @@ -1,17 +1,12 @@ -use std::ffi::OsStr; -use std::path::Path; -use std::process::exit; use std::rc::Rc; +use std::{ffi::OsStr, path::Path, process::exit}; -use super::assemble::assemble; -use super::compile::compile; -use super::diagnostic::handle_diagnostics_cli; -use super::diagnostic::Diagnostic; -use super::diagnostic::DiagnosticLevel; -use super::virtual_machine::ValTrait; -use super::virtual_machine::VirtualMachine; +use valuescript_compiler::{assemble, compile}; +use valuescript_vm::VirtualMachine; -pub fn command(args: &Vec) { +use super::handle_diagnostics_cli::handle_diagnostics_cli; + +pub fn run_command(args: &Vec) { if args.len() < 3 { println!("ERROR: Unrecognized command\n"); show_help(); @@ -45,43 +40,6 @@ pub fn command(args: &Vec) { println!("{}", result); } -#[derive(serde::Serialize)] -pub struct RunResult { - pub diagnostics: Vec, - pub output: Result, -} - -pub fn run(source: &str) -> RunResult { - let compiler_output = compile(source); - - let mut have_compiler_errors = false; - - for diagnostic in &compiler_output.diagnostics { - match diagnostic.level { - DiagnosticLevel::Error => have_compiler_errors = true, - DiagnosticLevel::InternalError => have_compiler_errors = true, - _ => (), - } - } - - if have_compiler_errors { - return RunResult { - diagnostics: compiler_output.diagnostics, - output: Err("Compile failed".into()), - }; - } - - let bytecode = assemble(compiler_output.assembly.join("\n").as_str()); - - let mut vm = VirtualMachine::new(); - let result = vm.run(&bytecode, &[]); - - return RunResult { - diagnostics: compiler_output.diagnostics, - output: Ok(result.codify()), - }; -} - enum RunFormat { TypeScript, Assembly, diff --git a/website/src/playground/vslib/index.ts b/website/src/playground/vslib/index.ts index 9bfac4e..c034e9c 100644 --- a/website/src/playground/vslib/index.ts +++ b/website/src/playground/vslib/index.ts @@ -2,6 +2,9 @@ export async function initVslib() { // deno-lint-ignore no-explicit-any const wasm: Record = (await WebAssembly.instantiateStreaming( fetch(`${location.origin}/value_script_bg.wasm`), + { + "./valuescript_wasm_bg.js": { __wbindgen_throw }, + }, )).instance.exports; let WASM_VECTOR_LEN = 0; @@ -128,6 +131,10 @@ export async function initVslib() { } } + function __wbindgen_throw(arg0: number, arg1: number) { + throw new Error(getStringFromWasm0(arg0, arg1)); + } + return { compile, run,