type t (* void *)

ソフトウエアのこととか

SATYSFi雑感

最近文章のためにずっと書いてる。 感触としてはかなり現状これでやっていくのはチャレンジングだと感じる。

Emacsのメジャーモードほしい

現状gfnさんが配布されているsatysfi.elがある

github.com

実装を見ると define-generic-mode で作られているシンプルなモードで、 キーワードハイライトが動作する感じ。 自動インデントとかかっこいい目の機能はない(と思う)。

私はこれ以外にカッコの対応が取れないときびしいので smartparen-mode を使っている。

github.com

<>の対応を取るためには、以下の設定を書いておくと良い感じがする。

(sp-local-pair 'fundamental-mode "<" ">")

書くときに困ること

Syntax Error or Lexer Error. 各括弧のによって何が起きるのかSATYSFi Bookを読んで把握したほうが良い。 プログラミング言語としてのSATYSFiはかなり特殊な言語だと思う。

文脈に依存したlexer

何を書くとLegalであるかというのは現在のコンテキストによって変わる。 そのコンテキストはどういう時に変化するかというと、各括弧によって変化する。

ソースコードのコメントにそのことが書いてある。

  (*
   * The SATySFi lexer is stateful; the transitions are:
   * | to \ from |program|block |inline|active |  math  |
   * |-----------|-------|------|------|-------|--------|
   * |  program  | (   ) |      |      | (   ) | !(   ) |
   * |           | (| |) |      |      | (| |) | !(| |) |
   * |           | [   ] |      |      | [   ] | ![   ] |
   * |  block    | '<  > | <  > | <  > | <     | !<   > |
   * |  inline   | {   } | {  } | {  } | {     | !{   } |
   * |  active   |       | +x ; | \x ; |       |        |
   * |           |       | #x ; | #x ; |       |        |
   * |  math     | ${  } |      | ${ } |       | {    } |
   *
   * Note that the active-block and active-inline transitions are one-way.
   *)

github.com

トップレベルはprogram stateから始まる。 demo.satyを順に見ていくと、

  • document関数の関数適用
    toplevelはdocument型の値を返す式を書く
  • (| によってprogramを受理する状態に遷移(変わらないが)。StackにStateをPushする
    • { によってinline stateに遷移、それをStack Push
      inline stateのときには地の文を書くことが出来る
    • \SATySFiのようなものはコマンド。コマンドはどういう時にセミコロンが必要なのか悩んだけど基本必要、コマンドの引数に{}があるときには書かない(書いたらエラー)
    • } でinline stateを抜ける
  • ………
  • '< はprogram stateからblock stateに遷移する
    • block stateは段落の塊みたいなinline-block型を持つ式を書く
    • +p は段落を作るためのコマンド
      • { でinline modeに遷移

.........

みたいなメンタルモデルを持たないといけない。 基本的には上の表の括弧で決まるから、わからなくなったら直前の開き括弧を探しに行くと良い気がする。

状態Lexerウウーみたいな気持ちになったけど、本質的に組版で地の文を書きつつプログラマブルな要素を書きたいとなると何でも書ける地の文の世界とプログラムの世界を状態で分けるのが自然な気がしてきた。

Syntax ErrorとかLexer Errorが出たらなんかこの状態でできないことしとらんかということを真っ先に考えたほうが良さそう。

// 今の理解なので間違ってたら教えてください。。。。まだ3週間くらいしか書いてないので

雑感

最近Latexを書きつつSATYSFiを書いていると頭が混乱してきます。 段落を書くのが +p { ... } で書くのと、line break 2つで切れ目と見て段落を形成するのはどっちが楽だろう。。。。。

LatexとSATISFIはソフトウエアとしての歴史が違うのでツールチェインで 比較してもしょうがないのだけどやはり色々辛いです。 けどもDSLのフロントエンド実装のことを無限に考えられて楽しいです。 Syntax Error, Lexer Errorのところを何とかする方法考えて遊んでいます。。

Emacsで自動インデントできるのメジャーモード作りたいんだけど、SMIEとか言う奴が全くわからないでいます。。。。。

追記:

私も少しはフロントエンドのコードを書いていたからわかるんですがわかりやすいエラー出力のために言語処理系がフロントエンドを変更してクソデカ lexer or parserになっていくのを見ると、この辺を諦めてスパっと行くのも開発者の労力削減のためにやむを得ないという気持ちになります。

GCCのパーサー定義とか見ると本当に地獄で、こんなものを1人プロジェクトでメンテ出来るわけがありません。 しかしそれでは書く方が辛さがあるので、いい感じの折衷案みたいなものが見いだせると嬉しいですね。。。