use arcis_interpreter::{arcis_type_macro, error_macro, library_macro, module_macro};
use proc_macro::TokenStream;

/// Tells our arcis compiler to create encrypted instructions that mimic the rust module you wrote.
/// Use `#[instruction]` to mark the functions that will be the entry points.
#[proc_macro_attribute]
pub fn encrypted(_attr: TokenStream, item: TokenStream) -> TokenStream {
    module_macro(item.into()).into()
}

/// Validates an arcis library, trying to find errors.
/// Allows to build a library that can be used in `#[encrypted]` instructions.
///
/// Will transform
/// ```
/// mod arcis_library {
///     /* content */
/// }
/// ```
/// into
/// ```
/// /* content */
/// ```
/// if it does not detect any errors.
#[proc_macro_attribute]
pub fn encrypted_library(_attr: TokenStream, item: TokenStream) -> TokenStream {
    library_macro(item.into()).into()
}

/// Derives `ArcisType`, a trait that helps to use the type in automated tests.
#[doc(hidden)]
#[proc_macro_derive(ArcisType)]
pub fn derive_arcis_type(input: TokenStream) -> TokenStream {
    arcis_type_macro(input.into()).into()
}

/// An `#[instruction]`. Should be inside an `#[encrypted]` module.
#[proc_macro_attribute]
pub fn instruction(_attr: TokenStream, item: TokenStream) -> TokenStream {
    error_macro(
        item.into(),
        "`#[instruction]` can only be used inside `#[encrypted]`.",
    )
    .into()
}
#[doc(hidden)]
#[proc_macro_attribute]
pub fn arcis_circuit(_attr: TokenStream, item: TokenStream) -> TokenStream {
    error_macro(
        item.into(),
        "`#[arcis_circuit = \"...\"]` can only be used inside `#[encrypted]`.",
    )
    .into()
}
