/// Captures are the macro equivalent of enums and macro 1.1 match arms. The capture either
/// contains one anonymous match arm or any number of named match arms. Captures are reusable,
/// i.e. they can be bound to scoped constants which can then be referred to any number of
/// times.
[pub] [macro] capture vertex_attribute {
/// you can use braces, brackets, or parentheses after the colon
unnamed: ( $kind:ty ),
named: {
$name:ident : $kind:ty
}
}
/// A macro takes a single anonymous capture, which may include other captures. Other syntaxes
/// for anonymous multi-armed captures welcomed, similar to the macros 1.1 syntax, perhaps.
[pub] macro buffer_layout(
$attrs($attr:&vertex_attribute),*
) -> [$macro | $item | $expr | etc...] {
// (idea:) macros have an optionally(?) somewhat well defined returned type
// the body that goes here could contain loops and if statements that operate on constant
// expressions; the body itself should be a sort of meta const-function
// the macros output is either determined by the return expression, like so
return fn my_func() {
};
// where the expr returned can be anything we can parse and coerce into an output;
// alternatively, there could be a quote! or emit! macro that aggregates all the calls to
// it; when the macro returns it hands the caller that aggregate output
}
The meta-variable syntax is a slightly extended version of the current syntax. Now repetitions can be named. Inside of a an emission macro, they can be indexed, after which accessing internal items requires dot notation.
Most importantly meta variables can be instances of captures, probably requiring some kind of syntax for differentiating between primitive token types and captures (captures can be referred to by fully qualified paths!). Items within a capture are accessed via dot notation.
===
Anybody interested in a system kind of like this for macros? This system is an order of magnitude more complicated than what Rust has, and I don't know if it could ever even be implemented in Rust (read: feasible to implement). And there's some lingering ambiguities.
I think the idea of reusable, compose-able captures is probably one we could very much use. The rest may be too much of a cost in terms of code readability vs productivity.
===
A more conservative syntax:
pub capture attribute {
unnamed: ( $kind:ty ),
named: {
$name:ident : $kind:ty
},
}
pub capture vertex_attributes {
unnamed: ( $( $attr:&attribute::unnamed ),* ),
named: ( $( $attr:&attribute::named ),* ),
}
const STATIC_FORMAT: vertex_attributes = { pos: [f32; 3], uv: [f32; 2], color: [byte; 4] };
pub macro buffer_layout {
( $attrs:&vertex_attributes::unnamed ) => {
// reverse the args and then recursively build a ZST ;)
// example usage in next arm
};
( $attrs:&vertex_attributes::named ) => {
// reverse the args and then recursively build a ZST ;)
// the "guts" are accessed like so:
$attrs { $($attr)* }
// I suspect there may be a difficulty in implementing the above...
// if that is true maybe an instrinsic macro
unpack!($attrs, {
$($attr)*
})
}
}
pub type static_vbo_format = buffer_layout!(static_format);