小型インタプリタ言語 TTI

平井真二
 
 TTI(Tiny Tiny Interpreter)は,S-OS“SWORD"上で動作する1バイト型(変数は1バイト整数)の,簡易エディタつきインタプリタ言語です。エディタはZEDAライクなカーソルエディタ風ラインエディタ。開始アドレスは3A00HでTTCと共存可能です。
 文法などではTTCのものを少し改良して上位バージョンとなっています。部分的にはどうしてもインタプリタで実現できないものもありますので完全なコンパチではありません。追加された命令を使用しなければ,そのままTTCでコンパイルして高速実行てきます。
 

◆TTIの特徴

 TTCの命令を含み,以下の命令が追加されています。
1) @GOTO,@GOSUB
 飛び先は1〜255ですが,ラベルに式が使えます。
例) .A=9 @GOTO A+1
  ラベル10に分岐します。
2) PUSH,POP
3) @IF
 BASICのIFと同等てす。
例) @IF A=1 “ABCDE"
  Aが1のとき,ABCDEを表示します。
4) LOOPA,LOOPB
 これは,
   DEC A IF A#0, ラベル
   DEC B IF B#0, ラベル
(LOOPA)
(LOOPB)
をひとまとめにした命令です。動作はマシン諾のDJNZと同等で,速さを意識した命令です。TTCでコンパイルするときは上記のように展開してください。
5) 関数 (S
 SCRN$関数でカーソル位置の文字コードを値とします。
 

◆使用方法

 TTIを起動させると,タイトル表示後,プロンプト‘]'が表示され,入力待ちになります(3A03Hにジャンプすればホットスタート)。]に続いてコマンド一覧のコマンドを入力するとそのコマンドが実行されます。また,1文字以上のスペースをつけてTTIの命令を入力すると,その命令が実行されます(いわゆるBASICのダイレクトモード)。
例) ] BELL 5
  ビープ音が5回鳴ります。
 エディタを使ううえでの注意点は,
1) テキストの入力において,I(追加),B(挿入)を使い分けなければならない
2) nはラベルでなく,Tコマンドのリスト表示でエディタがつけた行番号である
3) nは省略できない
です。なお,コマンド中断はSHIFT+BREAKキーです。
 プログラムの実行はGコマンドです。また,プログラムを途中から実行するには,実行させたい場所にラベルをつけて,
  ] GOTO ラベル
とします。
 実行中エラーが出ると,エラーメッセージとエラーが出た行を表示して止まります。エラーコード表を参照して修正してください。また,SHIFT+BREAKキーを押すと,プログラムの実行を中断できます(多少止まりにくいことがあります)。
 

◆TTCとの違い

 TTIはインタプリタのため,以下の点がTTCとは違います。TTCで動かすプログラムを書くときは気をつけてください。
1) DB,DW,DM命令は使えない
2) REPEAT〜UNTILループの途中でGOTOで抜け出してはいけない
3) PUT,GET命令の扱いが違う
例) DEレジスタの値を渡して,2000HをCALLする場合。
●TTC
  PUTDE X,Y
  DB $CD,$00,$20
●TTI
  PUTDE X,Y
  CALL $20,$00
 これは,TTCがCALL命令を出力する際,A,Dレジスタを破壊するコードを出すためです。したがってAレジスタを渡す場合も同様にしなければなりません。
 参考までに,TTCでDE,Aレジスタの値を渡してマシン語ルーチンを呼び出してDE,Aレジスタの値を受ける場合は,
  PUTDE X,Y
  PUTA Z
  DB $CD,$00,$20
  GETA Z
  GETDE X,Y
の順番で書かなければなりません。
4) インタプリタのみの命令はTTIでしか使えない
 当然のことながら,コンパイルを前提としたプログラム開発を行うときには,インタプリタ専用の命令をどのように置き換えていくかということをあらかじめよく考えてから開発したほうがよいでしょう。もちろん,コンパチの部分しか使わなくともプログラムを記述できます。
 さて,気になるスピードですが,サンプルのTICBANが301行のB=0をB=4に書き換えるだけでコンパイルしなくても十分遊べるので結構速いと思います。もっとも,TTIで書いて遅ければTTCでコンパイルすればいいわけですからあまり問題ではないでしょう。
 
表1 メモリマップ
■メインメモリ  
3A00H 3DACH : テキストエディタ
3DADH 4564H : TTIインタプリタ本体
4565H 47B8H : ワークエリア
■特殊ワークエリア
0000H 1000H : ラベルテーブル
 
表2 エラーメッセージ表
・SYNTAX ERROR
 ステートメントの記述がおかしい
・ILLEGAL FUNCTION CALL
 式の記述がおかしい
・UNDEFINED LABEL
 分岐先のラベルが見あたらない
・OUT OF LABEL
 ラベルが1023を超えている
・BAD GOSUB
 GOSUBのネステイングが64重を超えた
・BAD REPEAT
 REPEATループのネステイングが16重を超えた
・BAD UNTIL
 REPEATがないのにUNTILを実行しようとした
・BAD PUSH
 データスタックがオーバーフローした
・BAD POP
 スタックが空なのにデータを取り出そうとした
 
表3 コマンド一覧
I……テキストエンドより追加入力を始める。SHIFT+BREAKキーでコマンド入力に戻る
Tn……第n行からテキストを表示する。スペースで一時停止,SHIFT+BREAKキーでコマンド入力に戻る。なお,表示後のテキストはスクリーンエディット可能
Dn……第n行を削除する
Bn……第n行からテキストの挿入を始める。SHIFT+BREAKキーでコマンド入力に戻る
Sファイル名……現在作成しているテキストファイル名でセーブする
Lファイル名……ファイル名のテキストをロードする
Z……ディレクトリを表示する
&……現在作成中のテキストを消去する
R……テキストを復活する
P……Tコマンドにおけるプリンタ出力のON/OFFを設定する デフォルトはOFF
F文字列……先頭から文字列を探し始める。スペースで一時停止,SHIFT+BREAKキーでコマンド入力に戻る
M……現在作成中のテキストの格納されているアドレスを表示する
Xアドレス……テキスト格納先鎮アドレスを指定する。デフォルトは4800番地。なお,アドレスは16進4桁で,また,初めて指定したときは必ず&を実行すること
!……S-OSに戻る
C……TTCがメモリにあれば,制御を移す
G……プログラムを実行する
V……変数リストを表示する
 

TTIリファレンス

■構文規則

●プログラム
・文法はほぼtinyBASICと同様
・ラベルは0〜1023の範囲で必要なところだけつける
・ステートメント間のセパレータはスペース
・セミコロン以下の1行は注釈とみなされる
・ステートメントと式の間はスペースで区切る
●式
・ひとつの項,もしくは複数の項を2項演算子でつないだもの
・演算はすべて符号なし8ビットで行われる。また,オーバーフローのチェックはしない
・負数は2の補数または,0-のかたちで表現する
・演算は優先順位がないので,左から順番に行われる。また,括弧を使うことはできない
●項
・定数,変数,関数
 

■定数

●10進数
・取りうる値は,0〜255。255以上の値は,256で割った余りが値となる
●16進数
・先頭に$をつけて表す。値の範囲は00H〜FFH。必ず2桁で表すこと
●文字定数
・シングルクォーテーションを先頭とする1文字のASCIIコードを値とする
 

■変数

●1文字変数
・A,B……Zの1文字で表される変数
●特殊変数
・[と]の2つ。WIND命令で表される番地をアクセスする
 

■演算子

●2項演算子
・加減乗除剰余記号,比較演算子,論理演算子がある
●加減乗除剰余記号
・それぞれ,+,-,*,/,¥である
●比較演算子
・=,#(<>のこと),>,<
・真のとき1,偽のとき0を値とする
●論理演算子
・AND,OR,XORの3種があり,それぞれ,&,;,!で表す
 

■ステートメント

●.(ピリオド)
 .変数名=式
左辺の項に右辺の式の値を代入する。BASICのLET文と同じ
●INC
 INC 1文字変数
変数の値に1を加える。機械語と同じ,キャリは立たない
●DEC
 DEC 1文字変数
変数の値に-1を加える
●ADC
 ADC 1文字変数
キャリフラグの値を加える
具体的には,
  .B=O .A=A+1 ADC B
とすると,A=255のとき,B=1となる
●GOTO
 GOTO ラベル
指定行へ分岐する。コマンドとラベルの間のスペースは1個だけ
●GOSU8
 GOSUB ラベル
サブルーチンを呼び出す
●RETURN
 RETURN
GOSUBに対応するRETURN。または,BASICのEND文
●IF
 IF 式,ラベル
式の値が0以外(要するに真)ならば,指定行へ分岐する
●REPEAT〜UNTIL
 REPEAT
 UNTIL 式
式の値が1になるまで,REPEATとUNTILのあいだのプログラムを繰り返す。なお,途中でGOTOなどで抜け出してもかまわない
●END
 END
この命令によってコンパイルを終了する
●"str"
ダブルクォーテーションで囲まれた文字列をそのまま出力する
●'ctrl'
シングルクォーテーションで図まれた文字列をコントロールコードとして出力する
  D……カーソルを下へ1文字分移動
  U……カーソルを上へ1文字分移動
  R……カーソルを右へ1文字分移動
  L……カーソルを左へ1文字分移動
  C……画面をクリア
  /……改行する
●PRT1
 PRT1 式
式の値を10進右詰め3桁で出力する
●PRT2
 PRT2 式1,式2
式1を上位バイト,式2を下位バイトとみなした2バイトの値を10進右詰め5桁で出力する
●HEX2
 HEX2 式
式の値を16進2桁で出力する
●HEX4
 HEX4 式1,式2
式1を上位バイト式2を下位バイトとみなして,16進4桁で出力する
●CHR
 CHR 式
式の値のASCIIコードを出力する
●WIDCH
 WIDCH 式
画面の桁数を指定する
●LOCATE
 LOCATE 式1,式2
式1をX座標,式2をY座標とする位置へカーソルを移動する
●BELL
 BELL 式
式の回数だけビープ音を鳴らす
●WIND1
 WIND1 式1,式2
特殊変数[がアクセスする番地を決める。式1が上位バイト,式2が下位バイトを表す
●WIND2
 WIND2 式1,式2
特殊変数]がアクセスする番地を決める。WIND1と同様
●CALL
 CALL 式1,式2
式1を上位バイト,式2を下位バイトとするアドレスの機械語サブルーチンをコールする
●PUTA
 PUTA 式
式の値をAccに与える
●GETA
 GETA 変数
Accの値を変数に与える
●PUTDE
 PUTDE 式1,式2
式1の値をDレジスタに,式2の値をEレジスタに与える
●GETDE
 GETDE 変数1,変数2
Dレジスタの値を変数1,Eレジスタの値を変数2に与える
●@GOTO
 @GOTO 式
式の値のラベルへ分岐する
●@G05UB
 @GOSUB 式
式の値のラベルのサブルーチンを呼ぶ
●@IF
 @IF 式 ステートメント
式の値が真ならば,式以降のステートメントを実行する。ふつうのBASICのIF文
●PU5H
 PUSH 式
式の値をスタックに積む
●POP
 POP 1文字変数
スタックから値を取り出す
●LOOPA
 LOOPA ラベル
変数Aの値を-1にし,その結果が0でなければラベルへ分岐する。機械語のDJNZと同様
●LOOPB
 LOOPB ラベル
変数Bの値を-1し,その結果が0でなければラベルへ分岐する。機械語のDJNZと問様
●;B
 ;B
BASICのSTOP文と同等
 

■関数

●(I
 (I
キーが押されるのを待って1文字入力し,そのASCIIコードを値とする
●(G
 (G
リアルタイムキー入力。どのキーも押されていないならば0,なにかのキーが押されていれば,そのASCIIコードを値とする
●(F
 (F
カーソルを点滅させて1文字入力する
●(R
 (R
0〜255までの乱数を返す
●(X
 (X
カーソルのX座標を値とする
●(Y
 (Y
カーソルのY座標を値とする
●%R
 式%R
式の値を1ビット分,右にずらす
●%L
 式%L
式の値を1ビット分,左にずらす
●(S
 (S
カーソル位置の文字コードを値とする
 
(C)1989 Shinji Hirai(original)
(C)1997 Junji Okazaki(edited)
(C)2024 Oh!Ishi,Nibbles Lab.(formatted)