Rhino Code Reading #0x05
12月です。
気温の変化よりも月日の流れる速さに寒気を感じえない今日この頃ですがRhino Code Reading #0x05です。
前回はParserクラスを中心に、ソースコードから抽象構文木を作成する話をしましたが、今回は抽象構文木と中間コードについてす。
まずは抽象構文木について。
以前に書きましたが、抽象構文木とは「プログラムの構造を表現した木構造のデータ」です。
その木構造の一つ一つはAstRootを祖先としたノードクラス達であり、具体的には以下のようなクラス階層をしています。
- AstNode
- ArrayLiteral
- Block
- CatchClause
- Comment
- ConditionalExpression # 条件文 (test ? true : false)
- ElementGet
- EmptyExpression
- ErrorNode
- ExpressionStatement # 式文
- FunctionCall # 関数呼出
- NewExpression
- IfStatement
- InfixExpression # 二項演算式
- Assignment # 代入文
- ObjectProperty
- PropertyGet
- XmlDotQuery
- XmlMemberGet
- Jump
- BreakStatement
- ContinueStatement
- Label
- Scope # スコープ
- ArrayComprehension
- LetNode
- Loop
- DoLoop
- ForInLoop # foreach
- ArrayComprehensionLoop
- ForLoop # for
- WhileLoop
- ScriptNode
- AstRoot # ルートノード
- FunctionNode # 関数ノード
- SwitchStatement
- KeywordLiteral
- LabeledStatement
- Name # 変数名 or 関数名
- NumberLiteral
- ObjectLiteral
- ParenthesizedExpression # 丸括弧
- RegExpLiteral # 正規表現リテラル
- ReturnStatement
- StringLiteral
- SwitchCase
- ThrowStatement
- TryStatement
- UnaryExpression # 単項演算式 i++, i--
- VariableDeclaration # 変数宣言
- VariableInitializer # 変数初期化
- WithStatement
- XmlFragment
- XmlExpression
- XmlString
- XmlLiteral
- XmlRef
- XmlElemRef
- XmlPropRef
- Yield
これらのクラスは全て、org.mozilla.javascript.astパッケージに含まれています。
このパッケージは11月に新たに追加されたパッケージであり、現在の最新リリースであるRhino 1.7R1には存在しません。
パッケージが追加される以前では、どうやら抽象構文木を作らず、直接中間コードに変換を行なっていたようです。
また、他に気になった点としてはYieldノードです。
これは私がJavaScriptに不慣れなせいもありますが、初めはRubyのyieldと同じようなものかと思いましたが、実際は違っていました。
答えは下記のサイトを参照。
[javascript] JavaScript 1.7 の yield が凄すぎる件について - IT戦記
今回のコードリーディングによって、JavaScriptでコルーチンのサポートしていたことを知ることになりました。
各ノードには次のノードを指し示すフィールドが用意されています。
InfixExpressionならleftとright、FunctionNodeならtargetといった具合保持するフィールドは各ノードの種類によって異なります。
これらのノードは全て、プログラム的に意味のある構造だけを抽出した抽象的なデータである為に抽象構文木と呼びます。
逆にソースコードの構造をそのままの形で表現した木構造データを構文木(Syntax Tree)と呼ぶそうです。
次に中間コードについてです。
中間コードもまた抽象構文木と同様に木構造のデータであり、
その要素も抽象構文木と同様AstNodeを祖先とするノードの集合によって形成されています。
抽象構文木との違いは、中間コードのほうがよりバイトコードへと変換しやすい形式へと変換されている点です。
具体的には抽象構文木から中間コードの変換として、下記のような処理が行なわれています。
- FunctionNodeは親スコープのAstRootもしくはFunctionNodeのfunctionsフィールドに格納する
- 冗長な部分を最適化を行なう。例えば数値リテラル同士の演算は演算結果にに変換する
- for文やwhile文などを、GOTO等を用いた等価のコードに変換する
- Etc.
これらの処理によって、抽象構文木は中間コードへと変換されます。
またオプションとして、toStringが呼びだされた際に使用するソース情報の付加も行ないます。
抽象構文木より作成された中間コードはコンパイラへと渡され、Javaバイトコードを作成するのに使用されます。
- Category(s)
- rhino
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/iwanaga/rhino-code-reading05/tbping