0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FORTH ベーシックマスター Lev 10 ー gforthのデバッグ術と辞書探索

0
Last updated at Posted at 2025-12-06

はじめに ― デバッグとは“対話”である

FORTHにおけるデバッグとは、外部ツールを用いることではなく、言語自身に質問する行為 である。C言語やPythonのようにデバッガを起動してステップ実行するのではなく、gforthでは「実行系がすべて露出している」ため、コンパイル状態・辞書・スタックの中身などを、即座にその場で観察できる。

FORTHの哲学では、「プログラム=ワードの集積」であり、「デバッグ=ワードの分解観察」である。したがって、gforthでは“止めて覗く”よりも、“動かしながら覗く”ことが重要になる。

スタック観察 ― .S の基本

デバッグの第一歩は、スタックの状態を知ること である。gforthでは、.S(ドット・エス)を入力するだけで、現在のスタックの内容が表示される。

入力
1 2 3 .S
出力
<3> 1 2 3

ここで <3> は、スタックに3つの項目があることを示している。FORTHでは、ワードの入出力をスタック図で表す習慣があるため、.S はその確認に必須である。

スタック図の読み方再確認

DUP   ( n -- n n )
DROP  ( n -- )
+     ( n1 n2 -- n3 )

上記のように、「入力 → 出力」の順でスタックの変化を記す。.S はこの図を実行後の確認として照らし合わせる役割を果たす。

定義内容の表示 ― SEE ワード

次に、定義済みワードの中身を覗く方法を学ぶ。gforthには SEE というワードがあり、コンパイル済みのワードの内容(内部命令列)を表示してくれる。

入力
: SQUARE ( n -- n^2 ) DUP * ;
SEE SQUARE
出力
: SQUARE
  DUP *
;

このように、SEE はワードが colon 定義(: ... ;)である場合、実際の展開後の形を人間が読める形で出力する。CREATEVARIABLE で定義されたワードも、その構造に応じて内容を表示する。

: SQUARE ( n -- n^2 ) DUP * ;
: SQUARE ( n -- n^2 ) DUP DUP * * ;
SEE SQUARE

このように再定義しても、辞書には新しい定義が追加され、古い定義は参照されなくなる。SEE は常に「最新の定義」を表示する。

SEE IF
SEE LOOP

これらを実行してみると、制御構造も単なるワードとして辞書に登録されていることが分かる。この“可視化されたコンパイラ”という構造が、FORTHを単なるプログラミング言語ではなく、言語実験のための実験装置 として際立たせている。

組込みワード(ネイティブコード)に対して SEE を実行した場合は、機械語レベルまたは内部ラベルの一覧として表示される。SEE はコンパイラが生成したスレッド化コードを解析しているため、他のForth実装とは若干異なる出力になることがある。

辞書の探索 ― WORDSFIND-NAME

FORTHの辞書は、「ワード名」「リンク」「実行アドレス」のリストで構成されている。この構造を覗く代表的なワードが WORDS である。

入力
WORDS
出力
DROP DUP SWAP OVER ROT ... SQUARE ...

これは辞書に登録されているワードの一覧を、最新定義から順に表示している(つまり、再定義されたワードは常に前に現れる)

FORTHの辞書は、各ワードの「名前フィールド(Name Field)」を鎖のように連結した構造になっている。gforthでは、この辞書を直接探索するために FIND-NAME という低レベルワードが用意されている。

使用例:ワード名を検索する
s" DUP" find-name .s
出力例
<1> 7FFFB420E1C8

見つかった場合は、そのワードの「名前トークン(nt)」がスタックに残る。見つからなければ 0 が返される。

このntは、ワードのメタ情報を参照するためのハンドルであり、ここから実行トークンや名前文字列を取り出すことができる。

名前トークンから実行トークンを得る

NAME>INTを使うことで、名前トークンから実行トークン(xt)を取得できる。

入力
s" DUP" FIND-NAME NAME>INT .S
出力例
<1> 7FFFB420E120

このxtは、' DUPで得られるものと同一である。つまり、FIND-NAMENAME>INTを組み合わせれば、'と同様にワードを動的に取得できる。

名前を文字列として取得する

辞書内の名前を再び文字列として確認するには、NAME>STRINGを用いる。

入力
s" DUP" FIND-NAME NAME>STRING TYPE
出力
DUP

これにより、辞書から取得したトークンが確かに指定したワードであることを確認できる。NAME>STRING( nt -- c-addr u )を返すため、TYPEで直接表示できる。

実行モードとコンパイルモード ― STATE の確認

gforthには二つのモードがある:

  • インタプリタモード:その場でワードを実行する。
  • コンパイルモード:新しいワード定義の中で命令を辞書に記録する。

STATEは、どちらの状態にあるかを確認することが出来る。

: .STATE ( -- )
  STATE @ IF
    ." (Compiling...) "
  ELSE
    ." (Interpreting...) "
  THEN
;

\ このワードがコンパイル中にも実行されるよう IMMEDIATE に設定
IMMEDIATE

.STATEは、インタプリタモードとコンパイルモードでは違う動作を行う。

入力
.STATE
出力
(Interpreting...)

以下のようなワード定義を行うと、

: TEST .STATE 10 20 + ;

コンパイルされる時、(Compiling...)が表示され、「いまコンパイル中かどうか」をプログラム内で動的に判断できる。

デバッグの実践例 ― 動作を観察しながら修正する

以下は、意図的にバグを含んだ単純なプログラムの例である。

: SUM3 ( a b c -- sum )
   + ;

これを 3 4 5 SUM3 . と実行しても、正しい答えが得られない。原因は、3つの引数に対して加算が1回しか行われていないことだ。

3 4 5 SUM3 .S

でスタックを確認すれば <2> 3 9 が表示され、加算が1回しか行われなかったことが分かる。

修正版:

修正版
: SUM3 ( a b c -- sum ) + + ;

このように、スタック操作を逐次観察しながら修正していくのがFORTH流のデバッグである。

LOCATE ― ソースコード中の定義箇所を特定

構文
LOCATE name

name がどのファイルのどの行で定義されているかを表示する。gforthはソースファイルを読み込む際、内部的に「定義位置情報」を保持しているため、LOCATE によって定義元のファイル名と行番号を調べることができる。

私が使用しているSUMというワードで実行してみた。

LOCATE SUM
出力例
~/.config/gforthrc:0
: sum
  begin depth 1 > while
    +
  repeat ;

: fsum
  begin fdepth 1 > while
    f+
  repeat ;

: clear
  begin depth 0> while

自分で定義したワードに対しても、ソースファイルを INCLUDE 経由で読み込んでいれば、正しい位置情報が出力される。対話的に定義したワード(REPL上で入力したもの)は、一般に「no file information」として扱われる。

WHERE ― ワードが存在する場所を一覧表示

構文
WHERE name

name が複数の辞書(語彙空間)に存在する場合、そのすべての定義位置を一覧表示する。特に、同名ワードが異なるモジュールで再定義されているときに有用である。

WHERE TYPE
出力例
kernel/io.fs:139:13: newline type 0 out ! ; 0
kernel/io.fs:255:45: swap  0 max 0 ?DO  delta-I &80 min 2dup type  +LOOP  drop ; 1
kernel/nio.fs:103:19: over - spaces type ; 2
....

このように、複数のソースで使われている場合、全ての使用場所を一覧として示す。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?