Scala: dotty コンパイラを試す
Scala Days San Francisco のキーノートでも触れられた、Scala の新コンパイラ dotty を試す。
環境
- OS X Yosemite: Version 10.10.2
- Processor: 2.6 GHz Intel Core i7
- Memory 16GB 1600 MHz DDR3
- 以下インストール済み
- Oracle JDK 8 u40 (JDK 7 ではビルドできなかった)
- git: version 1.8.4.3
- sbt: version 0.13.0
インストール
まずは、作業ディレクトリに scala/scala および dotty のソースコードをダウンロード。
$ cd <YOUR_WORK_DIR> $ git clone git@github.com:scala/scala.git $ git clone git@github.com:lampepfl/dotty.git
Java コンパイラのバージョンを確認 (1.8.x であればOK)
$ javac -version javac 1.8.0_40
JDK 8 をインストールしているのにバージョンが古い場合は、環境変数などをチェック
$ export JAVA_HOME=`/System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java_home -v "1.8"` $ echo $JAVA_HOME /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home $ PATH=${JAVA_HOME}/bin:${PATH} $ javac -version javac 1.8.0_40
dotty をビルド
$ cd dotty $ sbt compile
100個ほど warn メッセージが表示されたが、Travis CI でも出ているので無視。所要時間は 58秒ほどだった。
sbt run を実行すると、usage が表示された。
$ set run
Usage: scalac <options> <source files> where possible standard options include: -Dproperty=value Pass -Dproperty=value directly to the runtime system. -J Pass directly to the runtime system. -bootclasspath Override location of bootstrap class files. -classpath Specify where to find user class files. -d destination for generated classfiles. -dependencyfile Set dependency tracking file. -deprecation Emit warning and location for usages of deprecated APIs. -encoding Specify character encoding used by source files. -explaintypes Explain type errors in more detail. -extdirs Override location of installed extensions. -feature Emit warning and location for usages of features that should be imported explicitly. -g Set level of generated debugging info. -help Print a synopsis of standard options -javabootclasspath Override java boot classpath. -javaextdirs Override java extdirs classpath. -language Enable one or more language features. -no-specialization Ignore @specialize annotations. -nobootcp Do not use the boot classpath for the scala jars. -nowarn Generate no warnings. -optimise Generates faster bytecode by applying optimisations to the program -pagewidth Set page width -print Print program with Scala-specific features removed. -sourcepath Specify location(s) of source files. -strict Use strict type rules, which means some formerly legal code does not typecheck anymore. -target Target platform for object files. All JVM 1.5 targets are deprecated. -toolcp Add to the runner classpath. -unchecked Enable additional warnings where generated code depends on assumptions. -uniqid Uniquely tag all identifiers in debugging output. -usejavacp Utilize the java.class.path in classpath resolution. -verbose Output messages about what the compiler is doing. -version Print product version and exit. @<file> A text file containing compiler arguments (options and source files)
UT を実行
$ sbt test ...snip... [info] Passed: Total 106, Failed 0, Errors 0, Passed 106
無事、全てのテストが通った。所要時間は 157秒。
REPL
Scala REPL で dotty の AST を試す。
$ ./bin/dotc -repl
Welcome to Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_40).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import test.DottyTypeStealer._; import dotty.tools.dotc.core.Types._;
import test.DottyTypeStealer._
import dotty.tools.dotc.core.Types._
scala> val s = stealType("object o { type X }", "o.X")
s: (dotty.tools.dotc.core.Contexts.Context, List[dotty.tools.dotc.core.Types.Type]) =
(Context(
owner = module class , scope = Scopes()
owner = module class , scope = Scopes()
owner = module class , scope = Scopes()
owner = module class , scope = Scopes()
owner = module class , scope = Scopes()
owner = module class , scope = Scopes()
owner = val , scope = Scopes(module _root_)
owner = val , scope = null
owner = val , scope = null,List(TypeRef(TermRef(ThisType(TypeRef(NoPrefix,)),o),X)))
scala> implicit val ctx = s._1
ctx: dotty.tools.dotc.core.Contexts.Context =
Context(
owner = module class , scope = Scopes()
owner = module class , scope = Scopes()
owner = module class , scope = Scopes()
owner = module class , scope = Scopes()
owner = module class , scope = Scopes()
owner = module class , scope = Scopes()
owner = val , scope = Scopes(module _root_)
owner = val , scope = null
owner = val , scope = null
scala> val t = s._2(0)
t: dotty.tools.dotc.core.Types.Type = TypeRef(TermRef(ThisType(TypeRef(NoPrefix,)),o),X)
scala> val u = t.asInstanceOf[TypeRef].underlying
u: dotty.tools.dotc.core.Types.Type = TypeBounds(TypeRef(ThisType(TypeRef(NoPrefix,scala)),Nothing), TypeRef(ThisType(TypeRef(NoPrefix,scala)),Any))
scala> t.show
res0: String = o.X
scala> u.show
res1: String = ""
ただし、ここで動いているのはあくまでも Scala REPL であるため、dotty 固有の構文は受け付けられない。
Hello world
まずは、付属のサンプルコードを試してみたが、 ClassFormatError で実行できず。
$ cat ./examples/hello.scala
package hello
object world extends App {
println("hello dotty!")
}
$ ./bin/dotc ./examples/hello.scala
warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$GenMapFactory$$CC; assuming they are invariant
warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$MapFactory$$CC; assuming they are invariant
warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$GenSetFactory$$CC; assuming they are invariant
warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$SetFactory$$CC; assuming they are invariant
four warnings found
$ ll hello
total 16
-rw-r--r-- 1 user staff 1134 3 28 18:41 world$.class
-rw-r--r-- 1 user staff 400 3 28 18:41 world.class
$ scala hello.world
java.lang.ClassFormatError: Illegal method name "initial$scala.DelayedInit" in class hello/world$
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at hello.world.main(hello.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:70)
at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:101)
at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:70)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:65)
at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
App トレイトを使うのを避けたら、とりあえず動くようになった。
package hello
object world {
def main(args: Array[String]): Unit = {
println("hello dotty!")
}
}
$ dotc ./src/01_hello_world.scala warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$GenMapFactory$$CC; assuming they are invariant warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$MapFactory$$CC; assuming they are invariant warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$GenSetFactory$$CC; assuming they are invariant warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$SetFactory$$CC; assuming they are invariant four warnings found $ scala hello.world hello dotty!
新機能を試す
プロシージャ構文の廃止
関数定義の = を省略すると、
package hello
object world_ng {
def main(args: Array[String]) {
println("hello dotty!")
}
}
コンパイルエラーになる。
$ dotc ./src/02_hello_world_ng.scala
./src/02_hello_world_ng.scala:4: error: '=' expected but '{' found.
def main(args: Array[String]) {
^
one error found
XMLリテラル
旧形式のXMLリテラルはコンパイルエラーになる。
package hello
object xml_ng {
def main(args: Array[String]): Unit = {
println(XML Literal)
}
}
$ dotc ./src/03_xml_literals_ng.scala
./src/03_xml_literals_ng.scala:5: error: xml is not a member of scala.type
println(XML Literal)
^
one error found
将来は xml"" で中置記法に対応するとのことだが、現時点ではまだ使えない模様。
package hello
object xml_literals {
def main(args: Array[String]): Unit = {
println(xml"""XML Literal""")
}
}
$ dotc ./src/04_xml_literals.scala
./src/04_xml_literals.scala:5: error: xml is not a member of StringContext
println(xml"""XML Literal""")
^
one error found
トレイト・パラメータ
トレイトがパラメータを取れるようになる。
package hello
object trait_parameter {
trait CoordLike(x: Double, y: Double) {
def show() = println(s"($x, $y)")
}
object Coord extends CoordLike(1.0, 2.0)
def main(args: Array[String]): Unit = {
Coord.show()
}
}
コンパイルはできたが、残念ながら実行はできなかった。
$ dotc ./src/05_trait_parameter.scala warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$GenMapFactory$$CC; assuming they are invariant warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$MapFactory$$CC; assuming they are invariant warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$GenSetFactory$$CC; assuming they are invariant warning: encountered F-bounded higher-kinded type parameters for type scala$collection$generic$SetFactory$$CC; assuming they are invariant four warnings found $ scala hello.trait_parameter java.lang.ClassFormatError: Illegal method name "initial$hello.trait_parameter$$CoordLike" in class hello/trait_parameter$$CoordLike
パッケージの指定(package hello)をなくしたら、今度は別のエラーが出た。
$ scala trait_parameter java.lang.ClassFormatError: Method x in class trait_parameter$$CoordLike has illegal modifiers: 0x402
0 件のコメント:
コメントを投稿