ES-BASIC #3 - ラボユース合宿の発表資料

  • (by K, 2019.08.27)

(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
    • http://k.osask.jp/files/esb20190827a.png
  • 以下のプログラムでマンデルブロ画像が描けます(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
    • http://k.osask.jp/files/esb20190827b.png
  • 以下のプログラムで横スクロールのゲームもできます(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
    • http://k.osask.jp/files/esb20190827c.png

(3) ラボユース合宿中にやったこと

  • [1]プログラムからプログラムを作る機能・実行する機能
    1000 PROGNEW A; // 新規プログラムを作成(A=ハンドル番号)
    1010 PROGPUTIMM 1000,"FOR I=0,100000000; NEXT",A
    1020 PROGRUN A; // 作ったプログラムをただちに実行
    1030 PROGDEL A; // 作ったプログラムを削除
    • (註)上記プログラムは下記のプログラムを作って実行して消します。
      1000 FOR I=0,100000000; NEXT
  • [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
  • [6]配列を操作する命令の追加
    • (つまらない例なので省略)
  • [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コンパイラ方式のインタプリタかなーと思っています。

こめんと欄


コメントお名前NameLink

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-08-28 (水) 17:43:03 (24d)