ES-BASIC #1

  • (by K, 2019.07.16)

(0) はじめに

  • ES-BASICはEssen開発プロジェクトのサブプロジェクトで、昔懐かしのBASICっぽい言語を適当に作ってみようというものです。

(1) なぜBASICか

  • BASIC言語は、今になって思えば、とても「教えやすい」言語だと思います。
  • 行番号とかも、一般には嫌われているように思いますが、しかし運動会のプログラムなどでは番号の後に演目が書かれているほうが普通なので、プログラムの前に番号があるのは実に自然です。
  • コンソールで、数値で始まる一行を入力されたら、それはプログラムとして保存すればいいわけですし、そうでなければダイレクト実行すればいいので、すごくわかりやすいじゃないですか。これは実装も簡単で済みます。こんないい発明を捨てるのはもったいないと私は思うのです。エディタを別に用意する必要もないわけです。
  • 今の私は、JITコンパイラを簡単に作れるライブラリを手にしているので(自作ライブラリ)、ちょっとした思いつきで言語を作っても失うものはほとんどありません。もし飽きたら中断して別の物を作ればいいだけのことです。・・・むしろだからこそ、いろいろ作って試してみることができます。

(2) 1日目

  • とりあえず思いつきで6時間くらい書いて、これくらいはできるようになりました。処理系は185行です。
    prompt>esbasic  (起動)
    Ok
    1 a=1
    2 b=2
    3 c=a+b
    4 println c
    list
       1 A=1
       2 B=2
       3 C=A+B
       4 PRINTLN C
    
    Ok
    run
    3

  • さらに1時間くらいかけてfor~nextを実装しました(TOは予約語にしたくなかったので、コンマにしました)。
    Ok
    s=0; for k=1,10; s=s+k; next; println s
    55
    
    Ok
    for i=0,99999999; next; println i
    100000000
  • この1億回ループに要した時間は、C言語の1億回ループの5倍くらいでしたので、まあまあの速度は出ています。
  • ここではダイレクト実行をやっていますが、もちろんプログラム内でもfor~nextは使えます。

(3) 2日目

  • [30分, +10行] まず30分くらいで、プログラムの大文字化ルーチンを修正しました。これまでは何も考えずに入力された文字は全て大文字化していましたが、この修正により、文字定数やコメント内の小文字は大文字にならなくなりました。
  • ・・・よしよし。プログラムは10行増えて、214行になりました。
    • そもそも大文字化する必要はないという考え方もできるのですが、私は今回大文字化したかったので、まじめに作りました。

  • [10分, +8行] 今度はMEMコマンドを作ってみました。現在どのくらいメモリを使っているのかの確認用です。プログラムは222行になりました。
  • すると問題が発覚しました。MEMコマンドを連続して打っているだけでも、消費メモリが徐々に増えていくのです。これは良くない!
    • バグを突き止めて修正しました。ライブラリに問題がありました。30分くらいで直りました。よしよし。これでおかしな挙動はなくなりました。

  • [1時間半, +89行] if~then~else~fiを追加して、inputを追加して、printを拡張しました。
  • printは文字定数も表示できるようになりました。カンマで終わると改行しません。printlnという名前がBASICらしくないと思っていたので、printに戻しました。
  • 処理系は311行になって結構長くなったなーという感じではあるのですが、しかしできることが増えて結構楽しいです。
    list
       1 PRINT "How old are you? ",
       2 INPUT AGE
       3 IF AGE < 20 THEN
       4     PRINT "You are a child."
       5 ELSE
       6     PRINT "You are a adult."
       7 FI
    
    Ok
    run
    How old are you? 12
    You are a child.
    
    Ok
    run
    How old are you? 55
    You are a adult.
    
    Ok

  • [1時間, +25行] さらに1時間くらいかけて、%演算子を追加して、for文にstep指定を追加しました。これで素数探しができるようになりました。現在処理系は336行です。
    list
       1 PRINT 2,,3,,
       2 FOR I=5,999,2
       3   I1=I-1
       4   F=0
       5   FOR J=3,I1,2
       6     K=I%J
       7     IF K==0 THEN F=1; FI
       8   NEXT
       9   IF F==0 THEN PRINT I,,; FI
      10 NEXT
    
    Ok
    run
    2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139
    149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283
    293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457
    461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631
    641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821
    823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997
    Ok
  • 絶好調です!

  • [10分, +4行] ついでに乗算と除算も追加しました。現在処理系は340行です。

(4) 3日目

  • [50分, -9行] 今日はまずGOTO命令とIF~GOTO構文を追加しました。行数が減っていますが、ちょっと雑に作ってきたのを整理したせいです。現在トータルで331行です。
  • そして私の定番ベンチマークの一つ、「1000万以下の素数の個数を数える、ただし配列は使わないで」をやってみました。
    list
       1 C=2; L=3; // 2,3の分は最初から数えてある、5から探す
       2 FOR I=5,10000000,2
       3   T=L*L; IF T < I THEN L=L+1; FI
       4   FOR K=3,L,2
       5     T=I%K; IF T==0 GOTO 8
       6   NEXT
       7   C=C+1
       8 NEXT
       9 PRINT C
    
    Ok
    run
    664579
  • よし、答えは合っています。しかも3.4秒しかかかりませんでした。これは速い!C言語で書いた場合と同じ速さです。
  • このプログラムの場合、剰余算で律速しているので、レジスタ変数を使わない簡単なJITコンパイラでも最高速度が出てしまうのです。やった!

  • [10分, +4行] 今度はRAND文を作ってみました。これはINPUTと同じように使います。いわゆるRAND関数ではありません。現在トータルで335行です。
    list
       1 RAND R; R=R%90; R=R+10; // これで10~99になる.
       2 PRINT "いくつだとおもいますか? ",; INPUT I
       3 IF R==I THEN PRINT "あたりです!"; FI
       4 IF R> I THEN PRINT "もっと大きいです"; FI
       5 IF R< I THEN PRINT "もっと小さいです"; FI
       6 IF R!=I GOTO 2
    
    Ok
    run
    いくつだとおもいますか? 50
    もっと小さいです
    いくつだとおもいますか? 30
    もっと大きいです
    いくつだとおもいますか? 40
    もっと大きいです
    いくつだとおもいますか? 45
    もっと大きいです
    いくつだとおもいますか? 47
    もっと大きいです
    いくつだとおもいますか? 49
    もっと小さいです
    いくつだとおもいますか? 48
    あたりです!
    
    Ok
    run
    いくつだとおもいますか? 48
    もっと大きいです
    いくつだとおもいますか? 75
    もっと大きいです
    いくつだとおもいますか? 86
    もっと大きいです
    いくつだとおもいますか? 95
    もっと大きいです
    いくつだとおもいますか? 99
    あたりです!
    
    Ok
    run
    いくつだとおもいますか? 50
    もっと大きいです
    いくつだとおもいますか? 88
    もっと大きいです
    いくつだとおもいますか? 90
    もっと大きいです
    いくつだとおもいますか? 99
    もっと小さいです
    いくつだとおもいますか? 98
    もっと小さいです
    いくつだとおもいますか? 94
    もっと小さいです
    いくつだとおもいますか? 92
    もっと小さいです
    いくつだとおもいますか? 90
    もっと大きいです
    いくつだとおもいますか? 91
    あたりです!
    
    Ok

  • [1時間, +19行] ここまでできるようになったら、もうやるしかないよなーということで、私にとっては定番のblaライブラリを使って、グラフィック表示です。
  • 19行の追加でここまでできるのだから、まあ悪くはないかな、と思っています。現在トータルで354行です。
    Ok
    openwin win,256,256; // まずこれでウィンドウを開いておく.
    
    Ok
    list
       1 C=0
       2 FOR Y=0,255
       3   FOR X=0,255
       4     SETPIX WIN,X,Y,C
       5     C=C+256
       6   NEXT
       7 NEXT
       8 FLUSHWIN WIN
    
    Ok
    run
  • こうすると、こんな感じの絵が出ます(ウィンドウタイトルは違います)。
    • http://osecpu.osask.jp/download/app0006a.png

  • [1時間, +27行] さらに頑張って、gosub作りました。push/popも作ったので一応再帰ができます(ここは笑うところです)。現在トータルで381行です。
  • ローカル変数がないので、すごく苦し紛れですが、しかし一応ちゃんと動きます。
  • これは再帰でフィボナッチ数を計算しているプログラムです。
      1 INITSTACK 1000; I=34; GOSUB 2; PRINT R; GOTO 10
      2 // fibo:  input i, output r.
      3 R=I
      4 IF I >= 2 THEN
      5   I=I-2; GOSUB 2; PUSH R
      6   I=I+1; GOSUB 2; POP T; R=T+R
      7   I=I+1
      8 FI
      9 RETURN
     10 //
  • 実行時間を測定したところ、C言語で書いた場合のちょうど2倍になりました。

こめんと欄


コメントお名前NameLink

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