rowl

rowlの開発を始めて1年が経ちました

1年前の今日、アセンブリで数十行のechoプログラムを作成しました。 それを徐々に育てて、今日ではソースコード行数がトータルで1万5千行を超えていました。 1年でたったこれだけかという気がしなくもないですが、趣味プログラムにしてはそれなりに進んだの…

rowlの式

rowlの式として以下の定義を使う方針にしました。その為、いろいろと実装の修正を行っています。 原始式(シンボル,整数リテラル,浮動小数点数リテラル,文字列)は式である。 hがシンボル,e1,...,enが式の時 h(e1, .., en)は式である。hを式のheadと言う。…

パターンマッチの実装(3)

型でのマッチングの実装を一部実装しました。 これによって関数のオーバーロードが出来るようになりました↓ print(10) # print_intが呼ばれる print("Hello World") # print_stringが呼ばれる関数定義時にはこんな感じで書きます↓ fib(n!Int): fib(n-1) + fi…

パターンマッチングの実装(2)

Rowlの動的なパターンマッチエンジンの構成について書きます。 まず、インタプリタ内にfuntableという関数テーブル(関数名 × 引数の数 → 関数実体)があります。 関数の実体は 関数本体(バイトコード) 関数定義のリスト(ASTではなくコンパイルした形) からな…

パターンマッチの実装(1)

自分はコンパイラの実装言語にはパターンマッチがあると楽だと思っているのでrowlにもパターンマッチエンジンを実装しています。以下の論文を参考にしています。 http://portal.acm.org/citation.cfm?id=507641&dl= これまで変数パターン、Dontcareパターン…

JITアセンブラを作った

とはいってもx86の機械語を生成するのではなく、VMのバイトコードを生成するやつを作りました。x86のJITアセンブラは次の世代で作る予定です。 このJITアセンブラは現在実装中のインタプリタに内蔵するJITコンパイラで用います。 以下はフィボナッチを計算す…

演算子順位法によるパーサ

リンカが問題なく動くようになったので、ようやく次の処理系(rowl1)作りを開始しました。 レキサはこれまでと同じく状態遷移図を手で作成しました。rowl2の開発時にはレキサの自動生成が出来るくらい、言語が高級になっていると良いなぁと思っています。現在…

ブートストラッピングの中で起きた問題と解決策

一か月ほど本業に専念していましたが、Rowlの開発を再開しました。 結構忘れているところがあるので、これまでの経過をまとめます。これまで実装したものの一覧は下図。 問題1: 機能不足 アセンブリ言語で実装したrowl0は機能が貧弱すぎて、次のステップで一…

オブジェクトファイルの設計

ファイル入出力とか可変長配列とかrowlVMのプリミティブが充実してきたので、現在はrowl-core言語で次期rowl1コンパイラの実装をしています。 ところが、メモリマネージャのないスクリプト言語であるrowl-coreは大量にメモリを消費する為ついに限界がきまし…

配列を実装した

メモリマネージャがちゃんと動きました。GCも今のところ大丈夫っぽいです。 ということで、エラトステネスの篩を実装してみました。次期コンパイラ実装専用のDSLなので可読性が低いのは勘弁してください。 (fun main () ( (sieve 200000) (exit 0) )) (fun s…

rowl1言語コンパイラをコンパイルするコンパイラ作成中

ようやくブートストラッピングの次のステップであるrowl1言語開発に着手しました。rowl1言語コンパイラはrowlVM上で動作するプログラムとして作成します。 rowl1コンパイラ記述言語のアセンブリ言語のアセンブラ http://github.com/nineties 中のrowl-assemb…

これまでの進捗の整理

アセンブリ(gas)でrowl0言語のコンパイラを作成した rowl0言語でrowl1言語のコンパイラ(型システム含む)を実装したが、バグ多発でいったん白紙に戻す。 rowl0言語でLISP風rowl-core言語のインタプリタを作成した rowl-core言語でvm記述言語を定義しvm記述言…

実行可能ファイルのフォーマット

実行可能ファイル(拡張子.rlx)からのロード・実行を実装しました。http://github.com/nineties/rowl/commit/c454fd019919dee0526ecc96b256091ca1da9771実行可能ファイルのフォーマットは先頭から 1ワード : ファイルの総バイト数(=N) 1ワード : グローバル参…

rowlVM/GC ブロック・ページの管理(再考)

今朝書いたのは綺麗ではなかったので考えなおします。多分車輪の再発明だと思いますが。 ポイントはページ⇔ページデスクリプタ間のアドレス変換のシンプル化です。 ページデスクリプタ・ページの配置を以下のようにします。 |<---------------------- 1 Mbyt…

rowlVM/GC ブロック・ページの管理

この論文 Compacting Garbage Collection with Ambiguous Roots ではあらかじめ固定長のメモリブロックがあって個定数のページがあるような実装になっているので直します。 GHCのアロケータ実装を参考にしています。まず、メモリはブロック単位(1Mbyte)でア…

データ型の定義

現在rowlVMにGCを実装中です。型のない言語で書いているのもあって、コードは汚くなってきましたがこのままいきます。 実装するGCは速度が気になりますが、とりあえずはMostly Copying GCで行こうと思います。下を参考にして、自分なりに修正をして実装しま…

マシンレジスタ割り当て

現在のマシンレジスタの割り当て状況のメモ。 %eax 汎用レジスタ %ebx 汎用レジスタ %ecx プログラムカウンタ %edx ゼロレジスタ(常に0が入っている) %esi スタックポインタ %edi ベースポインタ %ebxと%esi,%ediの値は保存しなければならない為関数の先頭…

組み込み型・命令(暫定)

コンパイラ・インタプリタ作成に特化した型・命令(consセルやビット配列)を用意して個性を出す方針。1バイトで足りるだろうか。組み込み型 ブール型 整数 (8bit・16bit・32bit・64bit) 浮動小数点数 (単精度・倍精度) 以上非ボックス化型 シンボル consセル …

関数が定義できるようになった。

rowlVM上で関数定義が出来るようになりました。 以下はfibonacciの定義。バイトコード長は22バイトです。今は手書きだけど、後でコンパイラ作ります。 (byte[] 100 fib @(assemble `( arg0 imm_i3 isub (if_lt hoge) arg0 imm_i1 isub (vcall 0 4) ; 0番(fib…

rowl VM/GC の実装

現在VM/GCの実装中です。 これまでの開発経過です。 1. rowl-coreインタプリタを開発 LISPの様なS式で書かれたrowl-core言語を処理する簡易インタプリタを以前作ったrowl0で実装しました。 言語機能が低いうちはインタプリタの方が簡単に作れるので、開発を…

VM/GCを作る。

2週間のんびりrowl-coreを作っていましたが、大体出来上がってきました。LISPもどきのインタプリタです。非常に雑な実装(識別子テーブルとか関数コールとか)ですが、使い捨てなのでこれでいいです。さて、次の作業はVMとGCの作成です。本当はパーサ作ったり…

今後の開発計画

現状 アセンブリ実装のrowl0完了 → rowl0実装のrowl1開発中 rowl1の開発もほぼ終了し、rowl2のコードを書き始めているという段階。 けれども、rowl1で高級な機能(クロージャや多重定義)を導入しようとしてバグが多発してきたので一旦ここで計画の見直しを行…

オーバーロードを実装した

久々の機能追加。 import stdlib; f: () { return 1; }; f: (x!int) { return x; }; export main: () { x : f (); y : f (1); exit(ExitSuccess); }; などが実行できるようにした。引数の型が同一で戻り値のみの型が違う関数の定義はできない。(エラーチェッ…

レジスタ割り当て断念

現在の簡便なレジスタ割り当てだと、複雑な関数でレジスタが足りなくなって失敗してしまう。名前換えとかに手を出すのは泥沼化する危険があるので、rowl1ではスタックベースの実行方法にすることにした。

クロージャが動いた

以下のコードが動くようになった! import stdlib; make_counter: (n) { return () { return n++; } }; export main: () { counter : make_counter(1); x : counter() + counter() + counter(); sys_exit(x); (% -> 6 %) }; 実装は非常に辛かった。まだ相互…

条件分岐を一部実装した

こんな感じのコードが実行出来る様になった。 import stdlib; fib: (n) { if (n) { return n * fib(n-1); }; return 1; }; export main: () { exit(fib(3)); }; if(n)の部分はまだ比較演算子を実装していない為。 コンパイルすると _fib.LT1ii: pushl %ebp m…

大域脱出する関数の型

例外やexitなどの関数の型をどう扱えば良いか困った。OCamlだと val exit : int -> 'a Haskellだと exitWith :: ExitCode -> IO a みたいに多相型を返して任意の型と単一化できるようにするのが普通のようだけど、rowlはreturnで値を返すのでこれができない…

分割コンパイルができるようになった

export/import/external宣言を実装した. (% test.rl %) export type hoge : A | B (int) ; export plus: (x, y) { return x + y; }; みたいなコードをコンパイルするとヘッダファイルが自動生成される. (% test.rli generated by rlc1 %) type hoge : A | …

variantが書けるようになった

こんな感じで。 type test : A | B (int) | C (char, int) ; export main: () { x : A; y : B (2); z : C ('a', 0); syscall(1, 0); }; パターンマッチはまだ実装していない。というか実はまだif文すら未実装。 Cのunionみたいにサイズが最大であるCに合わせ…

名前付きフィールドを一部実装

以下の様なコードがコンパイルできるようになった。右辺値としての一部だけ実装。 f: () { return (x:1, y:2); }; export main: () { p : f(); syscall(1, p.x + p.y); }; クロージャを実装すればオブジェクト指向っぽいコードも書けるようになる。