プログラミング言語をつくってみる③ - 関数とスコープ

最近、作業ログになっています。


スコープの作成

関数実装の下準備として、スコープを作りました。せっかくなので、ブロックスコープに対応しました。

コード1: スコープに対応(SsEnvironment)

コンストラクタで外側のスコープを渡せるようにし、自分の環境内に変数がない場合は、Outer をたどっていく感じです。もう Outer がなければ、例外を返します(つまり最上位までたどったけど見つからなかった)。また、スコープを付けると、変数宣言をちゃんとしなければ、プログラムがめちゃくちゃになってしまいますので、ちゃんと変数(または関数)を宣言しないと例外を返すようにしました。エラーメッセージ用に例外には対応するトークンを設定するようにした関係で、取得や設定命令ではトークンを渡さないといけなくなりましたが、まぁ、いいでしょう。

あとは、新しいスコープになる際には、

new SsEnvironment(env)
と外のスコープをコンストラクタに設定して、生成した環境を渡して eval を呼べば OK です。

関数の構文の作成

関数定義(declare_func)を追加し、グローバルには変数宣言と関数定義のみを書けるようにしました。

コード2: 関数定義を追加

スクリプトで定義した関数は、declare_func の eval 関数内でその抽象木を環境に登録するようにしました。そして、関数の実行は、関数定義の抽象木に呼び出し用の Call 関数を設定し、その中で行うようにしました。

コード3: 関数定義と呼び出し

これで、関数定義ができるようになりました。テストで、以下のコードを実行できました。最初に eval で抽象木を評価したあとに、JavaScript 側から

env.Get("main").Call(env, []);
と main 関数を呼び出すと実行されます。JavaScript 側からの呼び出しもラクラクですし、いい感じの組み込み言語っぽくなってきました。

コード4: テストコード
コード5: 出力結果

bool 型のリテラルがない

true 、false の解釈を忘れていました。字句解析でやってもいい気がしましたが、面倒だったので、文法を修正しました。(簡単なので、コードは省略)

まとめ

最低限、関数を持つプログラム言語くらいはできました。SsEnvironment に関数を設定すれば JavaScript ともつなげるので、簡単な組み込みスクリプトくらいには使えます。(文法がほぼ同じなので、メリットがありませんが)

次は、クラスを作ってみようと思います。