Glisp
クリエイティブソフトに組み込むための小さな S 式言語。TypeScript アプリのライブラリとして動きます。
ホスト言語の機能になる
TypeScript アプリにライブラリとして組み込む小さな言語。独自の VM もランタイムも持たず、ホスト側の関数や値をそのまま型付きで渡して使えます。
クリエイティブソフト向け
デザインツールや映像編集ツールに、コード・ブロック・直接操作の 3 通りで編集できる「設定兼スクリプト」を載せるための言語です。
失敗しても止まらない
名前が未解決でも、型が合わなくても、引数が足りなくても、評価は例外を投げず `()` を返します。型を持つ場所では既定値で続行され、エラーは別枠の診断として出るので、書きかけでも画面は描けます。
Glisp はクリエイティブソフトに組み込むことを前提とした、小さな S 式言語です。前身 Glisp: A Lisp-based Design Tool Bridging Graphic Design and Computational Arts の言語部分を切り出して、他のツールから組み込みやすい形に整えています。
想定しているのは、同じプロジェクトファイルを以下の 4 通りで扱えるようなツールです。
- ブロックエディタで構造的に編集する(Scratch 風)
- キャンバス上で直接操作する(裏で AST が書き換わる)
- テキストエディタでコードとして書く
- 設定ファイルとして保存する(中身はそのまま実行可能)
;; ホスト側がキャンバス用のプリミティブを bind する例
(def "circle"
(=> (cx: number cy: number r: number): Shape ...))
;; プロジェクトファイルは静的データと計算式を混ぜて書ける
{
size = 200
half = (/ size 2 %)
^{label: "背景"}
bg = (rect 0 0 size size)
^{color: "#ff7b72" label: "ドット"}
dot = (circle half half (* 0.2 size %))
[bg dot]
}
;; GUI ではスライダで `size` を直接動かせて、ファイル側は空白もコメントも
;; メタデータもそのまま保たれるので、テキストエディタでも編集できる。
なぜ Lisp か
コード・ブロック・直接操作の 3 つを「同じデータの違う見せ方」にしたいので、コード自体がデータでもある言語が向いています。S 式は構文木をそのまま書く形なので、ブロックエディタとテキストエディタが翻訳なしで同じツリーを触れます。パーサも極端に小さく、ブラウザやプラグインのような場所に埋め込んで配りやすい。
TypeScript の機能として動く
Glisp は単独で動く処理系ではなく、ホスト側の TypeScript アプリの中で動きます。ソースの読み込み、評価、JS から Glisp 値を呼ぶこと、JS の値を Glisp 側に渡すこと、これらは全部ホスト側のコードです。Glisp の値は実体としては JS の値で、その上に薄いブランドとメタデータが乗っているだけ。
なので Glisp を採用しても VM が二つになったりはしません。TypeScript アプリにライブラリを 1 つ足す感覚で、型も両側で素直に通ります。副作用と寿命の管理はホスト側が引き続き持ちます。
() が失敗の受け皿
評価は例外を投げません。名前が見つからなかった、パスが終端を超えた、引数が足りなかった、型が合わなかった、どれも () を返します。() は unit 型を持つ通常の値ですが、型付きの場所では特別扱いされます。
- 型付きスロットに
()が来たら、そのスロットの既定値で置き換えて評価を続ける。 - 失敗の理由は診断として別枠に蓄積され、原因のソース範囲に紐づく。
書きかけでもプログラムは動き続けるので、画面は描き続けられて、スライダは効き続けて、型パネルは「次に来るべき型」を出し続けます。ユーザは自分のペースで診断を潰していけば良い。
それぞれの設計判断
クリエイティブソフトに組み込むときに必ず当たる問題と、コアの判断とがほぼ一対一に対応しています。
- 空白とコメントを保ったまま AST と相互変換できる構文木:GUI 編集とテキスト編集が同じファイルで噛み合う。
- 失敗が
()に落ちる:書きかけでも画面が描ける。型不一致は例外ではなく診断。 (IO T)と構造的な関数型:ホスト側の副作用を厳しすぎない型で正確に表せる。./key/../argのパス参照:GUI がノード同士を構造的なアドレスで結べる。一時的な名前を作らなくていい。expandと抽象化のはしご:ソースと最終値の間のどの段でもホストが見せられる。マクロを高位から低位まで段階的に展開できる。- 静的に名前解決できる:実行せずに型と参照を GUI に出せる。
詳しい設計動機は 仕様書 を参照してください。
ステータス
言語コアは src/ で実装中。ターミナル REPL はすぐ使えますし、ブラウザの Playground も同じソースから動いています。組み込み API は host-api にまとめてあります。