豊四季タイニーBASIC確定版

豊四季タイニーBASICの確定版を公開しましたのでお知らせいたします。確定版は初版でいまひとつもの足りなかった細部の働き(たとえばPRINTの改行させない表示など)を実現し、ソースを整理したものです。開発には終わりというものがありませんが、現状、サイズとパフォーマンスのバランスが最高に達したと判断しました。これをもってソースの修正を終え、今後はドキュメントの整備に専念するつもりです。

Windows版(実行ファイルとVCプロジェクト)の公開場所はこちら
Linux版(Raspbery Pi実行ファイルとソース)の公開場所はこちら
Arduino版(日本語コメント付きのスケッチ)の公開場所はこちら
PIC24F記念版(HEXファイルを含むMPLAB X IDEプロジェクト)の公開場所はこちら

なお初版は従来どおりこちらのページでダウンロードできます。

豊四季タイニーBASICの初版は多くの人が移植や拡張を試みてくれました。今回、ソースを整理したせいで、その成果に水を差すかもしれないことを心苦しく思っています。豊四季タイニーBASICを末永く使っていただくため、今回に限り、ご容赦ください。もうソースの修正をしないので、今後こういうことはありません。

すでに移植や拡張をしている人に向けて新しい方法の概要を述べておきます。

移植の方法の変更点は次のとおりです。起動用のソースttbasic.xから本体のソースbasic.xの関数basicを呼び出す形をとりました。移植にあたり書き換えが必要になる部分を本体のソースの冒頭にまとめてあります。起動メッセージの版名はシンボルSTR_EDITIONに定義してください。

拡張の方法の変更点は次のとおりです。追加するキーワードは配列 kwtblのどこに書き加えても構いません。そのかわり、リストを表示するとき後ろに空白を入れないキーワード(たとえば「=」)の中間コード名(たとえばI_EQ)を配列i_nsaに書き加えてください。また、前が定数か変数のとき前の空白をなくす中間コードの名前(たとえばこれもI_EQ)を配列i_nsbに書き加えてください。もし忘れたり間違えたりしてもリストの表示が不自然になるだけです。

ソースの詳細を知りたい人はArduino版のソースの日本語のコメントを読んでください。

私はもうソースを修正しないので豊四季タイニーBASICの将来はみなさんの手の中にあります。引き続きどうぞよろしくお願いいたします。

広告
カテゴリー: TinyBASIC タグ: パーマリンク

豊四季タイニーBASIC確定版 への9件のフィードバック

  1. 名無し より:

    「もうソースの修正をしない」と宣言されているところに心苦しいのですが、サブルーチン内のFORループをRETURNで抜けることが考慮されていないため

    10 FOR I=0 TO 100
    20 GOSUB 50;PRINT “SQRT(“,; PRINT#0,I,; PRINT “)=”,; PRINT#0,J
    30 NEXT I
    40 STOP
    50 FOR J=100 TO 0 STEP -1
    60 IF J*J<=I RETURN
    70 NEXT J
    80 PRINT "OVERFLOW!";STOP

    Palo Alto Tiny BASIC では動作する↑のようなプログラムは期待した動作とならないようです。

  2. vintagechips より:

    このブログをご覧のみなさんにご報告します。

    このあと名無しさんから見事に美しいパッチが紹介されます。私は豊四季タイニーBASICのソースをもう書き換えないと宣言したので書き換えは行いませんが(FORとNEXは対で使うことを言語仕様とします)、名無しさんのパッチがこのページにあることは大きな意義をもちます。それをすっきりした形でご覧いただくため、途中に挟まった私のコメントを要約に書き換えました。

  3. 名無し より:

    ご返事をありがとうございました。
    サブルーチン内のFORループからのRETURNでの復帰の不具合は下記の変更で修正されるものと思います(このブログのコメント欄は多バイト文字への変換を自動で行うようなので正確に貼れているかはわかりませんが)。

    — basic.cpp 2016-02-26 14:25:20.000000000 +0900
    +++ basic.cpp 2016-04-25 00:00:00.000000000 +0900
    @@ -13,7 +13,7 @@
    #define SIZE_IBUF 64 //i-code conversion buffer size
    #define SIZE_LIST 256 //List buffer size
    #define SIZE_ARRY 32 //Array area size
    -#define SIZE_GSTK 6 //GOSUB stack size(2/nest)
    +#define SIZE_GSTK 9 //GOSUB stack size(3/nest)
    #define SIZE_LSTK 15 //FOR stack size(5/nest)

    // Depending on device functions
    @@ -1020,23 +1020,25 @@ unsigned char* iexe() {
    }

    //ポインタを退避
    – if (gstki >= SIZE_GSTK – 2) { //もしGOSUBスタックがいっぱいなら
    + if (gstki >= SIZE_GSTK – 3) { //もしGOSUBスタックがいっぱいなら
    err = ERR_GSTKOF; //エラー番号をセット
    break; //打ち切る
    }
    gstk[gstki++] = clp; //行ポインタを退避
    gstk[gstki++] = cip; //中間コードポインタを退避
    + gstk[gstki++] = (unsigned char*)lstki; //FOR stack indexを退避

    clp = lp; //行ポインタを分岐先へ更新
    cip = clp + 3; //中間コードポインタを先頭の中間コードに更新
    break; //打ち切る

    case I_RETURN: //RETURNの場合
    – if (gstki < 2) { //もしGOSUBスタックが空なら
    + if (gstki < 3) { //もしGOSUBスタックが空なら
    err = ERR_GSTKUF; //エラー番号をセット
    break; //打ち切る
    }

    + lstki = (int)gstk[–gstki]; //FOR stack indexを復帰
    cip = gstk[–gstki]; //行ポインタを復帰
    clp = gstk[–gstki]; //中間コードポインタを復帰
    break; //打ち切る

    Arduino UnoでRAMが足りなくなるとのことですが、3バイト増えるだけなのでさほどの影響はないと思われます。また、現状のArduino Uno版の実装ではキーワードテーブルとエラーメッセージの文字列がRAMに配置されているようなので、これをPROGMEMに移動することで、400バイト程? RAMの使用量を減らせる余地があるのではないでしょうか。

  4. vintagechips より:

    このブログをご覧のみなさんにご報告します。

    私がパッチの当て方を誤り、一時的にRUN命令がエラーになると報告したことから、やり取りが混乱いたしました。名無しさんのパッチは正しく動作します。さらに、PROGMEMでRAMを節約できるという予測に私が疑問を呈したところ、次のようなパッチを紹介してくれました。

  5. 名無し より:

    ご確認ありがとうございます。

    1. 手持ちのプログラムで確認した範囲ではご指摘のエラーが確認できておりません。具体的にどのようなプログラムでRUN命令のエラーとなったか例示していただけると有難いのですが。

    2. とりあえずエラーメッセージだけ PROGMEM に配置してみました。

    — basic.cpp 2016-02-26 14:25:20.000000000 +0900
    +++ basic.cpp 2016-04-25 18:00:00.000000000 +0900
    @@ -101,30 +101,53 @@ char sstyle(unsigned char code,

    // Error messages
    unsigned char err;// Error message index
    +const char errmsg0[] PROGMEM = “OK”;
    +const char errmsg1[] PROGMEM = “Devision by zero”;
    +const char errmsg2[] PROGMEM = “Overflow”;
    +const char errmsg3[] PROGMEM = “Subscript out of range”;
    +const char errmsg4[] PROGMEM = “Icode buffer full”;
    +const char errmsg5[] PROGMEM = “List full”;
    +const char errmsg6[] PROGMEM = “GOSUB too many nested”;
    +const char errmsg7[] PROGMEM = “RETURN stack underflow”;
    +const char errmsg8[] PROGMEM = “FOR too many nested”;
    +const char errmsg9[] PROGMEM = “NEXT without FOR”;
    +const char errmsg10[] PROGMEM = “NEXT without counter”;
    +const char errmsg11[] PROGMEM = “NEXT mismatch FOR”;
    +const char errmsg12[] PROGMEM = “FOR without variable”;
    +const char errmsg13[] PROGMEM = “FOR without TO”;
    +const char errmsg14[] PROGMEM = “LET without variable”;
    +const char errmsg15[] PROGMEM = “IF without condition”;
    +const char errmsg16[] PROGMEM = “Undefined line number”;
    +const char errmsg17[] PROGMEM = “\'(\’ or \’)\’ expected”;
    +const char errmsg18[] PROGMEM = “\’=\’ expected”;
    +const char errmsg19[] PROGMEM = “Illegal command”;
    +const char errmsg20[] PROGMEM = “Syntax error”;
    +const char errmsg21[] PROGMEM = “Internal error”;
    +const char errmsg22[] PROGMEM = “Abort by [ESC]”;
    const char* errmsg[] = {
    – “OK”,
    – “Devision by zero”,
    – “Overflow”,
    – “Subscript out of range”,
    – “Icode buffer full”,
    – “List full”,
    – “GOSUB too many nested”,
    – “RETURN stack underflow”,
    – “FOR too many nested”,
    – “NEXT without FOR”,
    – “NEXT without counter”,
    – “NEXT mismatch FOR”,
    – “FOR without variable”,
    – “FOR without TO”,
    – “LET without variable”,
    – “IF without condition”,
    – “Undefined line number”,
    – “\'(\’ or \’)\’ expected”,
    – “\’=\’ expected”,
    – “Illegal command”,
    – “Syntax error”,
    – “Internal error”,
    – “Abort by [ESC]”
    + errmsg0,
    + errmsg1,
    + errmsg2,
    + errmsg3,
    + errmsg4,
    + errmsg5,
    + errmsg6,
    + errmsg7,
    + errmsg8,
    + errmsg9,
    + errmsg10,
    + errmsg11,
    + errmsg12,
    + errmsg13,
    + errmsg14,
    + errmsg15,
    + errmsg16,
    + errmsg17,
    + errmsg18,
    + errmsg19,
    + errmsg20,
    + errmsg21,
    + errmsg22,
    };

    // Error code assignment
    @@ -180,6 +203,13 @@ void c_puts(const char *s) {
    while (*s) c_putch(*s++); //終端でなければ出力して繰り返す
    }

    +void c_puts_p(const char *s) {
    + while (char c = pgm_read_byte(s)) {
    + c_putch(c); //終端でなければ出力して繰り返す
    + s++;
    + }
    +}
    +
    void c_gets() {
    char c; //文字
    unsigned char len; //文字数
    @@ -1306,7 +1336,7 @@ void error() {
    } //もし「OK」ではなかったらの末尾

    newline(); //改行
    – c_puts(errmsg[err]); //「OK」またはエラーメッセージを表示
    + c_puts_p(errmsg[err]); //「OK」またはエラーメッセージを表示
    newline(); //改行
    err = 0; //エラー番号をクリア
    }

    エラーメッセージの文字列を PROGMEM に配置するのと併せてエラー出力の関数を新設しています。
    PC にインストールしていた Arduino IDE 1.6.5 で確認をしておりますが、Arduini Uno版を素の状態でビルドしたところのメッセージが

    > スケッチが プログラムストレージ領域の 8,790バイト (27%) を使用しています。最大は 32,256バイト です。
    > グローバル変数が 1,449バイト (70%) の 動的メモリを使用しており、ローカル変数に 599 バイトが残っています。最高は 2,048バイトです。

    だったものが、上記の変更を加えると

    > スケッチが プログラムストレージ領域の 8,832バイト (27%) を使用しています。最大は 32,256バイト です。
    > グローバル変数が 1,059バイト (51%) の 動的メモリを使用しており、ローカル変数に 989 バイトが残っています。最高は 2,048バイトです。

    ローカル変数の残りが 599 → 989 バイトと増加しており、PROGMEM への文字列の配置は Arduino Uno については効果があるものと思っています。

    Palo Alto Tiny Basic と完全互換でないことは理解しております。サブルーチン内でループ処理を行い終了条件に合ったところで復帰するという処理は Palo Alto Tiny Basic に限らず普通にある処理と思うので、先のコメントを投稿させていただきました。

    以上よろしくお願いいたします。

  6. 名無し より:

    コメントの投稿が入れ違いになってしまったようです。
    RUN命令のエラー件、了解いたしました。ご確認ありがとうございました。

    • vintagechips より:

      名無しさん、1本目のパッチは非の打ちどころがありません。2本目のパッチはプラットフォームに依存しますが、Arduino版においてたいへん効果的です。これらをすっきり読める形でみなさんにご紹介したいと考え、めったにやらないことですが、私が間違った検証の結果を報告したりお互いのコメントの時差で内容が混乱したりしたところを整理いたしました。名無しさんのコメントには手を付けず、趣旨を曲げないように配慮したつもりですが、その点についてご要望がありましたら承ります。貴重な情報をいただきありがとうございました。

  7. Hiro Okuda より:

    初めまして。
    ルールに則ってご連絡します。
    今回、このBASICを大幅に拡張・改変してRaspBerry piに移植することにしました。
    (できるかどうかはわかりませんが・・・)
    よろしくお願いいたします。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中