* ES-BASIC #4
-(by [[K]], 2019.09.06)

** (6) 開発メモ #1
-このメモを書き始めるまで:
--[2012.09.07] OSECPU-VMを作ろうと思い立つ。・・・これより以前の歴史は長すぎるのでここには書かない。
--[2013.03.??] セキュリティキャンプの教材にOSECPU-VMを使おうと決心。
--[2013.08.??] セキュリティキャンプをやっているうちに、OSやVMよりも言語開発に興味がある人の方が多そうだなあと感じた。ということで、OSECPU-VMが一段落ついたら次は言語に行こうと思った。

--[2015.03.17] 言語開発としてKH-FDPLというのを始める。[[K]]にとってはOS/VM系開発から言語処理系開発への切り替えになる。
--[2016.02.17] C言語に永続変数を持たせる「Persistent-C」の開発を始める。・・・まあまあのものはできたけど、なんか物足りない。
--[2016.10.24] 演算子や構文を自由に作れる「Essen」の開発を始める。・・・しかし難航する。
--[2017.06.16] TL-1, TL-2, TL-3 を開発し、プログラミング言語開発入門みたいなことを始める。→[[text0010]]
--[2018.05.31] TJ01~TJ03を開発し、JITコンパイラを作るのは難しくないと立証(→[[text0010]])。・・・その後、JITコンパイラのコード生成を頑張って、C言語並みの実行速度を実現。
--[2019.02.22] OSC2019 Tokyo/Spring で Essen2019-A を発表。Essenのブランド名を冠してはいるものの、もはやJITコンパイラではない。しかしEssenで実現したいことの一部を表現できた。
--[2019.04.16] 言語を何度も作りなおすのに疲れてきたので、言語からいったん離れて、自分の開発効率を大幅に向上できるような、自分専用ライブラリを作ろうと決心。
--[2019.04.29] 開発に使う言語をC言語からC++へ変更することにした。その方が使いやすいライブラリを作りやすいと思ったので。

--[2019.07.12] ついに ES-BASIC の開発を開始する。自作ライブラリがあれば、言語開発は相当にはかどるだろうと思っていたが、実際すごくはかどった。名称のESはもちろん私の言語開発ブランドであるEssenに由来する。→[[esbasic0001]]
--[2019.07.17] PUSH、POP命令を付けることで、グローバル変数しかないのに再帰呼び出しを実現(笑)。
--[2019.07.24] 整数演算しかできないES-BASICだけど、固定小数点演算にすることでマンデルブロ集合の描画に成功。
---(ここの3週間弱は、忙しくてほとんど開発できなかった時期)
--[2019.08.15] スクロール命令を付けたので、スクロールするゲームが作れるようになった。
--[2019.08.23] SecHack365の福岡合宿で、ES-BASIC用のプログラムとして、迷路作成プログラムを作ってみた(穴掘り法)。50分くらいでできた(このうちの半分の時間はバグ取り)。なかなか楽しい。
--[2019.08.27] ラボユース合宿で、ついにプログラムがプログラムを作ってそれを即座に実行するという機能を、ES-BASICに追加。自己書き換えすら可能。ついでにここまでの成果をとりあえず公開。→[[esbasic0003]]
--[2019.09.02] 代入文で、右辺に複数の演算子があるような「式」がやっと使えるようになった。ただし演算子の優先順位は無視していて、1+2*3が9になる。それでも今までよりは格段に便利。
--[2019.09.03] 代入文以外の文脈でも式が使えるようになった。一時変数の乱発が必要なくなり、一気に便利さが増した。
--[2019.09.05] 今までどちらかと言えば軽い持ちで雑に作ってきたES-BASICであったが、たったの830行ほどの処理系でしかないのに、JITコンパイラだから手軽なのに爆速だし、REPLがあるから気軽に実行できるし、プログラムをファイルに保存しなくても、コピー&ペーストで入力して実行できるし、blaライブラリがあるから簡単にグラフィックもできるし、「ああ、もしかしたら私が理想とするプログラミング環境に今までで一番近いのはこいつなのではないか」と直感的に思った。・・・Essenの基本仕様の一つに、「演算子や構文を簡単に拡張するための機能がある」というのがあったが、830行のプログラムなら簡単に手入れできるので、言語が言語を拡張する機能を持っている必要性はもしかしたらないかもしれないとも思った。

-''[2019.09.06(金)]''
--GOTOやGOSUBのとび先で、ラベルを指定できるようになった。これで、単純に行番号を付け直してもプログラムが壊れないように作れるようになった。めでたい。
--一方で、自作ライブラリのKIndexHSクラスにはどうやらrehashまわりにバグがあるらしいことが判明したので、次はこれを直さなければいけないだろう。
--この時点で、esbasic.cppは864行。・・・行数が36行も増えたが、これはgoto先がなかったりラベル定義が重複した場合などにもきちんと対処したため。
--KIndexHSのrehashのバグは、rehashのせいではなかった。KMemPoolのallocが怪しい。しかし別のバグを直したら再発しなくなってしまったので、ひとまずこのバグは追及しないことにする。

-''[2019.09.09(月)]''
--コマンド処理で引数の省略の処理を一般化したらきっとかなり行数が減るだろうと思っていたけど、実際にやってみたら8行しか減らなかった・・・。
--他でもいろいろ工夫して、トータルで500行くらいにできないだろうかと考えているのだけど、それはかなり無理があるかもしれないと思い始めた。

-''[2019.09.11(水)]''
--プログラミング言語に依存しない汎用的な部分をライブラリに追い出して、818行まで減らしたけど、目標の500行にはほど遠い・・・。

-''[2019.09.12(木)]''
--808行にはできた。うーん、あとはJITコンパイラのコア部分を切り出せたらよいのだけど、まだライブラリへ切り出すほどの完成度じゃないんだよな・・・。
--グラフィックの機能については、言語と独立にあってもいい気がするので、これらを追い出せば行数は減らせるな・・・。マイナス70行くらいは行けるんじゃないか?

-''[2019.09.13(金)]''
--ちょっと間に合わせ感はあるけれど、とにかく上記方針で732行まで減らせた!
--「プログラムを小さくするにはどうしたらいいのか」を考えると、このプログラムの本質は何か、どの部分は汎用化してライブラリに追い出してもいいか(再利用可能か)ということを真剣に考えることになるので、すごくいいと思う。でも多くの人はそういう観点でのプログラミングはしていないだろうけど・・・。
--言語を作っていると、特にその言語固有の新しい機能とかを作った場合、それはライブラリとして切り出すことができる。ライブラリにしておけば、その自作言語を使わなくても、ライブラリを利用することで、その新しい機能を利用できるようになる。そのようにライブラリを作った後で言語側を修正すると、言語はライブラリのラッパーになっているだけで、何も新しい機能は提供していないことになる。・・・これが言語処理系の実装方法として正しい姿なのだと私は思う。
--ES-BASICにデバッグ支援機能として、LWAIT命令を付けてみた。これは、line-waitの略で、一行実行するごとにどのくらいwaitを入れるのかをマイクロ秒単位で設定できる。・・・最近のPCはどいつもこいつも速くなってしまい、「動いているところ」を見るのはかなり難しい。たいてい最終結果だけが見える。昔はすごく遅かったので、動いているところを見るのは簡単だったのに。もしかしたら、昔の速度の方がプログラミングの理解がしやすくて、デバッグもやりやすかったのかもしれない。そう思って、実行速度を下げるコマンドを付けてみた・・・というわけだ。
--正直これが有用かどうかは、今の私にはよくわからないけど(さすがにもう速度に関わらずデバッグできてしまうので)、でもプログラムに手を入れずともコマンドを実行してからRUNするだけで、実行速度を自由に上げ下げできるのは結構新鮮だった。
--いろいろ試してみて、マイクロ秒をやめてナノ秒にしてみた。1ミリ秒でも遅すぎる場合があったので。

-''[2019.09.14(土)]''
--なかなかよいアイデアを思いついた。これでES-BASICはデバッグ支援機能において、ユニークな機能を有していると言えることになりそう。
--詳しいことは後日書く予定。

-''[2019.09.17(火)]''
--[[esbasic0005]]を書いた。これはES-BASICの基本部分だけを作るのに必要なプログラムが、"kll0.h"を使った場合にどのくらいになるのかを確認するためのもの。
--とりあえず89行で書けることはわかった。

--そして Shift+End を入力すれば、いつでもただちに停止できる機能を追加した。止まった時の行番号も表示される。止まった時の変数の値もprintすればいくらでも確認できる。

-''[2019.09.18(水)]''
--[[esbasic0005]]を更新した。ライブラリ側にもうちょっと関数を増やしたら、75行まで減らせた。

-''[2019.09.19(木)]''
--私はES-BASICの中でたまにアセンブラを書きたくなる。いやその、ES-BASICがサポートしていない命令があって、でも試してみたいことがあって、そんなときにすごく便利だから。
--しかし普通にアセンブラを作るとそれは大掛かりになってしまうので、もっと簡易的なものにしよう。とりあえずは直接機械語を書ける程度で。それだけでも私にとってはかなりありがたい。
--今まで、そういう生々しい拡張(普通の言語っぽくないこと)をやるのには抵抗があったのど、どうせ自分用の言語なんだし、気楽に実装することにする。
--将来的に互換性を保たなければいけない、みたいな気構えも捨てよう。当面は何でもアリって感じで。
--そうすることで見えてくるものもあると思うので。

--4時間くらい頑張ったらできた。追加したのは60行。これでインラインアセンブラもどきの命令が使える。
--こんな感じの雰囲気。
  13         CODE `xor   0X33 #RM:EAX,EAX
  14         CODE `store 0X89 #RM:EAX,[N]
  15         LABEL FORLOOP
  16           CODE `load  0X8B #RM:EAX,ECX
  17           CODE `imul  0XF7 #RM:5,ECX
  18           CODE `shrd  0X0F 0XAC #RM:EDX,EAX 24
  19           CODE `load  0X8B #RM:ESI,EAX
  20           CODE `load  0X8B #RM:EAX,EBX
  21           CODE `imul  0XF7 #RM:5,EBX
    (中略)
  36           CODE `load  0X8B #RM:EAX,[N]
  37           CODE `inc_eax 0X40
  38           CODE `store 0X89 #RM:EAX,[N]
  39           CODE `cmp   0X81 #RM:7,EAX %446
  40           CODE `jle   0X0F 0X8E #REL:FORLOOP
--ということで、すごく気軽に機械語で遊ぶ環境ができた。mod r/mやラベル計算くらいはやってくれる。
--もちろんES-BASICの他の命令と混在できるので、一番重たいループの内側だけをcodeで書けばいい。
--何か適当なファイル名を付けてソースを保存する必要はないし、アセンブルもコンパイルも必要ない。適当に入力して、runするだけ。気に入ったらlistしてコンソールからコピペして、好きなところに貼り付けておけばなくならない。
--もちろん実行速度は爆速なので(機械語だから当然だけど)、もう速度で他の言語に負けることはなくなった。まあ自力でアセンブラで書くのなら、の話だけど。
--アセンブラなのに Shift+End で停止することができて、しかも止まったらどこまで実行していたかも教えてくれるなんて、なんかむちゃくちゃ甘やかされているというか、正直あり得ない感じがする!止まった時の変数の値も確認できてしまう、すごくアセンブラらしくない!!

-''[2019.09.20(金)]''
--ALIAS命令を付けて、レジスタ名を隠して書けるようにした。これでレジスタ割り当ての変更とかが容易になった。
--そして各行ごとの実行回数をカウントして表示する機能も付けた。これはすごい。BASICにそんな機能があっても、まあそんなものかという気はするけど、アセンブラでこれができるって相当にすごい。
--アセンブラでプログラミングしていると、ここは通っているんだろうか?みたいなことを確認したいと思うことがよくある(まあC言語でもたまに確認したくなるけど)。そんなときに、行ごとの実行回数つきのリスト表示を見たら、もう一発で分かる。あちこちにprintfを仕込んで確認するなんていうことをしないでいい。
--アセンブラの中で処理を中断してしまった時などは、なんとレジスタの中身までも確認できる(ようにした)。どこで止まったかもわかるから、本当にデバッグがはかどる。もうアセンブラじゃないみたいだ。
--ES-BASICはBASICなんだと思うとささやかなインパクトしかないのだけど、アセンブラだと思うと、もうなんてすごいんだ!と圧倒されそうになる。超快適。病み付きになりそう。我ながらすごいものを作ってしまった。
--まあ基本的な使い方としては、まずES-BASICでお気軽に書いて、行ごとの実行回数カウントを見て負荷が集中している場所を突き止めて、そこだけアセンブラで書きなおせばできあがり。とても効率がよさそう。無駄がない。
--現在ES-BASICは927行。
--11/23~11/24のOSCに出展する予定なので、それまでにオープンソースにしよう。

-''[2019.09.25(水)]''
--ES-BASICのCODE命令がやっぱり少々不便なので、ASKA命令を追加してみた(なつかしい)。
  10         ALIAS ZX:ECX, ZY:EBX, XX:ESI, YY:EDI
  11         ASKA ZX = 0
  12         ASKA ZY = 0
  13         ASKA EAX = 0
  14         ASKA [N] = EAX
  15         LABEL FORLOOP
  16           ASKA EAX = ZX
  17           ASKA IMUL ZX
  18           ASKA SHRD EAX,EDX,24
  19           ASKA XX = EAX
--おお、これはまた格段に読みやすいし書きやすい!
--内部ではASKA文をCODE文に変換してバイナリを生成している(そのほうが実装が楽そうだったので)。
--現在の行数:
---esbasic.cpp: 915行 (主要部分、以下に含まれないすべて)
---chr.cpp : 104行 (ゲーム向けの追加フォントのデータ)
---aska.cpp : 111行 (ASKA命令、CODE命令のための記述)
* こめんと欄
#comment


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS