Open3

簡易Schemeフロントエンドの製作

okuokuokuoku

色々と悩んでみたけど、mruby方式でインタプリタを作って実アプリでベンチマークした方が良さそうなので、フロントエンドはとりあえず適当に用意することに。

mruby方式 = 一旦スクリプトをバイトコードにコンパイルしてしまってから実行する。

okuokuokuoku

Alexpander

今回はマクロの展開のためにAlexpanderを使う。

https://github.com/okuoku/yuni/blob/99d6aafb202581c0bcaa38431305a85a52fb65cf/alexpander/alexpander.scm

(配布元のサイトは消滅してしまったようだ。BSD3 or GPL2+。)

Alexpanderを通すと、R5RS Schemeのプログラムで使用される構文を begin define if delay lambda letrec quote set! の8種類にまで減らしてくれる。当然 and のような構文は if の連鎖になるので出力されるプログラムは相応に複雑になるが。。また、 map のような構文ではないライブラリ手続きは別途実装する必要がある。

okuokuokuoku

バイトコード

バイトコードはyuniの簡易FASLとSECDV VMを使う。

簡易FASL(drypack)

https://github.com/okuoku/yuni/blob/9335f8b968a19d48f93c860338902ffe9843f064/doc/dryscheme/drypack.md

drypackは、いわゆる(U)LEB128( https://en.wikipedia.org/wiki/LEB128 )の数値列でS式をシリアライズする。テキスト表現のS式よりもreaderの実装が簡単にできるというメリットがある。

SECDV VM

https://zenn.dev/link/comments/8b427b70218215

SCEDV VMはtail callと多値を直接扱える必要最低限の機能を持ったVMで、そのコンパイラは過去に書いている:

https://github.com/okuoku/yuni/blob/9335f8b968a19d48f93c860338902ffe9843f064/lib/yunivm/compiler/compilercore.sls

VMの命令としてシンボルを使うとちょっとVMの実装が面倒になるといった問題があるので、これを改造して使うことにする。

コンパイラの出力はS式となる。つまり、ラベル等の解決は自分でやる必要がある。