大分空いてしまったけど自分用のメモなので忘れきる前にやったとこまで書きたいと思います。
書いてて思うけど、用語がちゃんと決まってないのでなんかふわふわしてるな。
前回、制御構文は前に出す方針だと書きましたが、具体的には下記のものを前に出しました。
条件構文
if/when/unless
ループ構文
while/each/for
関数、マクロ定義
def/defmacro
- if/when/unless
- bool if [trueの時実行される] [falseの時実行される]
- bool when [trueの時実行される]
- bool unless [falseの時実行される]
>>> true if ["ok"] ["ng"] print
ok
- while/each/for
- bool while []
- list each []
- 開始 終了 間隔 for []
>>> true while ["loop" print]
loop
loop
…
このままだと無限ループになるので条件文等で脱出する必要があります。
breakコマンドはありません。
whileは常にスタック先頭の値を評価するので、ループを終了したい時にはスタックにfalseを積みます。
>>> true while ["loop" print false]
loop
とすると一回で終了です。
listは初めてでてきましたが、Pythonのリストと同じで、実はquoteと同じものです。
>>> [1 3 5] each [print]
1
3
5
eachはリストの要素を順にスタックに積んで行きます。
>>> [1 3 5] each [as $i $i 10 + print]
11
13
15
みたいに変数に受けて使うこともできます。
forは開始、終了、間隔を指定し、順にスタックに積んで行きます。
>>> 5 10 2 for [print]
5
7
9
今日はここまで。関数の話が残っちゃったけど、次回に廻しします。
まず、なんで遊ぶだけなのにわざわざ作るのか?について。
既存の処理系のが色々ライブラリも充実してるし、安定してるんだけと微妙に自分にとっては使いにくいから。文法規則の一部が合わなかったり、覚えるのが面倒くさかったり、マニュアルが読みづらくて挫折したりってので、じゃあ自分が使い易いのを作ったらいいんじゃね?って発想です。
まず自分でこう書きたいって思いがあって、それが実現できたら楽しいし、実現できなくても、それがちゃんと考えた結果ならそれはそれで納得がいく。
でもだいたいやりたいと思うことは実装はできる。文法的な整合性が悪くて変更することはあるけど。自分の知らない概念や機能は思いもつかないので入れられない。なので自分で作る場合、自分の知識以上の機能は入れられないという欠点はあります。まぁそれは勉強せい、ということでしょうね。
今回はquoteについて。
通常、左から順に評価されるのですが、ちょっと今すぐには評価しないで欲しいなーという場合があるのでquoteという概念を導入してます。LISPやらCatやらにあるあれです。評価して欲しくないWORD群を[]で囲います。
>>> 1 2 [+]
1 2 [+]
となって"+"が評価されません。
applyでquoteを実行します。
>>> 1 2 [+] apply
3
で、こんなのをどこで使うかというて制御構文やらなんやら色んなところで使います。
if/else文で勝手に評価されたら困るもんね。その他の使い方については、また後で紹介します。
以前Catもどきのインターブリターを作った時には、後置にこだわったので制御構文も後ろに後ろに持ってったけど、わかりにくかったので今回は反省して、
制御構文は前に持って行く
という方針で進めました。
もうちょっといこうかと思ったんですが疲れたので制御構文についてはまた次回にて。
最近はオレオレ言語を作って遊んでいます。メモを見ると7/15からやり始めたようです。
FORTH系の後置構文の言語で、同じく後置構文のCatやRaven、Python、Lisp/Schemeをちょっとづつかじったような感じです。
実装にはPythonのPLY.pyを使ってるので、Pythonはかじったというかおんぶに抱っこ状態です。
名前はAlabicaです。コーヒーの名前にしました。
なんで後置構文かっていうと、UNIXのコマンドラインでコマンドをパイプで繋いでどこまでも処理を繋げていける気持ち良さがあるからかな。
どんな風に考えてどうしたかってのを忘れないうちにメモってみます。
>>> 1 2
1 2
左から評価されてスタックに積まれます。
>>> 1 2 + 5 *
15
+や*は評価されるとスタックからWORDを2つ取って演算する関数です。
>>> 1 2 swap dup
2 1 1
swapはスタックからWORDを2つ取って入れ替え、dupはWORDを1つ取ってコピーします。
>>> 1 as var
>>> var
1
邪道かもしれないけどRavenで導入してたWORDへの代入が便利だったので導入してみた。後置構文的には語順が逆のような感じがするけどこの語順が気に入ったのでこのまま採用しました。
ということで、まずはこんな感じ。