MachiKania が動き出したので、BASIC の仕様をちょっと調べてみた。マニュアルが公開されているのだけど、細かいところがよくわからなかったんです。
同一名の変数はメモリ領域を共有している。つまり、変数には実は型の概念はなく、同じ 32 ビットデータを整数/単精度実数/文字列(のアドレス)としてそれぞれ解釈している。
A#=1:PRINT A
-->1065353216 ($3F800000 = 1.0 as binary 32)
A$="ABCDE":PRINT A
-->-1610603508 ($A000240C は文字列のアドレス)
A#=1:PRINT A$
-->Exception ($3F800000 を文字列アドレスとして解釈)
整数型変数が正しいメモリアドレスを指している場合、それに (式)
をつけると「整数型変数へのポインタ」としてメモリ内容にアクセスすることができる。書き込みも可能。このへんは、Tiny BASIC 系の雰囲気がある。正式に仕様としては公開されていないが、便利に使えそう。
A$="ABCDE":A(0)=$50515253:PRINT A$
-->SRQPE (最初の4バイトが置き換わった)
もちろん PEEK()
関数、POKE
文を使えば1バイト単位の読み書きが可能。
A$="ABCDE":POKE A,$53:PRINT A$
-->SBCDE (最初の1バイトが置き換わった)
POKE A+2,$51:PRINT A$
-->SBQDE (さらに3バイト目が置き換わった)
MachiKania の配列については、BASIC コンパイラ作者の Katsume さんが「MachiKania type Z で使われている多次元配列の実装について」という解説を書いておられる。それによると、A(x,y,z)
という配列の場合、A
, A(x)
, A(x,y)
のそれぞれにポインタを格納しておいて、添字が1つ増えるごとに次のポインタを参照する仕組みになっている。この実装から想像できる通り、MachiKania の配列は実質的にはメモリアドレスへのポインタとなっている。
DIM A(1):PRINT A
-->-1610603420 ($A0002464)
POKE A,$FF:PRINT A(0)
-->255 (最下位バイトが 0xFF になった)
PRINT A(2) (範囲外の添字)
-->3487026 (無意味な値が入っている)
文字列の実装がどうなっているのか興味がある。コンパイラのソースコードを見たところ、「一時的に使う文字列」へのポインタを保持する領域が用意されており、BASIC の1行分を実行するごとにこの領域をクリアしているらしい。あちこちに PIC32 のアセンブラが使ってあって、完全には読めていない。