refactor(tvix/eval): Generalize propagation of catchable values
Rather than explicitly checking for Value::Catchable in all builtins, make the #[builtin] proc macro insert this for all strict arguments by default, with support for a #[catch] attribute on the argument to disable this behavior. That attribute hasn't actually been *used* anywhere here, primarily because the tests pass without it, even for those builtins which weren't previously checking for Value::Catchable - if some time passes without this being used I might get rid of support for it entirely. There's also a `try_value` macro in builtins directly for the places where builtins were eg forcing something, then explicitly propagating a catchable value. Change-Id: Ie22037b9d3e305e3bdb682d105fe467bd90d53e9 Reviewed-on: https://cl.tvl.fyi/c/depot/+/10732 Tested-by: BuildkiteCI Reviewed-by: raitobezarius <tvl@lahfa.xyz>
This commit is contained in:
parent
4e040e8bc4
commit
780b47193a
2 changed files with 44 additions and 183 deletions
|
|
@ -22,6 +22,10 @@ struct BuiltinArgument {
|
|||
/// function is called.
|
||||
strict: bool,
|
||||
|
||||
/// Propagate catchable values as values to the function, rather than short-circuit returning
|
||||
/// them if encountered
|
||||
catch: bool,
|
||||
|
||||
/// Span at which the argument was defined.
|
||||
span: Span,
|
||||
}
|
||||
|
|
@ -205,6 +209,7 @@ pub fn builtins(args: TokenStream, item: TokenStream) -> TokenStream {
|
|||
.map(|arg| {
|
||||
let span = arg.span();
|
||||
let mut strict = true;
|
||||
let mut catch = false;
|
||||
let (name, ty) = match arg {
|
||||
FnArg::Receiver(_) => {
|
||||
return Err(quote_spanned!(span => {
|
||||
|
|
@ -219,6 +224,9 @@ pub fn builtins(args: TokenStream, item: TokenStream) -> TokenStream {
|
|||
if id == "lazy" {
|
||||
strict = false;
|
||||
false
|
||||
} else if id == "catch" {
|
||||
catch = true;
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
|
@ -233,8 +241,15 @@ pub fn builtins(args: TokenStream, item: TokenStream) -> TokenStream {
|
|||
}
|
||||
};
|
||||
|
||||
if catch && !strict {
|
||||
return Err(quote_spanned!(span => {
|
||||
compile_error!("Cannot mix both lazy and catch on the same argument")
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(BuiltinArgument {
|
||||
strict,
|
||||
catch,
|
||||
span,
|
||||
name,
|
||||
ty,
|
||||
|
|
@ -267,12 +282,22 @@ pub fn builtins(args: TokenStream, item: TokenStream) -> TokenStream {
|
|||
let ident = &arg.name;
|
||||
|
||||
if arg.strict {
|
||||
f.block = Box::new(parse_quote_spanned! {arg.span=> {
|
||||
let #ident: #ty = tvix_eval::generators::request_force(&co, values.pop()
|
||||
.expect("Tvix bug: builtin called with incorrect number of arguments")).await;
|
||||
|
||||
#block
|
||||
}});
|
||||
if arg.catch {
|
||||
f.block = Box::new(parse_quote_spanned! {arg.span=> {
|
||||
let #ident: #ty = tvix_eval::generators::request_force(&co, values.pop()
|
||||
.expect("Tvix bug: builtin called with incorrect number of arguments")).await;
|
||||
#block
|
||||
}});
|
||||
} else {
|
||||
f.block = Box::new(parse_quote_spanned! {arg.span=> {
|
||||
let #ident: #ty = tvix_eval::generators::request_force(&co, values.pop()
|
||||
.expect("Tvix bug: builtin called with incorrect number of arguments")).await;
|
||||
if #ident.is_catchable() {
|
||||
return Ok(#ident);
|
||||
}
|
||||
#block
|
||||
}});
|
||||
}
|
||||
} else {
|
||||
f.block = Box::new(parse_quote_spanned! {arg.span=> {
|
||||
let #ident: #ty = values.pop()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue