kduy
3/5/2015 - 2:46 PM

#1 - Scala macros tutorial.md

...
[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
// 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")
}
// 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 }
    }
  }
}
// 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)
}
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
echo sbt.version=0.12.1 > project/build.properties
mkdir -p project {macros,macrostest}/src/main/scala/gd/wa

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: