use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};
use crate::common::{
build_generic_args, extract_f_and_ctx_types, handler_name_from_fn, returns_result_type,
};
pub fn nontco_impl(item: TokenStream) -> TokenStream {
let input_fn = parse_macro_input!(item as ItemFn);
let fn_name = &input_fn.sig.ident;
let generics = &input_fn.sig.generics;
let where_clause = &generics.where_clause;
let returns_result = returns_result_type(&input_fn);
let (f_type, ctx_type) = extract_f_and_ctx_types(generics);
let handler_name = handler_name_from_fn(fn_name);
let generic_args = build_generic_args(generics);
let execute_call = if generic_args.is_empty() {
quote! { #fn_name(pre_compute, exec_state) }
} else {
quote! { #fn_name::<#(#generic_args),*>(pre_compute, exec_state) }
};
let handler_body = if returns_result {
quote! {
let __ret = { #execute_call };
if let ::core::result::Result::Err(e) = __ret {
exec_state.exit_code = ::core::result::Result::Err(e);
return;
}
}
} else {
quote! {
#execute_call;
}
};
let handler_fn = quote! {
#[inline(always)]
unsafe fn #handler_name #generics (
pre_compute: *const u8,
exec_state: &mut ::openvm_circuit::arch::VmExecState<
#f_type,
::openvm_circuit::system::memory::online::GuestMemory,
#ctx_type,
>,
)
#where_clause
{
#handler_body
}
};
let output = quote! {
#input_fn
#handler_fn
};
TokenStream::from(output)
}