diff options
author | Griffin Smith <root@gws.fyi> | 2022-11-06T15·28-0500 |
---|---|---|
committer | grfn <grfn@gws.fyi> | 2022-11-08T13·42+0000 |
commit | a1015ba1d7c2228224847f1931118da473815de3 (patch) | |
tree | 2cf2d28f841c3a40ac8f95a5c5e4a3a6797d648f /tvix/eval/builtin-macros/src | |
parent | dad07a8bc0369932a7b65efc2dd4181a8863eb5b (diff) |
feat(tvix/eval): Give names to builtin arguments r/5268
Refactor the arguments of a Builtin to be a vec of a new BuiltinArgument struct, which contains the old strictness boolean and also a static `name` str - this is automatically determined via the ident for the corresponding function argument in the proc-macro case, and passed in in the cases where we're still manually calling Builtin::new. Currently this name is unused, but in the future this can be used as part of a documentation system for builtins. Change-Id: Ib9dadb15b69bf8c9ea1983a4f4f197294a2394a6 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7204 Reviewed-by: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval/builtin-macros/src')
-rw-r--r-- | tvix/eval/builtin-macros/src/lib.rs | 65 |
1 files changed, 45 insertions, 20 deletions
diff --git a/tvix/eval/builtin-macros/src/lib.rs b/tvix/eval/builtin-macros/src/lib.rs index 8e2c4b3f8776..8276e421c5d8 100644 --- a/tvix/eval/builtin-macros/src/lib.rs +++ b/tvix/eval/builtin-macros/src/lib.rs @@ -5,7 +5,9 @@ use proc_macro2::Span; use quote::{quote_spanned, ToTokens}; use syn::parse::Parse; use syn::spanned::Spanned; -use syn::{parse_macro_input, parse_quote, FnArg, Ident, Item, ItemMod, LitStr, PatType}; +use syn::{ + parse_macro_input, parse_quote, FnArg, Ident, Item, ItemMod, LitStr, Pat, PatIdent, PatType, +}; struct BuiltinArgs { name: LitStr, @@ -89,31 +91,54 @@ pub fn builtins(_args: TokenStream, item: TokenStream) -> TokenStream { .into(); } - let strictness = f + let builtin_arguments = f .sig .inputs .iter_mut() .skip(1) - .map(|input| { - let mut lazy = false; - if let FnArg::Typed(PatType { attrs, .. }) = input { - attrs.retain(|attr| { - attr.path.get_ident().into_iter().any(|id| { - if id == "lazy" { - lazy = true; - false - } else { - true - } - }) - }); - } - !lazy + .map(|arg| { + let mut strict = true; + let name = match arg { + FnArg::Receiver(_) => { + return Err(quote_spanned!(arg.span() => { + compile_error!("Unexpected receiver argument in builtin") + })) + } + FnArg::Typed(PatType { attrs, pat, .. }) => { + attrs.retain(|attr| { + attr.path.get_ident().into_iter().any(|id| { + if id == "lazy" { + strict = false; + false + } else { + true + } + }) + }); + match pat.as_ref() { + Pat::Ident(PatIdent { ident, .. }) => ident.to_string(), + _ => "unknown".to_string(), + } + } + }; + + Ok(quote_spanned!(arg.span() => { + crate::internal::BuiltinArgument { + strict: #strict, + name: #name, + } + })) }) - .collect::<Vec<_>>(); + .collect::<Result<Vec<_>, _>>(); + + let builtin_arguments = match builtin_arguments { + Ok(args) => args, + Err(err) => return err.into(), + }; let fn_name = f.sig.ident.clone(); - let args = (0..(f.sig.inputs.len() - 1)) + let num_args = f.sig.inputs.len() - 1; + let args = (0..num_args) .map(|n| Ident::new(&format!("arg_{n}"), Span::call_site())) .collect::<Vec<_>>(); let mut reversed_args = args.clone(); @@ -122,7 +147,7 @@ pub fn builtins(_args: TokenStream, item: TokenStream) -> TokenStream { builtins.push(quote_spanned! { builtin_attr.span() => { crate::internal::Builtin::new( #name, - &[#(#strictness),*], + &[#(#builtin_arguments),*], |mut args: Vec<crate::Value>, vm: &mut crate::internal::VM| { #(let #reversed_args = args.pop().unwrap();)* #fn_name(vm, #(#args),*) |