ES-BASIC #3 - ラボユース合宿の発表資料
(1) ES-BASIC
- ES-BASICは川合が2019年7月から作り始めたプログラミング言語です。
- 基本的には、昔懐かしのBASICです。行番号ももちろんあります。
- インタプリタ(今風に言えばスクリプト言語)なので、
コンパイルなどの手間なくすぐに実行できます。
- だけどJITコンパイル方式を採用しているので実行速度は結構高速です。
- ES-BASICはC++を使って書かれていて、現在758行です。
(2) プログラム例
- 以下のプログラムでグラデーションが描けます(8行)。
1000 OPENWIN 256,256
1010 C=0
1020 FOR Y=0,255
1030 FOR X=0,255
1040 SETPIX X,Y,C
1050 C=C+256
1060 NEXT
1070 NEXT
- 以下のプログラムでマンデルブロ画像が描けます(46行)。
1000 OPENWIN 512,384
1010 FOR Y=0,383
1020 FOR X=0,511
1030 SN=0
1040 FOR SX=0,3
1050 CX=X*4
1060 CX=CX+SX
1070 CX=CX*56
1080 CX=CX+4673536
1090 FOR SY=0,3
1100 CY=Y*4
1110 CY=CY+SY
1120 CY=CY*56
1130 CY=CY+124928
1140 CY=0-CY
1150 ZX=0
1160 ZY=0
1170 FOR N=0,446
1180 XX=ZX*>>ZX,24; // 掛け算後にシフトする命令(固定小数点演算)
1190 YY=ZY*>>ZY,24
1200 T=XX+YY
1210 IF T>0X4000000 GOTO 1280
1220 TX=XX-YY
1230 TY=ZX*>>ZY,24
1240 TY=TY*2
1250 ZX=TX+CX
1260 ZY=TY+CY
1270 NEXT
1280 SN=SN+N
1290 NEXT
1300 NEXT
1310 N=SN/16
1320 C=0
1330 IF N<256 THEN
1340 C=N*0X10000
1350 ELSE
1360 IF N<447 THEN
1370 C=N-255
1380 C=C*256
1390 C=C+0XFF0000
1400 FI
1410 FI
1420 SETPIX X,Y,C
1430 NEXT
1440 LEAPFLUSHWIN 300
1450 NEXT
- 以下のプログラムで横スクロールのゲームもできます(21行)。
1000 OPENWIN 256,256
1010 Y=8; S=0; GCLS
1020 RAND T; T=T%15; T=T+1; ECHR 15,T,2
1030 RAND T; T=T%15; T=T+1; ECHR 15,T,3,4
1040 GETCHR 2,Y,T
1050 IF T==2 THEN S=S+1; FI
1060 GPRINTI 0,0,4,S
1070 IF T==3 GOTO 1200
1080 ECHR 2,Y,2,6
1090 EWAIT 200
1100 ECHR 2,Y,0
1110 EINKEY I
1120 IF I==4134 THEN Y=Y-1; FI
1130 IF I==4135 THEN Y=Y+1; FI
1140 IF I==32 GOTO 1200
1150 IF Y<1 THEN Y=1; FI
1160 IF Y>15 THEN Y=15; FI
1170 EINKEY I; IF I!=0 GOTO 1170
1180 SCROLL 0; CHRBOX 1,15,15,1,0
1190 GOTO 1020
1200 ECHR 2,Y,2,5
(3) ラボユース合宿中にやったこと
- [1]プログラムからプログラムを作る機能・実行する機能
1000 PROGNEW A; // 新規プログラムを作成(A=ハンドル番号)
1010 PROGPUTIMM 1000,"FOR I=0,100000000; NEXT",A
1020 PROGRUN A; // 作ったプログラムをただちに実行
1030 PROGDEL A; // 作ったプログラムを削除
- [2]行番号をつけなおすプログラム(11行)
1000 INPUT "src=?",A; STEP=10; LINE0=1000
1010 PROGNEW B
1020 PRINT "dest=",B
1030 PROGLIN1 I1,A; I1=I1-1; // 対象プログラムの行数を取得
1040 STRNEW S
1050 FOR I=0,I1
1060 PROGGET K,S,I,A; // プログラムを取得
1070 L=I1-I; L=L*STEP; L=L+LINE0
1080 PROGPUT L,S,B; // プログラムを作成
1090 NEXT
1100 STRDEL S
- [3]行番号を付け替えてプログラムを逆順にするプログラム
- [4]逆順にした後直ちに実行して、生成したプログラムを削除するプログラム
- [5]「プログラムを生成して実行するプログラム」を生成して実行するプログラム
1000 PROGNEW A
1010 PROGPUTIMM 1000,"PROGNEW B",A
1020 PROGPUTIMM 1010,"PROGPUTIMM 1000,'FOR I=0,100000000;NEXT',B",A
1030 PROGPUTIMM 1020,"PROGRUN B; PROGDEL B",A
1040 PROGRUN A; PROGDEL A
- [7]これらの改造に先立って、複数のプログラムを管理できるように改造
- とりあえずコンパイル型言語ではなかなかできないことができたかな?
(自己満足)
(4) ダウンロード
- 最低限度の使い方:
- とりあえずWindows用のみです。
- 起動するとOkがでて入力待ちになります。プログラムを入力してrunできます。
- グラフィックウィンドウは閉じないでください。
- exit命令を実行すると終了できます。
(5) 完全に余談
- なぜ川合はJITコンパイラ方式のインタプリタにこだわるのか?
- 普通のコンパイラではeval系の命令がありません。原理的に提供が難しいです。
- 川合はeval系の命令が大好きです。eval系の命令があれば、機械語やアセンブラの知識がなくてもJITコンパイラが作れます。・・・今回C++でES-BASICというJITコンパイラを書きましたが、機械語の知識がなければかけない内容になっています。つまりCPUに強く依存しています。もしC++がJITコンパイラであれば、ES-BASICの処理系は内部でC++命令の文字列を生成するだけで済むので、もっと簡単に作れたはずです。
- JITコンパイラなら、任意の処理を1万回呼ぶ、みたいなことをしたいときに、いろんな手段が選べます。
- 関数ポインタを受け取って間接callにする(普通のコンパイラだとこれくらいしか方法がない)。
- 関数ポインタを受け取って直接callを1万回ループするコードをevalで実行する。
- 任意の文字列(処理内容)を受け取ってそれを1万回ループの構文でサンドイッチしてからevalで実行する。
- いろんな方法を選べるということは、最速な方法を選択できるということでもあるので、JITコンパイラを採用したプログラミング言語は普通のコンパイラよりも高速になる傾向があると私は思ってます。
- コンパイラはコンパイラでいいところもあるのですが、私としては総合力ではJITコンパイラ方式のインタプリタかなーと思っています。
こめんと欄
|