kmizuの日記

プログラミングや形式言語に関係のあることを書いたり書かなかったり。

Dottyで自作言語Klassicの処理系をビルドしてみる

つい先日、Scala 3になることが決定した次世代ScalaコンパイラDotty。このDotty、まだときどきコンパイラがクラッシュするなどのバグはありますが、Scala 2.11のライブラリを使うことができるので、Scala 2.11対応のライブラリやプロダクトを試しにビルドしてみることができます。

Dotty

に書いてある手順だけでは、Scala 2.11対応のライブラリを依存関係に含めることができないようです。Dottyで既存のソースをビルドするためには、次の手順に従う必要があります。まず、sbt-dottyプラグインをproject/plugins.sbtに含めます:

addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.1.0-RC4")

バージョンが0.1.0-RC4という微妙な番号なので、適宜読み替えてください。次に、build.sbtのscalaVersionとlibraryDependenciesを次のように修正します。

scalaVersion := dottyLatestNightlyBuild.get

これでdottyのnightly buildを取得してこられるようです。また、libraryDependenciesには、次のように、依存関係の記述のあとに.withDottyCompat()の呼び出しを入れます。

libraryDependencies ++= Seq(
  ("org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.4").withDottyCompat(),
  ("org.scalatest" %% "scalatest" %  "3.0.0").withDottyCompat()
)

また、project/build.propertiesではsbt.versionとして0.13.15を使うように指定します。

sbt.version=0.13.15

たったこれだけです。注意点として、現時点で(将来も?)structural typeはDottyで未サポートであるため、

def using[A <: { def close(): Unit}, B](resource: A)(f: A => B): B = try {
  f(resource)
} finally {
  scala.util.control.Exception.allCatch(resource.close())
}

のような形でLoan Patternを使っているライブラリは使わない形に書き換える必要があります。最後は、sbt run で実行してみます。

> sbt
> run -e "1 + 2 * 3 / 4"
[info] Running com.github.klassic.Main -e 1 + 2 * 3 / 4
2
[success] Total time: 1 s, completed 2017/05/04 9:28:25

問題なく実行できているようです。ただ、少し問題があって、sbt consoleを実行しようとすると、原因は不明なのですがNullPointerExceptionが発生するようです。ガッしたい気分ですね。