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