project kepler compile time metaprogramming for scala
DESCRIPTION
Scala Days, Project Kepler: Compile-Time Metaprogramming for ScalaTRANSCRIPT
![Page 1: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/1.jpg)
Scala Macros
London, 2012
Eugene Burmako Jan Christopher Vogt
![Page 2: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/2.jpg)
Scala Macros
Empower developers to extend the compiler and stay sane!
This enables compile-time: – checks
– processing
– AST transformations
– code generation
– shipping of ASTs to runtime
![Page 3: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/3.jpg)
Implementation
Compile-time metaprogramming has long existed in Lisp, so it should be easy to implement, right?
![Page 4: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/4.jpg)
Trickiness
Homoiconicity for a language with syntax and types is hard.
Being non-hygienic is evil, being hygienic imposes a complexity tax on the spec.
Need quasiquotations to make AST manipulations bearable. Yet another concept.
![Page 5: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/5.jpg)
Beauty
Martin Odersky was suspicious:
“And, we'd need to be convinced that it is beautifully simple, or it won't go into Scala”.
Here is what convinced Martin:
![Page 6: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/6.jpg)
Cats
![Page 7: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/7.jpg)
The essence
Scala reflection provides a slice of the compiler’s cake. The infrastructure is already there.
Macros are (Tree*, Type*) => Tree functions. Just as simple as that.
Hygiene itself is implemented by a macro. Hence we stay minimalistic and flexible.
![Page 8: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/8.jpg)
USE CASE: SLICK
![Page 9: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/9.jpg)
SLICK overview
val coffees = Queryable[Coffee]( /* db connection */ )
coffees .filter( c => c.id == 101 )
9
SLICK Queryable frontend
SLICK Query ASTs
SQL
NoSQL
Web services
Scala ASTs
compile time
handed over to runtime (reification) runtime
implemented using macros
![Page 10: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/10.jpg)
Macros in SLICK
implemented as a macro that works on argument AST at compile time
val coffees = Queryable[Coffee]( /* db connection */ )
coffees .filter( c => c.id == 101 )
def filter[T]( predicate: T => Boolean ) : Queryable[T] =
macro QueryableMacros.filter[T]
object QueryableMacros{
def filter[T:c.TypeTag] (c: scala.reflect.makro.Context)
(predicate : c.mirror.Expr[T => Boolean]) = …
}
![Page 11: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/11.jpg)
A macro body
object QueryableMacros{
def filter[T:c.TypeTag] (c: scala.reflect.makro.Context)
(predicate: c.mirror.Expr[T => Boolean]) = {
val reifiedPredicate =
c.mirror.Expr[ reflect.mirror.Expr[T => Boolean] ](
c.reifyTree( c.reflectMirrorPrefix, projection.tree ) )
c.reify{ translate("filter", ) }
}}
// macro implementation signature
// reify tree (ship to runtime)
// splice into runtime call
splicing
inlined at the call site (macro expansion), translates queries further at runtime, e.g. to SQL
c.prefix.eval, reifiedPredicate.eval
![Page 12: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/12.jpg)
Resulting macro expansion
Scala AST
That are macros in SLICK
coffees .filter( c => c.id == 101 )
translate(
"filter",
coffees,
Function( List("c"),
Apply( Select("c", "id"), "==", List(
Literal(Constant(101)))))
)
![Page 13: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/13.jpg)
Applications in the compiler
• Removed a compiler phase (LiftCode)
• Made a 80% solution (manifests) a 99% solution (type tags)
• Manifests à la carte – no longer hardcoded in Implicits.scala, it‘s just several macros (you can write your own implementations!)
• Ideas: SourceLocations, SourceContexts, static requirements on the compiler and the compilation environment
![Page 14: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/14.jpg)
Applications in the wild
• SLICK
• Macrocosm
• Scalatex
• Expecty
• Scalaxy
• Ideas: procedure typing with arrows, lens generation, ACP DSL, zero-overhead mocks
![Page 15: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/15.jpg)
Future work
• Debugging generated code
• Untyped macros
• Type macros
• Macro annotations
• Replacing the compiler with a macro
![Page 16: Project kepler compile time metaprogramming for scala](https://reader033.vdocument.in/reader033/viewer/2022051312/54747b0bb4af9fae0a8b5734/html5/thumbnails/16.jpg)
Future work
• Debugging generated code
• Untyped macros
• Type macros
• Macro annotations
• Replacing the compiler with a macro
Come on, just kidding about the last one!