This commit is contained in:
Anton Danilkin
2018-08-13 18:59:52 +03:00
62 changed files with 1537 additions and 168 deletions

View File

@ -19,6 +19,8 @@ pub struct Program {
pub structs: Vec<Struct>,
/// rust consts
pub consts: Vec<Const>,
/// rust submodules
pub modules: Vec<Module>,
}
/// A rust to js interface. Allows interaction with rust objects/functions
@ -239,6 +241,18 @@ pub enum ConstValue {
Null,
}
/// A rust module
///
/// This exists to give the ability to namespace js imports.
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
#[derive(Clone)]
pub struct Module {
pub vis: syn::Visibility,
pub name: Ident,
/// js -> rust interfaces
pub imports: Vec<Import>,
}
impl Program {
pub(crate) fn shared(&self) -> Result<shared::Program, Diagnostic> {
Ok(shared::Program {
@ -246,6 +260,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::<Result<_, Diagnostic>>()?,
version: shared::version(),
@ -365,7 +381,9 @@ impl ImportFunction {
/// for a setter in javascript (in this case `xxx`, so you can write `obj.xxx = val`)
fn infer_setter_property(&self) -> String {
let name = self.function.name.to_string();
assert!(name.starts_with("set_"), "setters must start with `set_`");
if !name.starts_with("set_") {
panic!("error: setters must start with `set_`, found: {}", name);
}
name[4..].to_string()
}

View File

@ -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() {
@ -67,6 +69,11 @@ impl TryToTokens for ast::Program {
for c in self.consts.iter() {
c.to_tokens(tokens);
}
for m in self.modules.iter() {
if let Err(e) = m.try_to_tokens(tokens) {
errors.push(e);
}
}
Diagnostic::from_vec(errors)?;
@ -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,30 @@ impl ToTokens for ast::Const {
}
}
impl<'a> TryToTokens for ast::Module {
fn try_to_tokens(&self, tokens: &mut TokenStream) -> Result<(), Diagnostic> {
for import in &self.imports {
DescribeImport(&import.kind).to_tokens(tokens);
}
let vis = &self.vis;
let name = &self.name;
let mut errors = Vec::new();
let mut body = TokenStream::new();
for import in &self.imports {
if let Err(e) = import.kind.try_to_tokens(&mut body) {
errors.push(e);
}
}
Diagnostic::from_vec(errors)?;
(quote!{
#vis 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);