feat(tvix/eval): Give names to builtin arguments
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
This commit is contained in:
parent
dad07a8bc0
commit
a1015ba1d7
6 changed files with 109 additions and 55 deletions
|
@ -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),*)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue