mitsuchi/mud

演算子についていろいろ

Opened this issue · 18 comments

1inguini さんが進めてらっしゃる演算子の実装についてまとめてみました。
https://github.com/mitsuchi/mud/wiki

どうするのがよさそうか、ここでやりとりしましょう。

3-1 は 3 (-1) という関数3の適用になって、この場合は死ぬ。

1+add 2 3 は 1 (+add) 2 3 の意味になる

ここ矛盾してないですか(上が死ぬなら下も死ぬ)

ところでwikiに書かれてる内容が、「僕の実力不足で意図せずなってしまった挙動」と「意図される挙動」どちらも書いてあるので(前のコメントの部分は前者)理想の挙動だけにしてもらえますか?それに沿って実装するので

了解です!現状は書いてあったほうが分かりやすいと思うので、現状と理想で分けるようにします。

(上が死ぬなら下も死ぬ)はそのとおりと思います。矛盾というより、下は 1 (+add) 2 3 の意味になるし、(この場合は)死ぬのかなと思いました。wiki を更新しておきますね。

理想の挙動とかいっちゃって何様という感じで恐縮なのですが、まとめてみました。いかがでしょうか…。

現在の挙動のところ、僕が書いてるパーサはまだマージされてないので三土氏が書いたものの現在の挙動のほうが適切な気がしないでもないですね

了解です!「現在の挙動」も(しょぼいのがよく分かりますが)追加しました。その他もろもろ追記しました。

collaborators に 1inguini さんを追加していますので、wiki も編集いただけるようになっているはずです(といいつつ使い方はよく分かっていませんが)。

演算子に#を使えなくしました(コメントなのでむしろ入ってるほうがミス)

いまの構文だと
fun + (+ < ++) fun ++ (++ < +++) fun +++ (+++ < +)
というふうに循環する優先順位が宣言できてしまうことに気づきました

確かに!そのとおりですね。

優先順位に関する連立不等式を解いて解なしになったら(たぶん循環してるので)エラー、
みたいなうまいやり方があればいいですね。
なさそうなら循環の検出は後回しでいいと思います。

fun < (< < <<)と等しくなるfun < (<<<<)を許しますか(現状行ける)

なるほど。1文字目も2文字目も < だとわかってるんだから <<<< でいけちゃうんですね。
許す(現状のまま)でいいと思います! とはいえ読みにくいので実際には < < << と書くのがいいよね、という気持ちで。

fun + (+ < ++) fun ++ (++ < +++)と宣言されたとき+ < ++ < +++という優先順位になりますが、ここにfun +++ (+++ > +)という+よりも+++が一段階だけ優先されるという条件を加えると+よりも+++が二段階優先されるという現状と矛盾してしまいます、どうしましょう(どうしようもないと思います)。

fun +++ (+++ > +) fun ++ (++ < +++)が先に宣言されると[{+, ++}, {+++}]でやっぱりfun + (+ < ++)と矛盾します

+ < *が「+よりも*を一段階だけ優先」ではなく「+よりも*のほうが何段階かは不明だが優先される」なら無矛盾になりますが、定義された優先順位が分かりづらい上優先順位が一意に決まらなさそう(fun A (A < B) fun C (C < B)のとき[A, B, C]と[C, A, B]両方の可能性がある)なのでまずそうです

precedence [foo, bar, baz]
fun + (+ baz) = ...
fun * (* bar) = ...
fun == (foo ==) = ...

みたいにすれば単純化できますが、あまりエレガントではないかなぁという気持ち

というのも、

precedence [foo, bar, baz]
fun + (+ baz) = ...
fun * (* bar) = ...
fun == (foo ==) = ...
fun block = {
    precedence [foo, foobar, bar, baz]
    fun ++ (++ foobar) = ...
    x y -> x ++ y
}

と新しいスコープで新しい優先順位の新しい演算子を定義するときに外側の(fooとかを優先順位指定子と呼ぶことにすると)優先順位指定子を過不足なく書き直さなくてはいけないので

難しいですね!

案1
「A < B のとき、BはAより一段階優先される。A < B, B < C, A < Cは、CがAに対して1段階かつ2段階優先という意味になって矛盾するのでコンパイル時にエラーとする」

・利点:とりあえず実装できそう
・欠点:単体では優先順位が無矛盾なプログラムどうしをのちのちインポートなどで混ぜ合わせると矛盾が生まれてコンパイルできない、となりそう。

これはとりあえず実装できそうです。
それかこんなのはどうでしょう?

案2
A < B のとき A -> B という辺を書いて優先順位指定の全体を有向グラフとするとき、
優先順位を次のように定める。
・どこからも入ってくる辺を持たない頂点の優先順位は0とする。
・優先順位n1, n2, .., nm のm個の頂点から入る辺を持つ頂点の優先順位は max(n1, n2, .., nm) + 1とする。

例:辺は上から下に向かうとする。A < B, C < B の例は

A  C
\ /
 B

となり、A=0, C=0, B=1 (=max(0,0) + 1)。つまりAとCは同順。

A < B, B < C, A < C の例は

A
|\
B |
|/
C

なので、A=0, B=1, C=2 (=max(0,1) + 1)

A < B, A < C, B < D, D < E, C < E という例だと

  A
 / \
B   C
|   |
D   |
 \ /
  E

となり、A=0, B=1, C=1, D=2, E=3 (=max(1,2) + 1)。
こんな感じで一般の場合にもうまく行けばいいんですが。