Context: Now I am implementing in Racket a few of the control structures
of Ink, a notation for writing text adventure games.
(If you are interested, see Writing web-based interactive fiction with ink )
I have the following macro:
define-syntax-parse-rule (choi* name action ...)
; a choice that can be taken only once during entire execution
; Do I need to worry about thread0safety?
#:with globalcounter (syntax-local-lift-expression #'1)
(when ( > globalcounter 0)
(propose (Choice name (thunk action ...
(set! globalcounter ( - globalcounter 1))
))
)
)
)
this defines an alternative that can be taken only once. And it works.
The globalcounter counts the number of activations, and refuses
to propose it if it has already been executed.
The globalcounter is generated by the call to syntax-local-lift-exoression.
There is a separate globalcounter for each use of the choi* macro.
Now one of the features of Ink is a RESET command.
RESET resets the state of the system to what it was at the start of
a game, meaning in my case that all those globalcounters have to be
reset to 1.
I do not know how to implement this, because I have found no means
to make or access a list of all these globalcounters at macro time or run time.
Surely there must be some way of collecting this information at
macro time so that I can use it in a macrogenerated run-time reset
function?
While it is possible to collect the list of #'globalcounter IDs at expansion time by just define a expansion-time variable, I think this does not to work because you'll have to ensure that the reset function is expanded last so it retrieves the complete list of counters. Even worse, the code that reset the counters must reside in the same module (which is caused by the use of mutable variables):
To fix the issue, an alternative is to simply collect the list of counters at run time and let each counter add itself to the list, just like the call to add-to-reset-list! that is lifted via syntax-local-lift-expression: