From 1e02ca7eab7a26ce15d578c3ae7f28b291790c60 Mon Sep 17 00:00:00 2001 From: Richard Dodd Date: Thu, 9 Aug 2018 18:07:41 +0100 Subject: [PATCH] Add support for modules to the backend. --- crates/backend/src/ast.rs | 15 +++++++++++++++ crates/backend/src/codegen.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index 57869a89..08c64975 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -19,6 +19,19 @@ pub struct Program { pub structs: Vec, /// rust consts pub consts: Vec, + /// rust submodules + pub modules: Vec, +} + +/// A rust module +/// +/// This exists to give the ability to namespace js imports. +#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] +pub struct Module { + /// module name + pub name: String, + /// js -> rust interfaces + pub imports: Vec, } /// A rust to js interface. Allows interaction with rust objects/functions @@ -227,6 +240,8 @@ impl Program { structs: self.structs.iter().map(|a| a.shared()).collect(), enums: self.enums.iter().map(|a| a.shared()).collect(), imports: self.imports.iter() + // add in imports from inside modules + .chain(self.modules.iter().flat_map(|m| m.imports.iter())) .map(|a| a.shared()) .collect::>()?, version: shared::version(), diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index a40cbf3a..5274a0ce 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -43,6 +43,8 @@ impl TryToTokens for ast::Program { for i in self.imports.iter() { DescribeImport(&i.kind).to_tokens(tokens); + // If there is a js namespace, check that name isn't a type. If it is, + // this import might be a method on that type. if let Some(ns) = &i.js_namespace { if types.contains(ns) && i.kind.fits_on_impl() { let kind = match i.kind.try_to_token_stream() { @@ -61,6 +63,11 @@ impl TryToTokens for ast::Program { errors.push(e); } } + for m in self.modules.iter() { + if let Err(e) = m.try_to_tokens(tokens) { + errors.push(e); + } + } for e in self.enums.iter() { e.to_tokens(tokens); } @@ -87,6 +94,7 @@ impl TryToTokens for ast::Program { // Each JSON blob is prepended with the length of the JSON blob so when // all these sections are concatenated in the final wasm file we know // how to extract all the JSON pieces, so insert the byte length here. + // The value is little-endian. let generated_static_length = description.len() + 4; let mut bytes = vec![ (description.len() >> 0) as u8, @@ -1103,6 +1111,29 @@ impl ToTokens for ast::Const { } } +impl TryToTokens for ast::Module { + fn try_to_tokens(&self, tokens: &mut TokenStream) -> Result<(), Diagnostic> { + let mut errors = Vec::new(); + for i in self.imports.iter() { + DescribeImport(&i.kind).to_tokens(tokens); + } + let name = &self.name; + let mut body = TokenStream::new(); + for i in self.imports.iter() { + if let Err(e) = i.kind.try_to_tokens(&mut body) { + errors.push(e); + } + } + Diagnostic::from_vec(errors)?; + (quote!{ + pub mod #name { + #body + } + }).to_tokens(tokens); + Ok(()) + } +} + /// Emits the necessary glue tokens for "descriptor", generating an appropriate /// symbol name as well as attributes around the descriptor function itself. struct Descriptor<'a, T>(&'a Ident, T);