Right now I have a macro label that will raise a compiler error if a compiler flag is used and the macro is invoked with a label identifier that doesn’t exist. I also want to add a feature where the compiler will tell you any labels that exist in label files that aren’t used in your program, but I’m struggling with this one.
Through compiler constants, I can record wherever the label macro is used, including the identifiers it sees, but I have no way of knowing when the compiler is done expanding macros (and therefore we’ve seen all instances of the label macro usage, and can now safely throw an error for any labels not used so far).
As an example, say I have the label yaml file:
labels:
one: one
two: two
Then the outcomes I would expect:
# Macro to read and load label identifiers into constansts
CrI18n.compiler_load_labels("mylabels.yml") # => knows identifiers ["labels.one", "labels.two"] exists
label(labels.one) # => "one"
label(labels.three) # => compiler error, `labels.three` doesn't exist
# Compiler error, `labels.two` defined but not used
Any suggestions? I suspect this isn’t possible with today’s macro hooks, but am open to being pleasantly surprised :) The finished macro looks to be the closest, but that seems to be run after types have been read in, but before method definitions (and where the majority of the label macro usage) have been figured out.
Interesting question!, I’ve tried different things, but without success… until I got the trick!
You could use the hookfinished at top level to execute your macro code, but it will executed only at the end of top level phase, meaning before the inner of defs.
macro finished
{% puts "two" %}
end
def foo
{% puts "three" %}
end
foo
{% puts "one" %}
The trick to to put your macro code inside a def into the finished hook.
def very_end
{% puts "four" %}
end
macro finished
very_end
{% puts "two" %}
end
def foo
{% puts "three" %}
end
foo
{% puts "one" %}
Nice trick @I3oris! Unfortunately it doesn’t seem to work across multiple files. I’m able to delay it enough to capture more usages than I did originally, but not quite all. Thanks though, you’ve given me another approach to think about at least. Might still be something to take advantage of there…
oh…
I thought it worked on multiple file because it worked between two file. However I cannot found an example that doesn’t work with multiple file. Can you share an example when that doesn’t works?
Ack! Sabotaged by my own experimentation - it looks like this trick does work, but I had a previous call in another macro to the equivalent of the very_end definition you provided in your example, which triggered it earlier than I wanted to with only the partial list of encountered labels.
After I remove that call entirely, I’m now able to reliably have some macro code run at the very end of everything.