1#![forbid(unsafe_code)]
14#![allow(deprecated)]
15#![deny(missing_docs)]
16
17mod attrs;
18mod function_expand;
19mod macro_expand;
20mod module_expand;
21mod native_class_expand;
22mod native_macro_expand;
23mod native_number_expand;
24mod parse;
25mod shape;
26
27use attrs::{bool_attr, camel_case, string_attr};
28use parse::ParsedModule;
29use proc_macro::TokenStream;
30use proc_macro2::Span;
31use quote::{format_ident, quote};
32use syn::{ItemMod, LitStr, Token, parse_macro_input, punctuated::Punctuated};
33
34#[proc_macro_attribute]
43pub fn sim_lib(attr: TokenStream, item: TokenStream) -> TokenStream {
44 let attr =
45 parse_macro_input!(attr with Punctuated::<syn::MetaNameValue, Token![,]>::parse_terminated);
46 let mut module = parse_macro_input!(item as ItemMod);
47
48 let lib_id = match string_attr(&attr, "id") {
49 Ok(value) => value,
50 Err(err) => return err,
51 };
52 let version = match string_attr(&attr, "version") {
53 Ok(value) => value,
54 Err(err) => return err,
55 };
56 let native_export = match bool_attr(&attr, "native_export") {
57 Ok(value) => value,
58 Err(err) => return err,
59 };
60
61 let Some((_, items)) = &mut module.content else {
62 return syn::Error::new_spanned(&module, "#[sim_lib] requires an inline module")
63 .to_compile_error()
64 .into();
65 };
66
67 let parsed = match ParsedModule::parse(items) {
68 Ok(parsed) => parsed,
69 Err(err) => return err.to_compile_error().into(),
70 };
71
72 let lib_ident = format_ident!("{}Lib", camel_case(&module.ident.to_string()));
73 let generated = match parsed.expand(&module.vis, &lib_ident, &lib_id, &version, native_export) {
74 Ok(generated) => generated,
75 Err(err) => return err.to_compile_error().into(),
76 };
77 let expansion_text = generated.to_string();
78 let expansion_text = LitStr::new(&expansion_text, Span::call_site());
79
80 *items = parsed.cleaned_items;
81 items.push(syn::parse_quote! {
82 pub const __SIM_LIB_EXPANSION: &str = #expansion_text;
83 });
84 items.extend(
85 syn::parse2::<syn::File>(generated)
86 .expect("generated sim_lib items should parse")
87 .items,
88 );
89
90 quote!(#module).into()
91}
92
93#[proc_macro_attribute]
96pub fn sim_class(_attr: TokenStream, item: TokenStream) -> TokenStream {
97 item
98}
99
100#[proc_macro_attribute]
103pub fn sim_constructor(_attr: TokenStream, item: TokenStream) -> TokenStream {
104 item
105}
106
107#[proc_macro_attribute]
110pub fn sim_fn(_attr: TokenStream, item: TokenStream) -> TokenStream {
111 item
112}
113
114#[proc_macro_attribute]
118pub fn sim_macro(_attr: TokenStream, item: TokenStream) -> TokenStream {
119 item
120}
121
122#[proc_macro_attribute]
126pub fn sim_codec(_attr: TokenStream, item: TokenStream) -> TokenStream {
127 item
128}
129
130#[proc_macro_attribute]
134pub fn sim_number_domain(_attr: TokenStream, item: TokenStream) -> TokenStream {
135 item
136}
137
138#[proc_macro_attribute]
142pub fn sim_site(_attr: TokenStream, item: TokenStream) -> TokenStream {
143 item
144}
145
146#[proc_macro_attribute]
149pub fn case(_attr: TokenStream, item: TokenStream) -> TokenStream {
150 item
151}
152
153#[proc_macro_attribute]
156pub fn shape(_attr: TokenStream, item: TokenStream) -> TokenStream {
157 item
158}
159
160#[cfg(test)]
161mod tests;