見出し画像

BASICはどのように動いているのか

BASICという言語は基本的にインタプリタとして実装されることが殆どです。マイコンが箱に入って予めBASICインタプリタを搭載したパソコンとして売られるまでは、マイコンを組めば、まずモニタというかファームを入れる必要があるのですが、いちいちマシン語でプログラムを組むのも大変ですし、出回っているゲームなんかをやりたければBASIC「を」書いて使えるようにするのが目標でした。

インタプリタに限らず言語処理系というのは、基本的にソースコードの構文解析をして、コンピュータが理解できる形式に変換して、必要であれば順序を入れ替えるなどして最終的に実行するわけです。このあたりは lex と yacc について書いてあるドキュメントを探せば、良い解説があると思うのですが、これを理解するには文字列のパースから始まって名前の管理であるとか木構造などを覚える必要があって、スタックなんていう概念も使いこなす必要があります。

BASIC

初期のBASICインタプリタは、キーボードから入力した文字列をリターンキーを押すたびに解釈し構文チェックなどをするものの、それをプログラムとしてそのままメモリに格納していました。これが一番シンプルなのですが、実行時に再び構文解析を行う必要があります。そこで入力された内容を、まず解釈してから、その結果そのままではなく、コード化してメモリに格納するように進化しました。PRINTなどの命令文を文字列ではなく特別に割り当てられたコードに置き換えてメモリにしまうのです。もちろんLISTを実行してプログラムを表示するときには、このコードを元の文字列に直して表示してくれるのです。このコードを中間言語と呼ぶことがあります。

中間言語(中間表現)という言葉は、このBASICの例以外にも多くの使われ方をしているのですが、Javaのバイトコードやpythonの.pycも仲間といえば仲間です。

中間表現

もちろん行番号も2進数にコード化されます。リテラルの解釈をどうするかは処理系によって異なるのですが、これも2進数に変換しておくのが一般的です。この解釈がはいるので、入力した内容と表示される内容に微妙な違いが出ます。例えば小文字で入力した文字が大文字になったり、余分な空白が付いたり無くなったり、倍精度浮動小数点の数値を入れれば後ろに#が付いたりします。この時に余分な空白が保存されるかどうかは処理系依存なんですよね。

GOTOであるとかGOSUBなどに続く行番号は、解釈の時点では行番号を2進数に変換したものが使われるのですが、これだと実行時に飛び先を都度、検索しなければなりません。解釈の時点ではその行番号が実際にはメモリの中のどこにあるのかは決まらないので仕方が無いのですが、ループなどで繰り返し飛ぶのであれば効率の悪いことになります。そこで実行を開始してからGOTOなどを実行して飛び先を検索した後に、次からは検索しなくても良いように、行番号ではなく飛び先のメモリアドレスに置き換えるなんていうことをしています(この時に中間コードの値も変更する)。

この機能が実装される前に書かれたコードは、頻繁に呼ばれるサブルーチンなどのコードは検索で時間がかからないように若い番号にするなんていう読みにくさを助長するテクニックがバッコしていました。普通に考えればサブルーチンは後ろの方に置きたいのですが、それを前に持ってきて最初の行でいきなりGOTO 10000とかしていたわけです。まあPASCALなんかもmainを最後にする必要があるので、別にどちらでも構わないのですけどね。

N系BASICの中間言語仕様

https://www.antun.net/tips/p2v/nBasic.html

BASICはインタプリタなので、FOR文とNEXT文が必ずしも1対1になっている必要はなく、どこにNEXTがあろうと最後に実行した、対応するFORのところに戻るわけです。ですから想定外のループが発生したりしてバグの温床であるには違いありませんし、コンパイラなんかを作ろうとすると大変になるところです。

プログラムを保存するときには、この変換された状態のデータが保存されます。ですから他の機種で読み込むと中間コードが違うので動作しなくなるのですね。最初は自力で変換プログラムを書いていたのですが、いつの間にかアスキーセーブというオプションが使えるようになり、この場合は中間コードがLISTで表示されるようなテキストになって保存されるので、そのまま動くかは別にして異なる機種でも読めるようになりました。

3章 BASICの内部構造 - MSX

http://ngs.no.coocan.jp/doc/wiki.cgi/TechHan?page=3%BE%CF+BASIC%A4%CE%C6%E2%C9%F4%B9%BD%C2%A4

このように内部処理を考えれば、BASICごとの微妙な差異も怪しいところが見えるようになるのですが、リファレンスとなるものが実装自身しかなかったので、新しいBASICが出るたびに機能追加や高速化のために実に微妙な非互換性が発生し、移植する際には苦労しました。まあ少なくともマイクロソフト製に関しては、内部構造はそんなに違うものではありませんでしたが。

昔はそれこそアセンブラでセッセとインタプリタを書いていたのですが、今は強力な高級言語が使えるので、試しにインタプリタを書いてみると良い勉強にはなると思います。なにせ仕様がコンパクトなんで、わりとアッサリ書けるものです。

397 行で tiny basic のインタプリタを作る

Natural Tiny Basic (NT-Basic)

#プログラミング言語 #インタプリタ #BASIC #中間コード  


この記事が気に入ったらサポートをしてみませんか?