An experiment and tutorial on how to create a solid and portable macros system based on solid methodology and principles.
Design Goals:
- Portable -- better IDE experience, works both in Scala and Dotty
- Solid -- compiler crashes to a minimum, no hack required in writing macros
- Friendly -- no knowledge about compiler internals, no dependent universes
- Hygienic -- hygiene guaranteed by the type system
import scala.gestalt.api_
object Test {
def plus(a: Int, b: Int): Int = meta {
q"$a + $b"
}
}
Gestalt advances the state of the art of meta-programming in Scala:
- Macros are portable among different Scala compilers
- Better IDE support due to portability
- Hygienic macros ensured by type system
- Automatic owner chain management
- Type system defends against incorrect mixing of typed and untyped trees
- Friendly semantic APIs
- No inconvenience related to path-dependent universes
- Easy to implement by compiler vendors
The design space of a macro system is large. Gestalt aims to be simple, solid and portable for the 80% common use cases.
a ) Assumptions on compiler implementation
- more assumptions
- fewer assumptions (✓) : portability & easy implementation
b ) Assumptions on macro usage
- more assumptions (✓) : focus on 80% common cases, make them easy
- fewer assumptions
c) Features
- more features
- fewer features (✓) : metaprogramming is hard, restrict power, implementation solid
sbt macros/test:run