git.delta.rocks / jrsonnet / refs/commits / a5471f26b10f

difftreelog

source

crates/jrsonnet-macros/src/lib.rs2.0 KiBsourcehistory
1use proc_macro2::Span;2use quote::quote;3use syn::{parse_macro_input, FnArg, Ident, ItemFn, Pat};45#[proc_macro_attribute]6pub fn builtin(7	_attr: proc_macro::TokenStream,8	item: proc_macro::TokenStream,9) -> proc_macro::TokenStream {10	// syn::ItemFn::parse(input)11	let fun: ItemFn = parse_macro_input!(item);1213	let inner_name = Ident::new("inner", Span::call_site());14	let mut inner_fun = fun.clone();15	inner_fun.sig.ident = inner_name.clone();16	let result = match fun.sig.output {17		syn::ReturnType::Default => panic!("builtin should return something"),18		syn::ReturnType::Type(_, ty) => ty,19	};2021	let params = fun22		.sig23		.inputs24		.iter()25		.map(|i| match i {26			FnArg::Receiver(_) => unreachable!(),27			FnArg::Typed(t) => t,28		})29		.map(|t| {30			let ident = match &t.pat as &Pat {31				Pat::Ident(i) => i.ident.to_string(),32				_ => panic!("only idents supported yet"),33			};34			// TODO: Check if ty == Option<_>35			let optional = false;36			quote! {37				BuiltinParam {38					name: #ident,39					has_default: #optional,40				}41			}42		});4344	let args = fun45		.sig46		.inputs47		.iter()48		.map(|i| match i {49			FnArg::Receiver(_) => unreachable!(),50			FnArg::Typed(t) => t,51		})52		.map(|t| {53			let ident = match &t.pat as &Pat {54				Pat::Ident(i) => i.ident.to_string(),55				_ => panic!("only idents supported yet"),56			};57			let ty = &t.ty;58			quote! {{59				let value = parsed.get(#ident).unwrap();6061				jrsonnet_evaluator::push_description_frame(62					|| format!("argument <{}> evaluation", #ident),63					|| <#ty>::try_from(value.evaluate()?),64				)?65			}}66		});6768	let attrs = &fun.attrs;69	let vis = &fun.vis;70	let name = &fun.sig.ident;71	(quote! {72		#(#attrs)*73		#vis fn #name(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {74			#inner_fun75			use jrsonnet_evaluator::function::BuiltinParam;76			const PARAMS: &'static [BuiltinParam] = &[77				#(#params),*78			];79			let parsed = jrsonnet_evaluator::function::parse_builtin_call(context, &PARAMS, args, false)?;8081			let result: #result = #inner_name(#(#args),*);82			let result = result?;83			result.try_into()84		}85	})86	.into()87}