use agent::AgentArgs;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Item, ItemMod};
mod action;
mod agent;
mod contract;
mod schedule;
mod state;
mod utils;
#[proc_macro_attribute]
pub fn contract(_attrs: TokenStream, input: TokenStream) -> TokenStream {
let module = parse_macro_input!(input as ItemMod);
if module.content.is_none() {
return syn::Error::new_spanned(
module,
"Macro can only be implemented on modules that have some content",
)
.to_compile_error()
.into();
}
let (brace, mut items) = module.content.unwrap();
let new_tokens = match contract::parse_module_content(brace.span.join(), &items, &module.ident)
{
Ok(tokens) => tokens,
Err(e) => return e.to_compile_error().into(),
};
items.push(Item::Verbatim(new_tokens));
match module.vis {
syn::Visibility::Public(_) => (),
_ => {
let tokens =
syn::Error::new_spanned(module.mod_token, "Contract module must be public")
.to_compile_error();
items.push(Item::Verbatim(tokens));
}
}
let wasm_exports = contract::generate_wasm_exports(&module.ident);
let new_module = ItemMod {
attrs: module.attrs,
vis: module.vis,
unsafety: module.unsafety,
mod_token: module.mod_token,
ident: module.ident,
content: Some((brace, items)),
semi: module.semi,
};
quote! {
#new_module
#wasm_exports
}
.into()
}
#[proc_macro_attribute]
pub fn agent(attrs: TokenStream, input: TokenStream) -> TokenStream {
let module = parse_macro_input!(input as ItemMod);
let parsed_attrs = syn::parse_macro_input!(attrs as AgentArgs);
if module.content.is_none() {
return syn::Error::new_spanned(
module,
"Macro can only be implemented on modules that have some content",
)
.to_compile_error()
.into();
}
let (brace, mut items) = module.content.unwrap();
let use_ws = parsed_attrs.websocket.unwrap_or_default();
let new_tokens = match agent::parse_module_content(brace.span.join(), &items, use_ws) {
Ok(tokens) => tokens,
Err(e) => return e.to_compile_error().into(),
};
items.push(Item::Verbatim(new_tokens));
match module.vis {
syn::Visibility::Public(_) => (),
_ => {
let tokens = syn::Error::new_spanned(module.mod_token, "Agent module must be public")
.to_compile_error();
items.push(Item::Verbatim(tokens));
}
}
let wasm_exports = agent::generate_wasm_exports(&module.ident);
let wasm_ws_exports = if use_ws {
agent::generate_ws_wasm_exports(&module.ident)
} else {
quote! {}
};
let new_module = ItemMod {
attrs: module.attrs,
vis: module.vis,
unsafety: module.unsafety,
mod_token: module.mod_token,
ident: module.ident,
content: Some((brace, items)),
semi: module.semi,
};
quote! {
#new_module
#wasm_exports
#wasm_ws_exports
}
.into()
}
#[proc_macro_derive(State)]
pub fn derive_contract_state(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input);
let output = state::impl_state(input);
match output {
syn::Result::Ok(token_stream) => token_stream,
syn::Result::Err(err) => err.to_compile_error(),
}
.into()
}
#[proc_macro_attribute]
pub fn action(_attrs: TokenStream, input: TokenStream) -> TokenStream {
input
}
#[proc_macro_attribute]
pub fn schedule(_attrs: TokenStream, input: TokenStream) -> TokenStream {
input
}