Macro tear::__impl_twist[][src]

macro_rules! __impl_twist {
    ( @parse-map [$($bk:tt)*] [$($bv:tt)*] ($e:expr => $f:expr) ) => { ... };
    ( @parse-map [$($bk:tt)*] [$($bv:tt)*] ($e:expr) ) => { ... };
    ( @parse-map [$($bk:tt)*] [$($bv:tt)*] ($($tokens:tt)*) ) => { ... };
    ( @label-parse ($($flag:tt)*) [ | $($rest:tt)* ] -> $($l:tt)* ) => { ... };
    ( @label-parse ($($flag:tt)*) [ $token:tt $($rest:tt)* ] -> $($l:tt)* ) => { ... };
    ( @label-parse ($($flag:tt)*) [ ] -> $($rest:tt)* ) => { ... };
    ( @label-expr ($($flag:tt)*) [ $e:expr ] -> $($l:tt)* ) => { ... };
    ( @label-expr ($($flag:tt)*) [ $e:expr => $f:expr ] -> $($l:tt)* ) => { ... };
    ( @label-expr ($($flag:tt)*) [ $($rest:tt)* ] $($whatever:tt)* ) => { ... };
    ( @label-labels ($($flag:tt)*) $count:expr, [] -> [($($bk:tt)*) ($($bv:tt)*)] $e:expr ) => { ... };
    ( @label-labels ($($flag:tt)*) $count:expr, [ $label:lifetime : $type:ty , $($rest:tt)* ] -> [($($bk:tt)*) ($($bv:tt)*)] $e:expr ) => { ... };
    ( @label-labels ($($flag:tt)*) $count:expr, [ $label:lifetime , $($rest:tt)* ] -> [($($bk:tt)*) ($($bv:tt)*)] $e:expr ) => { ... };
    ( @label-labels ($($flag:tt)*) $count:expr, [ $($rest:tt)* ] -> [($($bk:tt)*) ($($bv:tt)*)] $e:expr ) => { ... };
    ( @label-box ( ("unbox") -> $($flag:tt)* ) ($($bk:tt)*) ($($bv:tt)*) $e:expr ) => { ... };
    ( @label-box ( ("pass") -> $($flag:tt)* ) ($($bk:tt)*) ($($bv:tt)*) $e:expr ) => { ... };
}

(dev) Macro required by twist!

Mostly contains step by step (@prefix) parsing for all the entrypoints in twist!. When it’s done, it calls twist! with the final processed values.

Overview of the steps

When breaking from a single loop, @parse-map parse the right-hand part as either an expression, or an expression => another expression (which is the mapping function).

When breaking from multiple loop labels, there are multiple steps:

  • @label-parse separates the labels from the right-hand expressions
  • @label-expr parses the right-hand expressions as either a single expression, or an expression => the mapping function
  • @label-labels parses each comma-separated label of the format $label or $label : $type
  • @label-box moves the collected data for breakvals into the right slot, to indicate if we need to unbox the values or not

Input and Output

The syntax for calling @label-parse is the following:

(("pass") -> ("break") () ()) [$($tokens)*] ->
  │          │         │  │      └ The tokens that make up the label list and the expression
  │          ├─────────┴──┘        eg. `'a 'b | 1 + 1`
  │          └ Only one the three flags should be filled. In order:
  │            - "break" if the innermost loop can be broken normally
  │            - the type of the innermost loop break value if we break with a value
  │            - the type of the boxed innermost loop break value, if we break
  │              with Box<dyn Any>
  └ "unbox" if we unbox the breakvals, otherwise "pass"

We use “flags” to simulate booleans with empty parenthese or non-empty parentheses with token trees inside. Because we can only conditionally do something when “it’s full”, we need to have a slot for each case.

We call twist! @boxed with the following syntax:

($($flag)*) ($($bk)*) [ ($($bv)*) () ] $e
    │           │       │         │    └ The expression to match on
    │           │       ├─────────┘
    │           │       └ Only one of these two slots should be filled.
    │           │         The left one is filled if we breakval normally
    │           │         The right one is filled if we unbox the value before breakval'ing
    │           └ The normal breaks
    └ The same three flags from the input

See inline documentation for brief explanations of what each @step does.