Skip to content

Instantly share code, notes, and snippets.

@torgeir
Last active July 6, 2019 08:49
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save torgeir/4392014 to your computer and use it in GitHub Desktop.
Save torgeir/4392014 to your computer and use it in GitHub Desktop.
A quick howto on getting started with scala macros (from the scala macros paradise branch, using sbt and sbt gen-idea)

Scala macros tutorial, using sbt

The following steps executed in order will;

  • create the project file structure
  • set the sbt version
  • add the gen-idea sbt plugin (if you want to import your project into intellij)
  • create an sbt build, that builds the macros project prior to the macrostest project (so the regex macro is usable in the macrostest project)
  • create the macros project scala file
  • create the macrostest project scala file
  • compile the two projects
  • fail compilation of macrotest, as the invalid regex [a-z is created compile time by the regex macro

Versions:

  • scala 2.11.0-SNAPSHOT (from org.scala-lang.macro-paradise)
  • sbt 0.12.1
  • gen-idea 1.2.0

References:

mkdir -p project {macros,macrostest}/src/main/scala/gd/wa
echo sbt.version=0.12.1 > project/build.properties
echo 'resolvers += "sbt-idea-repo" at "http://mpeltonen.github.com/maven/"' >> project/plugins.sbt
echo >> project/plugins.sbt
echo 'addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0")' >> project/plugins.sbt
// project/Build.scala
import sbt._
import Keys._
object BuildSettings {
val buildSettings = Defaults.defaultSettings ++ Seq(
organization := "gd.wa",
version := "1.0.0",
resolvers += Resolver.sonatypeRepo("snapshots"),
scalacOptions ++= Seq(),
scalaVersion := "2.11.0-SNAPSHOT",
scalaOrganization := "org.scala-lang.macro-paradise"
)
}
object MyBuild extends Build {
import BuildSettings._
lazy val root: Project = Project(
"root",
file("."),
settings = buildSettings) aggregate(macros, macrosTest)
lazy val macros: Project = Project(
"macros",
file("macros"),
settings = buildSettings ++ Seq(
libraryDependencies <+= (scalaVersion)("org.scala-lang.macro-paradise" % "scala-reflect" % _)
))
lazy val macrosTest: Project = Project(
"macrostest",
file("macrostest"),
settings = buildSettings) dependsOn(macros)
}
// macros/src/main/scala/gd/wa/Macros.scala
package gd.wa
import scala.language.experimental.macros
import scala.reflect.macros.Context
import scala.util.matching.Regex
object Macros {
def regex(str: String): Regex = macro regexImpl
def regexImpl(c: Context)
(str: c.Expr[String]): c.Expr[Regex] = {
import c.universe._
str.tree match {
case Literal(Constant(string: String)) =>
string.r
reify { str.splice.r }
}
}
}
// macrostest/src/main/scala/gd/wa/MacrosTest.scala
package gd.wa
import scala.language.experimental.macros
object MacrosTest extends App {
import Macros._
regex("[a-z")
}
...
[error] exception during macro expansion:
[error] java.util.regex.PatternSyntaxException: Unclosed character class near index 3
[error] [a-z
[error] ^
[error] at java.util.regex.Pattern.error(Pattern.java:1713)
[error] at java.util.regex.Pattern.clazz(Pattern.java:2254)
[error] at java.util.regex.Pattern.sequence(Pattern.java:1818)
[error] at java.util.regex.Pattern.expr(Pattern.java:1752)
[error] at java.util.regex.Pattern.compile(Pattern.java:1460)
[error] at java.util.regex.Pattern.<init>(Pattern.java:1133)
[error] at java.util.regex.Pattern.compile(Pattern.java:823)
[error] at scala.util.matching.Regex.<init>(Regex.scala:156)
[error] at scala.collection.immutable.StringLike$class.r(StringLike.scala:222)
[error] at scala.collection.immutable.StringOps.r(StringOps.scala:29)
[error] at scala.collection.immutable.StringLike$class.r(StringLike.scala:211)
[error] at scala.collection.immutable.StringOps.r(StringOps.scala:29)
[error] at gd.wa.Macros$.regexImpl(Macros.scala:19)
[error] one error found
[error] (macrostest/compile:compile) Compilation failed
[error] Total time: 16 s, completed Dec 27, 2012 9:36:27 PM
@torgeir
Copy link
Author

torgeir commented Oct 6, 2013

Added a repo holding an updated version of whats in this gist https://github.com/torgeir/scala-macros-tutorial-using-sbt. Uses quasiquotes and shows how showRaw can ease debugging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment