@@ -316,7 +316,7 @@ pub fn get_capability(issuer: &Address, params: &str) -> Option<Capability> {
316316/// fn init(our: Address) {
317317/// let parent = our.clone();
318318/// Spawn!(|parent: Address| {
319- /// println!("hello from {our}. I am Spawn of {}!", args["our"] );
319+ /// println!("hello from {our}. I am Spawn of {parent }!");
320320/// });
321321/// ...
322322/// }
@@ -329,19 +329,93 @@ pub fn get_capability(issuer: &Address, params: &str) -> Option<Capability> {
329329/// 3. Update the relevant metadata for the package
330330/// (i.e. `Cargo.toml`, `metadata.json`, etc.).
331331///
332+ /// More example usage:
332333///
334+ /// Can pass function call rather than closure:
333335/// ```no_run
334336/// fn init(our: Address) {
335337/// let parent = our.clone();
336338/// Spawn!(my_function(parent));
337339/// ...
338340/// }
339341/// ```
342+ /// Nested function calls work as expected.
343+ ///
344+ /// Can optionally supply subset of [`spawn()`] arguments, namely
345+ /// * name: &str,
346+ /// * on_exit: [`OnExit`],
347+ /// * request_capabilities: Vec<[`Capability`]>,
348+ /// * grant_capabilities: Vec<[`ProcessId`]>,
349+ /// * public: bool,
350+ /// for example:
351+ /// ```no_run
352+ /// fn init(our: Address) {
353+ /// let parent = our.clone();
354+ /// Spawn!(my_function(parent), name: "hello-world", public: true);
355+ /// ...
356+ /// }
357+ /// ```
340358#[ macro_export]
341359macro_rules! Spawn {
342- // Pattern 1: Match closure with type-annotated parameters
360+ // Pattern 1: Closure with type-annotated paramters & with no options
343361 ( |$( $param: ident : $type: ty) ,+ $( , ) ?| $body: block) => { } ;
344362
345- // Pattern 2: Match function call
363+ // Pattern 2: Function call with no options
346364 ( $fn_name: ident( $( $arg: expr) ,* $( , ) ?) ) => { } ;
365+
366+ // Pattern 3: Closure with type-annotated paramters & with options
367+ (
368+ |$( $param: ident : $type: ty) ,+ $( , ) ?| $body: block,
369+ $(
370+ $key: ident : $value: expr
371+ $( , ) ?
372+ ) *
373+ ) => { {
374+ // Validate each key at compile time using nested macro
375+ validate_spawn_args!( $( $key) ,* ) ;
376+
377+ // Your implementation here
378+ } } ;
379+
380+ // Pattern 4: Function call with options
381+ (
382+ $fn_name: ident( $( $arg: expr) ,* $( , ) ?) ,
383+ $(
384+ $key: ident : $value: expr
385+ $( , ) ?
386+ ) *
387+ ) => { {
388+ // Validate each key at compile time using nested macro
389+ validate_spawn_args!( $( $key) ,* ) ;
390+
391+ // Your implementation here
392+ } } ;
393+ }
394+
395+ #[ macro_export]
396+ macro_rules! validate_spawn_args {
397+ // Empty case - no args to validate
398+ ( ) => { } ;
399+
400+ // Validate single argument
401+ ( name) => { } ;
402+ ( on_exit) => { } ;
403+ ( request_capabilities) => { } ;
404+ ( grant_capabilities) => { } ;
405+ ( public) => { } ;
406+
407+ // Recursively validate multiple arguments
408+ ( $first: ident, $( $rest: ident) ,+ $( , ) ?) => {
409+ validate_spawn_args!( $first) ;
410+ validate_spawn_args!( $( $rest) ,+) ;
411+ } ;
412+
413+ // Error case - invalid argument name
414+ ( $invalid: ident $( , $( $rest: tt) * ) ?) => {
415+ compile_error!( concat!(
416+ "Invalid Spawn argument '" ,
417+ stringify!( $invalid) ,
418+ "'. Valid options are: name, on_exit, request_capabilities, grant_capabilities, public"
419+ ) ) ;
420+ } ;
347421}
0 commit comments