extern crate proc_macro;
use TokenStream;
use quote;
/// Marks the main function to be executed by the lunatic runtime as the root
/// process.
///
/// Note: The macro can only be used on `main` function with 1 argument of type
/// `Mailbox<T>`.
///
/// # Example
/// ```ignore
/// #[lunatic::main]
/// fn main(_: Mailbox<()>) {
/// println!("Hello, world!");
/// }
/// ```
/// Add [`AbstractProcess`] behavior to the given struct implementation with
/// minimum boilerplate code.
///
/// - Use `#[init]`, `#[terminate]`, and `#[handle_link_trapped]` attributes to
/// specify methods for implementing [`AbstractProcess`].
/// - Use `#[handle_message]` and `#[handle_request]` attributes to specify
/// message and request handlers.
///
/// Specifying message types is unnecessary because the macro will create
/// wrapper types for messages on all handlers. Handlers can take an arbitrary
/// number of parameters and invoking them works the same as directly calling
/// the method on the struct without spawning it as a process.
///
/// A trait is generated and defaults to private and follows the name of your
/// type with `Handler` added as a suffix. To rename or change the visibility of
/// the generated trait, you can use the `trait_name` and `visbility` arguments
/// with `#[abstract_process(trait_name = "MyHandler", visibility = pub)]`.
///
/// # Examples
///
/// ```ignore
/// use lunatic::{
/// abstract_process,
/// process::{Message, ProcessRef, Request, StartProcess},
/// Tag,
/// };
///
/// struct Counter(u32);
///
/// #[abstract_process]
/// impl Counter {
/// #[init]
/// fn init(_: ProcessRef<Self>, start: u32) -> Self {
/// Self(start)
/// }
///
/// #[terminate]
/// fn terminate(self) {
/// println!("Shutdown process");
/// }
///
/// #[handle_link_trapped]
/// fn handle_link_trapped(&self, tag: Tag) {
/// println!("Link trapped");
/// }
///
/// #[handle_message]
/// fn increment(&mut self) {
/// self.0 += 1;
/// }
///
/// #[handle_request]
/// fn count(&self) -> u32 {
/// self.0
/// }
/// }
///
///
/// let counter = Counter::start(5, None);
/// counter.increment();
/// assert_eq!(counter.count(), 6);
/// ```
///
/// A more complicated example
///
/// ```ignore
/// use lunatic::{
/// abstract_process,
/// process::{Message, ProcessRef, Request, StartProcess},
/// }
///
/// struct A;
///
/// #[derive(serde::Serialize, serde::Deserialize)]
/// struct Person {
/// name: String,
/// age: u16,
/// }
///
/// #[abstract_process(trait_name = "AHandler", visibility = pub)]
/// impl A {
/// #[init]
/// fn init(_: ProcessRef<Self>, _: ()) -> A {
/// A
/// }
///
/// #[hanlde_message]
/// fn multiple_arguments(&self, a: u8, (b, c): (bool, char)) {
/// assert_eq!(a, 5);
/// assert_eq!(b, false);
/// assert_eq!(c, 'a');
/// }
///
/// #[handle_request]
/// fn unpack_struct(&self, Person { name, age }: Person) -> String {
/// assert_eq!(name, "Mark");
/// assert_eq!(age, 5);
/// self.create_greeting(name)
/// }
///
/// fn create_greeting(&self, name: String) {
/// format!("Hi {}!", name)
/// }
/// }
///
///
/// let a = A::start_link((), None);
///
/// a.multiple_arguments(5, (false, 'a'));
///
/// let person = Person {
/// name: "Mark".to_owned(),
/// age: 4,
/// };
///
/// let greeting = a.unpack_struct(person);
/// assert_eq!(greeting, "Hi Mark!");
/// ```
///
/// [`AbstractProcess`]: process/trait.AbstractProcess.html