1
votes

I know that Scala macros can't be referenced in code which is compiled in the same compilation run as the macro itself.

I also know from empirical testing that if one has a codebase that does that (refer to a macro in the same project), if the reference to the macro is removed, the code is compiled, the reference to the macro is re-inserted, and the code is compiled again, the second compilation will succeed, and the macro-generated code will function correctly. I assume this is because the compiler sees the .class file for the macro from the first compilation run and uses that.

Is there a way to write code (using reflection or similar) which determines if code generated by a macro exists, and if so calls it? I'm thinking of something similar to How to invoke method on companion object via reflection?, but instead of invoking a normal method, invoking macro-generated code.

My goal is to have code which does one thing when compiled the first time, and a different thing when compiled every time after the first, without any changes to the source code in-between the two compilation runs. I understand that this is not a good practice. Builds should be deterministic in most cases. My interest is in whether it's possible to create Scala code like this as a technical curiosity.

1
what have you tried so far?Zain
I've tried using normal reflection to get a list of methods available from the object where the macro is defined. I didn't think this would work, and it didn't. The [macro]_impl function is always visible via that approach, but the [macro] function never is.blincoln

1 Answers

1
votes

I know that Scala macros can't be referenced in code which is compiled in the same compilation run as the macro itself.

There are some changes in Dotty. Now macros can't be referenced in the same file but can be referenced in the same compilation run otherwise.

https://github.com/lampepfl/dotty/pull/7324

http://dotty.epfl.ch/docs/reference/metaprogramming/macros.html#defining-a-macro-and-using-it-in-a-single-project

Quote from there:

The idea is to suspend the callers of a macro (and their upstream dependencies), compile the sourcefile(s) containing the macro(s), and then compile the suspended files in a second run.