[Nashorn] "${expr}"で様々な計算式を文字列に埋め込む
投稿日: 2015/12/13 14:00:53
jjsに-scriptingオプションを指定すると、文字列の中に${expr}という形式でexprの部分に変数名や計算式を埋め込むことができます。コンストラクタや代入を埋め込むこともできます。
${expr}はexprの部分をそのままeval()に渡しているのかと思ったのですが、バイトコードを見た限りではeval()は使用されておらず、例えば"A${x+9}Z"は("A"+(x+9)+"Z")に相当する処理に変換されるようです。
1-1. 実行するスクリプト(stringInterpolation.js)
var s = "A";
var n = 10;
print("s+1=${s+1}, n+1=${n+2}, s.aaa=${s.aaa}, [3,4]=[${[3,4]}]");
print("new java.awt.Point(5,6)=${new java.awt.Point(5,6)}");
print("(function(x)x*7)(8)=${(function(x)x*7)(8)}");
var t = null;
print("(t=s)=${t=s}=(t)=${s}");
1-2. jjsで実行する
>jjs -scripting -fullversion stringInterpolation.js
nashorn full version 1.8.0_66-b18
s+1=A1, n+1=12, s.aaa=undefined, [3,4]=[3,4]
new java.awt.Point(5,6)=java.awt.Point[x=5,y=6]
(function(x)x*7)(8)=56
(t=s)=A=(t)=A
2-1. バイトコードを確認するためのスクリプト(stringInterpolationByteCode.js)
var x = "s";
print("A${x+9}Z");
2-2. jjsに-pc(--print-code)オプションを付けてバイトコードを確認する(抜粋)
>jjs -scripting -fullversion -co=true -pc stringInterpolationByteCode.js
nashorn full version 1.8.0_66-b18
class: jdk/nashorn/internal/scripts/JO1P0
// class version 51.0 (51)
// access flags 0x21
...
L3 [bci=29]
<line 2>
29 aload 2
30 invokedynamic dyn:getMethod|getProp|getElem:print(Object;)Object; [static 'bootstrap' fastscope]
35 getstatic ScriptRuntime.UNDEFINED : Undefined;
38 ldc "A"
40 aload 2
41 invokedynamic dyn:getProp|getElem|getMethod:x(Object;)Object; [static 'bootstrap' fastscope]
46 bipush 9
48 invokestatic Integer.valueOf(I)Integer;
51 invokestatic ScriptRuntime.ADD(Object;Object;)Object;
54 invokestatic ScriptRuntime.ADD(Object;Object;)Object;
57 ldc "Z"
59 invokestatic ScriptRuntime.ADD(Object;Object;)Object;
62 invokedynamic dyn:call(Object;Undefined;Object;)Object; [static 'bootstrap' fastscope]