JavaScriptによるJavaScript実装

いで@いで庵

はじめに

セルフホスティング
ある言語でその言語自身の処理系を作ること
例:Cコンパイラ
スクリプト言語でも一応行われている
例:PyPy(PythonによるPython実装)

JavaScriptでもセルフホスティングの前例はある

  • Narcissus (Brendan Eichによる実装。)

でもSpiderMonkeyの開発ブランチでしか動かない

→じゃあ作るぜ

JavaScript概要

動的型付け
型宣言要らない
プロトタイプベース
オブジェクト指向の宗派の一つ。構文としてのクラスがない
JavaScriptの他にはSelf,Lua,Io,NewtonScriptぐらいしかない
関数がファーストクラスなオブジェクト
数値や文字列といった値と同等に扱える

実装の目標と現状

目標

ECMA262 3rd edition準拠

ECMA262は各ベンダーのJSの共通部分の規格。JavaScript1.5, JScript5.5相当

現状

文法の実装がだいたい終わったところ

  • まだfor in文と例外処理が実装されてない
  • 組込オブジェクトの実装ができてない

ソースコードから実行までの流れ

字句解析
ソースコードの文字列をトークンという単位に切り分ける
構文解析
トークンの配列から構文木を作る
実行コード生成
構文木から実行コード(機械語やバイトコード)を作る

実行コードを走らせる

字句解析

トークン
プログラム的に意味のある文字列の最小単位。
  • 記号 + - { ) ++ など
  • リテラル 3.14(数値リテラル) "hello"(文字列リテラル) など値を表す文字列
  • 予約語 if else while intなど
  • 識別子 要するに変数とかに使える名前 hoge fuga foo bar

※空白文字やコメントは無視

字句解析
ソースコードを一文字すつ読んでトークンに切り分ける。
トークンの種類も調べる。

字句解析 (続き)

要するにこんな感じ

実際には一気にソースコードをすべてトークン列に変換するのではなく、構文解析をしながら少しずつトークンに変換していく

研究報告書の字句解析の節の後半で書いているのは一気にソースコードをトークン列に変換しようとすると詰むという話

構文解析

トークンの配列から構文木を作る

人力でやる場合、再帰下降型パーサでやることが多い(たぶん)

字句解析とか構文解析とかめんどい人へ

世の中には便利なツールがありまして・・・

lex,flex
字句解析コードを自動生成
yacc,bison
構文解析コードを自動生成

実際に処理系を作るならこういうツールを使うのもありかも

実行コード生成

  • 構文木から命令列に変換
  • 識別子(変数名とか関数名とか)の解決
  • ジャンプ先アドレスの解決

VM設計

  • スタックマシン
  • ローカル変数はコールスタックフレームに直接置かないで
    ローカル変数を抱えているスコープオブジェクトへの参照を持つ
  • 変数へのアクセスはスコープオブジェクトの連鎖をたどって行う
  • コールスタックフレームはthisで参照されるオブジェクトを持つ

スコープオブジェクト?

  • 各スコープに対応するスコープオブジェクトが存在する
  • それぞれのスコープオブジェクトは
    それぞれのスコープに属するローカル変数を保有している
  • 親スコープへの参照を持っている

どうしてこんなものが必要?

クロージャの実装のために必要!!

クロージャとは

関数の中で関数を定義できる、かつ

内側の関数から外側の関数のスコープにアクセスできる機能

クロージャとは (続き)

何が問題?

関数の実行を抜けた後もスコープが生きている必要がある

コールスタックフレームにローカル変数を置けない!!

関数呼び出し(C言語の場合)

関数呼び出しを抜ければその関数のローカル変数は用済み。

→コールスタックフレームにローカル変数を直接置いておけばよい。

関数呼び出し(JavaScriptの場合)

関数呼び出しを抜けたあともローカル変数が参照されるかも。

→コールスタックフレームにローカル変数を直接置けない。

→スコープへの参照をコールスタックフレームに持たせる。

関数呼び出し(JavaScriptの場合 続き)

関数を呼ぶときはその関数のもつスコープオブジェクトを親とする新しいスコープオブジェクトを生成

スコープオブジェクトの処分はガベージコレクションに任せる。

今後の予定

  • for in文の実装
  • 例外処理の実装
  • 組み込みオブジェクトの実装

その他今後の希望

バインドを楽にしたい、VMコード生成時の最適化など

御清聴ありがとうございました。