【ITニュース解説】The Interpreter ✨
2025年09月21日に「Dev.to」が公開したITニュース「The Interpreter ✨」について初心者にもわかりやすく解説しています。
ITニュース概要
Lox言語の式を評価するInterpreterクラスを作成した。これはVisitorインターフェースを実装し、四則演算や比較など様々な種類の式を処理できる。また、Loxで発生する実行時エラーを適切に処理するためのRuntimeErrorクラスも作った。
ITニュース解説
プログラミング言語のコードを実行する仕組みの一つに「インタープリタ」がある。これは、書かれたコードを一行ずつ読み込み、その場で実行していくプログラムだ。今回のニュース記事は、まさにこのインタープリタの心臓部にあたる「Interpreterクラス」と、実行中のエラーを適切に処理する「RuntimeErrorクラス」の作成について解説している。Loxという独自のプログラミング言語のプログラムを動かすための、非常に重要な進捗報告と言えるだろう。
Loxインタープリタの「頭脳」にあたるのがこのInterpreterクラスだ。このクラスの主な役割は、Loxのソースコードが文法的に正しいか分析され(パースされ)た後に生成される「構文木」というデータの構造を読み解き、そこに書かれた命令を実際に実行することにある。記事で「Visitorインターフェース」を実装していると述べられているが、これはプログラムの「構造(式や文)」と「その構造に対する操作(評価や実行)」を分離する「Visitorパターン」という設計手法を用いていることを意味する。Interpreterクラスは、構文木の各ノード(式の部品)をまるで「訪問」するように巡回し、それぞれのノードに適切な処理を適用していくのだ。処理の開始点となるのはinterpret()メソッドで、このメソッドは与えられたLoxの式を評価し、その結果を出力したり、実行中の問題をエラーとして報告したりする。
Interpreterクラスには、visitBinaryExpr()やvisitUnaryExpr()、visitLiteralExpr()といった、さまざまな種類の式に対応するメソッド群が定義されている。これらは、構文木の中から特定の種類(例えば、二項演算)の式を見つけ出すたびに呼び出される。これらのメソッドの役割は、構文木の各ノードから「値」を抽出し、そのノードが表現する式の「結果」を計算して返すことだ。例えば、数値リテラルのノードであればその数値を、文字列リテラルのノードであればその文字列をそのまま返すといった具合だ。
特に複雑なのはvisitBinaryExpr()メソッドで、「1 + 2」や「x > y」のように二つの値(オペランド)の間に演算子(オペレータ)がある式を評価する。このメソッドはまず、左右それぞれのオペランドを再帰的にevaluate()メソッドを使って評価し、それぞれの値をオブジェクトとして取得する。次に、中央の演算子の種類に応じて処理を分岐する。
例えば、比較演算子(大なり>、大なりイコール>=、小なり<、小なりイコール<=) の場合は、左右のオペランドが数値であることを確認し、その大小関係に基づいて真偽値(trueまたはfalse)を返す。算術演算子(マイナス-、アスタリスク*、スラッシュ/) も同様に左右のオペランドが数値であることを確認し、引き算、掛け算、割り算を実行してその結果の数値を返す。
+演算子の場合、これは少し特殊な振る舞いをする。左右のオペランドが両方とも数値であれば足し算を行い、両方とも文字列であれば文字列の連結を行う。もし、片方が数値で片方が文字列といった不適切な組み合わせであれば、「Operands must be two numbers or two strings.」という実行時エラーを発生させる。これは、プログラミング言語が異なるデータ型に対して同じ演算子をどう扱うか、という型の柔軟性(あるいは厳密性)を示す良い例だ。
等価演算子(等しい==、等しくない!=) の場合は、isEqual()というヘルパー関数を使って左右のオペランドが等しいかどうかを判断し、その真偽値を返す。
このように、visitBinaryExpr()メソッドは、演算子の種類に応じた複雑なロジックを、適切な型チェック(checkNumberOperands()などのヘルパー関数も活用して)とエラー処理を伴って実行している。これらのヘルパー関数は、共通の処理をまとめ、コードを読みやすく、保守しやすくするのに役立っている。
プログラムを実行していると、文法は正しくても、実行時に不適切な操作が行われることでエラーが発生することがある。例えば、存在しない変数を使おうとしたり、数値をゼロで割ろうとしたりする場合などだ。Loxインタープリタでは、このような「実行時エラー」を適切に処理するためにRuntimeErrorクラスが作成された。このクラスは、Javaの標準的なエラー処理機構であるRuntimeExceptionを継承しており、Javaのエラーメッセージをそのまま表示するのではなく、Lox言語の利用者にとってより分かりやすい形でエラーを報告できるようにしている。具体的には、Loxコード内でエラーが発生したときに、インタープリタはRuntimeErrorオブジェクトを生成し、エラーメッセージとエラーが発生したコードの行番号などの情報を含めてユーザーに表示する。これにより、プログラマはLoxのプログラムのどこで、どのような問題が発生したのかを正確に把握し、修正できる。
今回解説した内容は主に「式」の評価に関するものだったが、プログラミング言語は「文」(変数定義、条件分岐、ループなど)が組み合わさって構成される。ニュース記事の「What's next」に書かれている通り、次のステップでは、これらの「文」を評価・実行できるようにインタープリタを拡張していくことになるだろう。