Suppose we need to build an event handling system. Scattered about of the user source code there are event handler - functions with a specific signature, marked with attribute macros #[event_handler]
and event dispatcher functions which are marked with #[event_dispatcher]
attribute macros.
# [event_dispatcher]
fn event1_dispatcher (src: & mut EventSource, event1: & Event1) {}
# [event_dispatcher]
fn event2_dispatcher (src: & mut EventSource, event: & Event2) {}
# [event_dispatcher]
fn event2_dispatcher2 (src: & mut EventSource, event: & Event2) {}
# [event_handler]
fn handler2 (src: & mut EventSource, event: & Event1) {}
# [event_handler]
fn handler3 (src: & mut EventSource, event: & Event2) {}
# [event_handler]
fn handler4 (src: & mut EventSource, event: & Event2) {}
# [event_handler]
fn handler5 (src: & mut EventSource, event: & Event2) {}
After all macros expansion, as result, the following code expected.
fn event1_dispatcher (src: & mut EventSource, event1: & Event1) { handler2 (src, event1); }
fn event2_dispatcher (src: & mut Event Event, event2: & Event2) {
handler3 (src, event2);
handler4 (src, event2);
handler5 (src, event2);
}
fn event2_dispatcher2 (src: & mut EventSource, event2: & Event2) {
handler3 (src, event2);
handler4 (src, event2);
handler5 (src, event2);
}
fn handler2 (src: & mut EventSource, event1: & Event1) {}
fn handler3 (src: & mut EventSource, event2: & Event2) {}
fn handler4 (src: & mut EventSource, event2: & Event2) {}
fn handler5 (src: & mut EventSource, event2: & Event2) {}
The moment of the macros expansion in generally almost unpredictable, since it determined by macros textual location and it contained module insertion point.
To accomplish the project is needed to hold information about all available event handler functions before any event_dispatcher
macros expansion. So it can be used, to compose their event dispatcher function body. The information is collected in #[event_handler]
macros expansion process. We need somehow prevent any #[event_dispatcher]
macros expansion before all #[event_handler]
macros are proceeded.
This requirement make building the project in Rust macros quite difficult.
My proposal is to add to the macros an expansion_order
attribute. So programmer, if necessary, can enforce some order of macros expansion.
Macros without the expansion_order
attribute are expanding, as it’s now - immediately, in place.
But expansion of macros with new order attribute, are delayed, until all macros without order attribute are completely expanded.
At the very end, the lasted macros, are sorting according the expansion_order
attribute and expand sequentially.
Inside group of macros with same expansion_order
the order of expansion may vary. Only different attribute value can guaranty expansion order.