diff --git a/valuescript_compiler/src/asm.rs b/valuescript_compiler/src/asm.rs index eb77e5b..9193dd4 100644 --- a/valuescript_compiler/src/asm.rs +++ b/valuescript_compiler/src/asm.rs @@ -11,10 +11,36 @@ pub use crate::instruction::{Instruction, InstructionFieldMut}; #[derive(Debug, Clone, Default)] pub struct Module { pub export_default: Value, - pub export_star: Object, + pub export_star: ExportStar, pub definitions: Vec, } +#[derive(Debug, Clone, Default)] +pub struct ExportStar { + pub includes: Vec, + pub local: Object, +} + +impl std::fmt::Display for ExportStar { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.local.properties.is_empty() && self.includes.is_empty() { + return write!(f, "{{}}"); + } + + writeln!(f, "{{")?; + + for p in &self.includes { + writeln!(f, " include {},", p)?; + } + + for (name, value) in &self.local.properties { + writeln!(f, " {}: {},", name, value)?; + } + + write!(f, "}}") + } +} + impl Module { pub fn as_lines(&self) -> Vec { let assembly_str = self.to_string(); @@ -26,17 +52,7 @@ impl Module { impl std::fmt::Display for Module { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - if self.export_star.properties.is_empty() { - write!(f, "export {} {}", self.export_default, self.export_star)?; - } else { - writeln!(f, "export {} {{", self.export_default)?; - - for (name, value) in &self.export_star.properties { - writeln!(f, " {}: {},", name, value)?; - } - - write!(f, "}}")?; - } + write!(f, "export {} {}", self.export_default, self.export_star)?; for definition in &self.definitions { write!(f, "\n\n{}", definition)?; diff --git a/valuescript_compiler/src/assembler.rs b/valuescript_compiler/src/assembler.rs index 011bfe8..e8abdc9 100644 --- a/valuescript_compiler/src/assembler.rs +++ b/valuescript_compiler/src/assembler.rs @@ -36,7 +36,14 @@ struct Assembler { impl Assembler { fn module(&mut self, module: &Module) { self.value(&module.export_default); - self.object(&module.export_star); + self.output.push(ValueType::ExportStar as u8); + self.varsize_uint(module.export_star.includes.len()); + + for p in &module.export_star.includes { + self.pointer(p); + } + + self.object(&module.export_star.local); for definition in &module.definitions { self.definition(definition); @@ -448,6 +455,7 @@ pub enum ValueType { Lazy = 0x12, BigInt = 0x13, GeneratorFunction = 0x14, + ExportStar = 0x15, // External = TBD, } diff --git a/valuescript_compiler/src/assembly_parser.rs b/valuescript_compiler/src/assembly_parser.rs index a48795a..db3d594 100644 --- a/valuescript_compiler/src/assembly_parser.rs +++ b/valuescript_compiler/src/assembly_parser.rs @@ -5,8 +5,8 @@ use num_bigint::BigInt; use valuescript_common::{InstructionByte, BUILTIN_NAMES}; use crate::asm::{ - Array, Builtin, Class, Definition, DefinitionContent, FnLine, Function, Instruction, Label, - LabelRef, Module, Number, Object, Pointer, Register, Value, + Array, Builtin, Class, Definition, DefinitionContent, ExportStar, FnLine, Function, Instruction, + Label, LabelRef, Module, Number, Object, Pointer, Register, Value, }; pub struct AssemblyParser<'a> { @@ -22,7 +22,7 @@ impl<'a> AssemblyParser<'a> { let export_default = self.assemble_value(); self.parse_whitespace(); - let export_star = self.assemble_object(); + let export_star = self.assemble_export_star(); self.parse_whitespace(); let mut definitions = Vec::::new(); @@ -777,11 +777,7 @@ impl<'a> AssemblyParser<'a> { panic!("{}", self.render_pos(0, &"Expected value".to_string())); } Some('%') => Value::Register(self.assemble_register()), - Some('@') => { - self.parse_exact("@"); - let name = self.parse_identifier(); - Value::Pointer(Pointer { name }) - } + Some('@') => Value::Pointer(self.assemble_pointer()), Some('$') => Value::Builtin(self.assemble_builtin()), Some('[') => Value::Array(Box::new(self.assemble_array())), Some('-' | '.' | '0'..='9') => self.assemble_number(), @@ -826,6 +822,12 @@ impl<'a> AssemblyParser<'a> { } } + fn assemble_pointer(&mut self) -> Pointer { + self.parse_exact("@"); + let name = self.parse_identifier(); + Pointer { name } + } + fn assemble_array(&mut self) -> Array { let mut array = Array::default(); @@ -964,26 +966,68 @@ impl<'a> AssemblyParser<'a> { self.parse_exact("{"); loop { + match self.assemble_object_kv() { + None => break object, + Some(kv) => object.properties.push(kv), + }; + self.parse_optional_whitespace(); - let mut c = *self.pos.peek().expect("Expected object content or end"); - let key = match c { + let c = *self.pos.peek().expect("Expected comma or object end"); + + match c { + ',' => { + self.pos.next(); + } '}' => { self.pos.next(); break object; } - _ => self.assemble_value(), - }; + _ => { + panic!( + "{}", + self.render_pos(0, &format!("Unexpected character {}", c)) + ); + } + } + } + } + + fn assemble_object_kv(&mut self) -> Option<(Value, Value)> { + self.parse_optional_whitespace(); + let c = *self.pos.peek().expect("Expected object content or end"); + + let key = match c { + '}' => { + self.pos.next(); + return None; + } + _ => self.assemble_value(), + }; + + self.parse_optional_whitespace(); + self.parse_exact(":"); + let value = self.assemble_value(); + Some((key, value)) + } + + fn assemble_export_star(&mut self) -> ExportStar { + let mut export_star = ExportStar::default(); + + self.parse_exact("{"); + + loop { self.parse_optional_whitespace(); - self.parse_exact(":"); - let value = self.assemble_value(); - object.properties.push((key, value)); + if self.parse_one_of(&["include ", ""]) == "" { + break; + } + export_star.includes.push(self.assemble_pointer()); self.parse_optional_whitespace(); - c = *self.pos.peek().expect("Expected comma or object end"); + let c = *self.pos.peek().expect("Expected comma or object end"); match c { ',' => { @@ -991,7 +1035,34 @@ impl<'a> AssemblyParser<'a> { } '}' => { self.pos.next(); - break object; + return export_star; + } + _ => { + panic!( + "{}", + self.render_pos(0, &format!("Unexpected character {}", c)) + ); + } + } + } + + loop { + match self.assemble_object_kv() { + None => break export_star, + Some(kv) => export_star.local.properties.push(kv), + }; + + self.parse_optional_whitespace(); + + let c = *self.pos.peek().expect("Expected comma or object end"); + + match c { + ',' => { + self.pos.next(); + } + '}' => { + self.pos.next(); + break export_star; } _ => { panic!( diff --git a/valuescript_compiler/src/link_module.rs b/valuescript_compiler/src/link_module.rs index 5df97e3..1beae24 100644 --- a/valuescript_compiler/src/link_module.rs +++ b/valuescript_compiler/src/link_module.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::asm::{Definition, DefinitionContent, FnLine, Instruction, Object, Pointer, Value}; +use crate::asm::{Definition, DefinitionContent, ExportStar, FnLine, Instruction, Pointer, Value}; use crate::gather_modules::PathAndModule; use crate::import_pattern::{ImportKind, ImportPattern}; use crate::name_allocator::NameAllocator; @@ -25,7 +25,7 @@ pub fn link_module( }; let mut pointer_allocator = NameAllocator::default(); - let mut included_modules = HashMap::::new(); + let mut included_modules = HashMap::::new(); let mut path_and_module = match modules.get(&entry_point.clone()) { Some(path_and_module) => path_and_module.clone(), @@ -171,7 +171,7 @@ fn resolve_and_rewrite_import_patterns(path_and_module: &mut PathAndModule) -> V fn link_import_patterns( module: &mut Module, - included_modules: &HashMap, + included_modules: &HashMap, diagnostics: &mut Vec, ) { for definition in &mut module.definitions { @@ -194,10 +194,15 @@ fn link_import_patterns( pointer: import_pattern.pointer, content: match import_pattern.kind { ImportKind::Default => DefinitionContent::Value(default.clone()), - ImportKind::Star => DefinitionContent::Value(Value::Object(Box::new(namespace.clone()))), - ImportKind::Name(name) => match namespace.try_resolve_key(&name) { + ImportKind::Star => { + // TODO: namespace.includes + DefinitionContent::Value(Value::Object(Box::new(namespace.local.clone()))) + } + ImportKind::Name(name) => match namespace.local.try_resolve_key(&name) { Some(value) => DefinitionContent::Value(value.clone()), None => { + // TODO: namespace.includes + diagnostics.push(Diagnostic { level: DiagnosticLevel::Error, message: format!( diff --git a/valuescript_compiler/src/module_compiler.rs b/valuescript_compiler/src/module_compiler.rs index 303f0c1..89580e4 100644 --- a/valuescript_compiler/src/module_compiler.rs +++ b/valuescript_compiler/src/module_compiler.rs @@ -284,7 +284,7 @@ impl ModuleCompiler { }); if export { - self.module.export_star.properties.push(( + self.module.export_star.local.properties.push(( Value::String(ident.sym.to_string()), Value::Pointer(pointer), )); @@ -312,7 +312,7 @@ impl ModuleCompiler { }; if export { - self.module.export_star.properties.push(( + self.module.export_star.local.properties.push(( Value::String(fn_name.clone()), Value::Pointer(pointer.clone()), )); @@ -341,7 +341,7 @@ impl ModuleCompiler { }; if export { - self.module.export_star.properties.push(( + self.module.export_star.local.properties.push(( Value::String(ts_enum.id.sym.to_string()), Value::Pointer(pointer.clone()), )); @@ -503,6 +503,7 @@ impl ModuleCompiler { self .module .export_star + .local .properties .push((Value::String(export_name), Value::Pointer(defn))); } @@ -549,6 +550,7 @@ impl ModuleCompiler { self .module .export_star + .local .properties .push((Value::String(namespace_name), Value::Pointer(defn))); } @@ -714,7 +716,7 @@ impl ModuleCompiler { }; if let Some(export_name) = export_name { - self.module.export_star.properties.push(( + self.module.export_star.local.properties.push(( Value::String(export_name), Value::Pointer(defn_name.clone()), )); diff --git a/valuescript_compiler/src/visit_pointers.rs b/valuescript_compiler/src/visit_pointers.rs index da23e53..7296daa 100644 --- a/valuescript_compiler/src/visit_pointers.rs +++ b/valuescript_compiler/src/visit_pointers.rs @@ -1,5 +1,6 @@ use crate::asm::{ - Array, Definition, DefinitionContent, FnLine, Instruction, Module, Object, Pointer, Value, + Array, Definition, DefinitionContent, ExportStar, FnLine, Instruction, Module, Object, Pointer, + Value, }; pub fn visit_pointers(module: &mut Module, visitor: Visitor) @@ -34,7 +35,7 @@ where pub fn module(&mut self, module: &mut Module) { self.value(None, &mut module.export_default); - self.object(None, &mut module.export_star); + self.export_star(None, &mut module.export_star); for definition in &mut module.definitions { self.definition(definition); @@ -70,6 +71,14 @@ where } } + fn export_star(&mut self, owner: Option<&Pointer>, export_star: &mut ExportStar) { + for p in &mut export_star.includes { + self.pointer(owner, p); + } + + self.object(owner, &mut export_star.local); + } + fn value(&mut self, owner: Option<&Pointer>, value: &mut Value) { use Value::*; @@ -88,14 +97,18 @@ where self.value(owner, &mut class.static_); } Pointer(pointer) => { - (self.visitor)(match owner { - Some(owner) => PointerVisitation::Reference(owner, pointer), - None => PointerVisitation::Export(pointer), - }); + self.pointer(owner, pointer); } } } + fn pointer(&mut self, owner: Option<&Pointer>, pointer: &mut Pointer) { + (self.visitor)(match owner { + Some(owner) => PointerVisitation::Reference(owner, pointer), + None => PointerVisitation::Export(pointer), + }); + } + fn instruction(&mut self, owner: &Pointer, instruction: &mut Instruction) { use Instruction::*;