エラーの整備

現状はエラー時に fprintf で stderr にごにょっとメッセージを出して return NULL; みたいなありえないことをやっている。


そのせいでたまにセグフォするという極悪仕様なのだけれども、これをまともにするのが今日の作業。

実現したいこと

  • 大域脱出してシンプルなエラー処理
  • エラーになった行番号を出す
  • デバッグ用に、エラーになった C++ソースコードの行番号を出す
  • not reached 最適化
  • 可変個数の引数でエラーメッセージを指定できるように
  • C++の例外を使わず
  • Error::raise() みたいな感じ。

実装

  • setjmp/longjmp で大域脱出
  • Errorクラスでsetjmp/longjmp を隠蔽
  • 行番号は Token -> Node -> Object で引き継いで保持する
  • C++ソースコード行番号はError::raise をマクロRAISE_ERROR でラップしたときに付加

使いかた

エラーを返す。

RAISE_ERROR(variable->lineno(), "unbound variable [%s]", variable->toString().c_str());


マクロで以下のように展開されます。

#define RAISE_ERROR(lineno, ...)                                     \
    Error::raise(lineno, __FILE__, __LINE__, __func__, __VA_ARGS__); \
    /* NOTREACHED */


/* NOTREACHED */は最適化されると良いな的おまじない。


実際に実行すると以下のように出力されます。

nobita% ./src/scheme ./test/test.scm
./test/test.scm:172: error: unbound variable [variable: total-reportssss]
Environment.cpp:86: debug: lookupVariableValue

./test/test.scm:172: error: invalid application [string: "hoge"]
Application.cpp:30: debug: eval


全部思いどおり行ったので、珍しく短い(?)時間で実装できたな。90分くらい?