今回は他言語実行環境としてのGraalVM、Polyglotに着目します。現時点での最新版、1.0.0-rc5を使います。
http://www.graalvm.org/downloads/
なお、rc5からCommunity EditionがmacOSに対応しました(今まではEnterprise Editionだけでした)。こちらを使います。
$ java -version openjdk version "1.8.0_172" OpenJDK Runtime Environment (build 1.8.0_172-20180626105433.graaluser.jdk8u-src-tar-g-b11) GraalVM 1.0.0-rc5 (build 25.71-b01-internal-jvmci-0.46, mixed mode)
Polyglot Shell
$ $JAVA_HOME/bin/polyglot --shell GraalVM MultiLanguage Shell 1.0.0-rc5 Copyright (c) 2013-2018, Oracle and/or its affiliates JavaScript version 1.0 Usage: Use Ctrl+L to switch language and Ctrl+D to exit. Enter -usage to get a list of available commands. js>
polyglot
コマンドにshellオプションを付けると、REPLが立ち上がります。Ctrl+Lで言語が切り替えられるのですが、押しても切り替わらず何も起こらないでしょう。
これは、GraalVMにデフォルトで入っているのはJavaScriptだけだからです。他の言語は自分でインストールします。
このままでも、JavaScriptとJavaの相互運用はできます。相互運用する場合、--jvm
オプションが必要です。
$ $JAVA_HOME/bin/polyglot --shell --jvm js> var BigInteger = Java.type('java.math.BigInteger'); js> BigInteger.valueOf(2).pow(100).toString(16) 10000000000000000000000000
guコマンドでの言語インストール
GraalVMにはgu (Graal updater) コマンドがあり、guコマンドで言語をコンポーネントとしてインストールできます。提供されている言語を見ます。
$ $JAVA_HOME/bin/gu available Downloading: Component catalog ComponentId Version Component name ---------------------------------------------------------------- python 1.0.0-rc5 Graal.Python R 1.0.0-rc5 FastR ruby 1.0.0-rc5 TruffleRuby
python、R、rubyがあります。rubyをインストールします。
$ $JAVA_HOME/bin/gu install ruby Downloading: Component catalog Processing component archive: Component ruby Downloading: Component ruby Installing new component: TruffleRuby (org.graalvm.ruby, version 1.0.0-rc5) ... $ $JAVA_HOME/bin/gu list ComponentId Version Component name ---------------------------------------------------------------- ruby 1.0.0-rc5 TruffleRuby
rubyがあります。
RubyとJava、JavaScriptとの相互運用
polyglotシェルを起動し、Ctrl+Lするとrubyに切り替わります。
$ $JAVA_HOME/bin/polyglot --shell --jvm ruby>
JavaScriptと同様、rubyとJavaで相互運用できます。
ruby> BigInteger = Java.type('java.math.BigInteger') ruby> BigInteger.valueOf(2).pow(100).toString(16) "10000000000000000000000000"
JavaScriptからRubyを呼び出してみます。
js> var array = Polyglot.eval("ruby", "[1,2,42,4]") js> array[2] 42
RubyからJavaScript。
ruby> array = Polyglot.eval('js', '[1,2,42,4]') <foreign> ruby> array[2] undefined local variable or method `array' for main:Object
polyglotシェルでは他言語の戻り値をうまく扱えないようです。こう書くと動きます。
ruby> array = Polyglot.eval('js', '[1,2,42,4]'); array[2] 42
rbファイルに書く場合はきちんと動作します。
不明点
呼び出し側の変数をeval内で参照する方法。
js> var s = "100"; js> Polyglot.eval('ruby', 's.to_i') undefined local variable or method `s' for main:Object (NameError)
たとえばここでは、JavaScriptの変数sをRubyのeval内で参照したい。Javadocを見たけれど、うまく見つからなかった。
ソースファイルから実行する
test.rbとして保存します。
array = Polyglot.eval('js', '[1,2,42,4]'); puts array[2]
rubyコマンドはgraalvm-ce-1.0.0-rc5/Contents/Home/jre/languages/ruby/bin/ruby
にあります。
$ graalvm-ce-1.0.0-rc5/Contents/Home/jre/languages/ruby/bin/ruby -v truffleruby 1.0.0-rc5, like ruby 2.4.4, GraalVM CE Native [x86_64-darwin]
実行します。他言語と相互運用する場合、--jvm
オプションが必要です。
$ graalvm-ce-1.0.0-rc5/Contents/Home/jre/languages/ruby/bin/ruby --jvm test.rb 42
デバッガ
GraalVMには多言語環境に対応したデバッガがあります。なんとChromeのDevToolsを利用しています。--inspect
オプションをつけます。
$ graalvm-ce-1.0.0-rc5/Contents/Home/jre/languages/ruby/bin/ruby --jvm --inspect test.rb Debugger listening on port 9229. To start debugging, open the following URL in Chrome: chrome-devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/4cc77c2e-56cbc17f25aee
Chromeにchrome-devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/4cc77c2e-56cbc17f25aee
をそのまま入力します。
ブレークポイントも設定できます。
その他変数の中身を見るなど、デバッガ機能が利用できます。