rhythmc_macros/
lib.rs

1#![feature(
2  custom_inner_attributes,
3  proc_macro_span,
4  proc_macro_diagnostic,
5  proc_macro_def_site
6)]
7use rhythmc_compiler::utils::syn::resolve_module_path;
8
9#[macro_use]
10extern crate lazy_static;
11
12use glsl::syntax::TranslationUnit;
13use proc_macro::{Delimiter, Span, TokenStream, TokenTree};
14
15use std::collections::HashMap;
16use std::str::FromStr;
17
18lazy_static! {
19  /// Stores a map of already compiled module names to their respective GLSL IR.
20  /// This is used to look up compiled translation unit that are being imported.
21  static ref IR_MAP: HashMap<String, TranslationUnit> = HashMap::new();
22}
23
24fn compile_error(message: &str) -> TokenStream {
25  TokenStream::from_str(message).unwrap()
26}
27
28#[proc_macro_attribute]
29pub fn shader(_attr: TokenStream, item: TokenStream) -> TokenStream {
30  let module_path = if let Some(path) = resolve_module_path(
31    Span::call_site().into(),
32    Span::call_site().source_file().path(),
33  ) {
34    path
35  } else {
36    return compile_error("rhythmc failed to resolve this module path");
37  };
38
39  let mut result = Vec::new();
40  let mut iter = item.into_iter();
41  loop {
42    let token = iter.next();
43    if token.is_none() {
44      return compile_error(
45        "invalid usage of 'rhythmc::shader', expected module",
46      );
47    }
48    result.push(TokenStream::from(token.clone().unwrap()));
49    if let TokenTree::Group(group) = token.clone().unwrap() {
50      if group.delimiter() == Delimiter::Brace {
51        return compile_error(
52          "invalid usage of 'rhythmc::shader', expected module",
53        );
54      }
55    }
56    if token.unwrap().to_string() == "mod" {
57      break;
58    }
59  }
60  result.push(TokenStream::from(iter.next().unwrap()));
61  if let TokenTree::Group(group) = iter.next().unwrap() {
62    assert_eq!(group.delimiter(), Delimiter::Brace);
63    result.push(
64      TokenStream::from_str(
65        format!(
66          "{{ 
67        pub static RHYTHMC_SHADER_MODULE_NAME: &str = \"{}\";
68        pub static RHYTHMC_SHADER_MODULE_IMPORTS: Vec<String> = vec![];
69        {}
70      }}",
71          module_path,
72          group.stream()
73        )
74        .as_str(),
75      )
76      .unwrap(),
77    );
78  } else {
79    return compile_error(
80      "invalid usage of 'rhythmc::shader', failed to parse",
81    );
82  }
83  assert!(iter.next().is_none());
84  let result = result.iter().cloned().collect();
85  result
86}
87
88#[proc_macro_attribute]
89pub fn import(_attr: TokenStream, item: TokenStream) -> TokenStream {
90  // Find RHYTHM_SHADER_MODULE_IMPORTS and add an entry for an external source
91  item
92}
93
94// #[proc_macro_derive]
95// pub fn rhythmc_struct