[インデックス 1833] ファイルの概要
このコミットは、Go言語の初期開発段階における言語仕様の変更を記録しています。具体的には、Go言語の文法定義において、「ラベル付きステートメント」の扱いをより明確かつ構造的に変更したものです。この変更は、Go言語の文法規則を整理し、将来的な拡張性や可読性を向上させることを目的としています。
コミット
commit dea4394a674c9b7868eb06b2325fc17a909c3064
Author: Robert Griesemer <gri@golang.org>
Date: Mon Mar 16 17:36:52 2009 -0700
instead of unlabeled statements, have a single labeled statement
- no syntactic or semantic change
R=r
DELTA=45 (24 added, 18 deleted, 3 changed)
OCL=26349
CL=26368
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/dea4394a674c9b7868eb06b2325fc17a909c3064
元コミット内容
コミットメッセージは「instead of unlabeled statements, have a single labeled statement - no syntactic or semantic change」と簡潔に述べられています。これは、「ラベルなしステートメントの代わりに、単一のラベル付きステートメントを持つようにする」という意味であり、この変更が構文的または意味的な影響を伴わないことを強調しています。つまり、既存のGoコードの動作に影響を与えることなく、言語仕様の内部的な定義を整理したものです。
変更の背景
このコミットは2009年3月に行われており、Go言語がまだ活発に開発され、その言語仕様が固まりつつあった非常に初期の段階に位置します。当時のGo言語の設計者たちは、言語の構文規則をより明確で、一貫性があり、理解しやすいものにするために、継続的に仕様を洗練させていました。
この特定の変更の背景には、おそらく以下のような意図があったと考えられます。
- 文法規則の明確化と単純化: 以前の定義では、
Statement
がLabel ":" UnlabeledStatement
という形式で定義されており、ラベルが「ラベルなしステートメント」に付与されるという、やや回りくどい表現になっていました。これをLabeledStat
という独立したプロダクションとして定義することで、文法規則がより直接的で理解しやすくなります。 - 構文解析の効率化: コンパイラやツールがGoコードを構文解析する際、明確に定義された文法規則は解析プロセスの効率と正確性を向上させます。
LabeledStat
を独立させることで、パーサーがラベル付きステートメントを認識しやすくなった可能性があります。 - 将来の拡張性: 整理された文法は、将来的に言語に新しい機能や構文を追加する際の基盤としてより堅牢です。
この変更は、Go言語の設計哲学である「シンプルさ」と「明確さ」を追求する一環として行われたものと解釈できます。
前提知識の解説
このコミットの技術的詳細を理解するためには、以下の概念についての前提知識が必要です。
- プログラミング言語の文法 (Grammar): プログラミング言語の構文規則を定義する形式的なシステムです。通常、バッカス・ナウア記法 (BNF) やその拡張である拡張バッカス・ナウア記法 (EBNF) などで記述されます。Go言語の仕様もEBNFに似た形式で記述されています。
- プロダクション (Production Rule): 文法規則の個々の定義です。例えば、
A = B C
は「AはBの後にCが続く」という規則を示します。 - 非終端記号 (Non-terminal Symbol): 文法規則の左辺に現れる記号で、さらに別の規則によって展開される記号です。例:
Statement
,Expression
。 - 終端記号 (Terminal Symbol): 文法規則の右辺にのみ現れる記号で、それ以上展開されない、言語の基本的な要素です。例:
identifier
,":"
,if
,for
。
- プロダクション (Production Rule): 文法規則の個々の定義です。例えば、
- ステートメント (Statement): プログラムの実行可能な最小単位です。変数宣言、代入、条件分岐、ループなどがステートメントに該当します。
- ラベル (Label): プログラム内の特定のステートメントに名前を付ける識別子です。Go言語では、
goto
、break
、continue
ステートメントのターゲットとして使用されます。goto
ステートメント: プログラムの実行フローを、指定されたラベルを持つステートメントに無条件にジャンプさせます。break
ステートメント: ループやswitch
、select
ステートメントから抜け出すために使用されます。ラベルを指定することで、ネストされたループの外側のループから抜け出すことができます。continue
ステートメント: ループの現在のイテレーションをスキップし、次のイテレーションに進みます。ラベルを指定することで、ネストされたループの外側のループの次のイテレーションに進むことができます。
- Go言語仕様 (Go Language Specification): Go言語の構文、セマンティクス、標準ライブラリの動作などを定義する公式文書です。このコミットで変更されている
doc/go_spec.html
は、この仕様の一部です。
技術的詳細
このコミットの核心は、Go言語仕様のdoc/go_spec.html
ファイルにおける「Statements」セクションの文法定義の変更です。
変更前と変更後の文法定義を比較することで、その意図が明確になります。
変更前 (--- a/doc/go_spec.html
):
<pre class="grammar">
-Statement = { Label ":" } UnlabeledStatement .
-Label = identifier .
-UnlabeledStatement =
- Declaration | EmptyStat |
+Statement =
+ Declaration | EmptyStat | LabeledStat |
SimpleStat | GoStat | ReturnStat | BreakStat | ContinueStat | GotoStat |
FallthroughStat | Block | IfStat | SwitchStat | SelectStat | ForStat |
DeferStat .
-SimpleStat =
- ExpressionStat | IncDecStat | Assignment | SimpleVarDecl .
+SimpleStat = ExpressionStat | IncDecStat | Assignment | SimpleVarDecl .
変更前は、Statement
が{ Label ":" } UnlabeledStatement
として定義されていました。これは、「任意の数のラベルとコロンのペアの後に、ラベルなしステートメントが続く」という意味です。UnlabeledStatement
は、宣言、空ステートメント、単純ステートメントなど、様々な種類のステートメントの集合でした。この定義では、ラベルはUnlabeledStatement
に付与されるものとして扱われていました。
変更後 (+++ b/doc/go_spec.html
):
<pre class="grammar">
+Statement =
+ Declaration | EmptyStat | LabeledStat |
SimpleStat | GoStat | ReturnStat | BreakStat | ContinueStat | GotoStat |
FallthroughStat | Block | IfStat | SwitchStat | SelectStat | ForStat |
DeferStat .
+<h3>Labeled statements</h3>
+
+<p>
+A labeled statement may be the target of a <code>goto</code>,
+<code>break</code> or <code>continue</code> statement.
+</p>
+
+<pre class="grammar">
+LabeledStat = Label ":" Statement .
+Label = identifier .
+</pre>
変更後、Statement
の定義から{ Label ":" }
が削除され、代わりにLabeledStat
という新しい非終端記号がStatement
の選択肢の一つとして追加されました。そして、LabeledStat
がLabel ":" Statement
として独立して定義されました。
この変更により、以下の点が明確になりました。
LabeledStat
の独立: ラベル付きステートメントが、他の種類のステートメント(宣言、空ステートメントなど)と同列の、独立したステートメントのカテゴリとして扱われるようになりました。- 再帰的な定義:
LabeledStat = Label ":" Statement .
という定義は、ラベルの後に続くStatement
自体が、さらにラベル付きステートメントである可能性を許容します。これにより、label1: label2: someStatement
のような多重ラベルの構文が自然に表現されます。 - 文法の簡潔性:
Statement
の定義がより簡潔になり、ラベルの概念がLabeledStat
にカプセル化されました。
コミットメッセージにある「no syntactic or semantic change」という記述は、この文法変更がGo言語の既存のコードの構文解析結果や実行時の動作に影響を与えないことを意味します。これは、変更前の文法定義が実質的にLabeledStat
の概念を内包していたため、その表現方法をより明示的かつ構造的にしたに過ぎないからです。
コアとなるコードの変更箇所
このコミットで変更されたファイルはdoc/go_spec.html
のみです。
具体的には、以下の部分が変更されています。
Statement
プロダクションの変更:- 削除:
<pre class="grammar">Statement = { Label ":" } UnlabeledStatement .
- 追加:
<pre class="grammar">Statement = Declaration | EmptyStat | LabeledStat | ...
- 削除:
UnlabeledStatement
プロダクションの削除:UnlabeledStatement
の定義自体が不要になったため、関連する行が削除されました。
LabeledStat
プロダクションの新規追加:<h3>Labeled statements</h3>
という新しいセクションが追加され、その中に以下の文法定義が記述されました。<pre class="grammar"> LabeledStat = Label ":" Statement . Label = identifier . </pre>
SimpleStat
プロダクションの変更:- これは直接的な変更ではなく、
UnlabeledStatement
の削除に伴い、SimpleStat
の定義がより簡潔に一行で表現されるようになりました。
- これは直接的な変更ではなく、
コアとなるコードの解説
変更の核心は、Go言語の文法定義におけるStatement
の構造化です。
変更前は、Statement
が以下のように定義されていました。
Statement = { Label ":" } UnlabeledStatement .
これは、「ステートメントは、0個以上のLabel ":"
のペアの後にUnlabeledStatement
が続くもの」と解釈できます。UnlabeledStatement
は、ラベルが付かない可能性のある様々な種類のステートメント(例: Declaration
, EmptyStat
, SimpleStat
など)を指していました。この定義は、ラベルが任意のステートメントに付与されうることを表現していましたが、LabeledStat
という明確なカテゴリが存在しないため、概念的にやや曖昧でした。
変更後は、Statement
の定義が以下のように変わりました。
Statement = Declaration | EmptyStat | LabeledStat | SimpleStat | ...
そして、LabeledStat
が新たに定義されました。
LabeledStat = Label ":" Statement .
Label = identifier .
この新しい定義は、LabeledStat
がStatement
の一種であることを明確に示しています。LabeledStat
自体は、Label
とコロンの後に、任意のStatement
が続くものとして定義されます。このStatement
は、さらにLabeledStat
である可能性もあるため、label1: label2: someCode
のような多重ラベルの構文もこの定義で自然に表現されます。
この変更は、Go言語の文法をより形式的に正確にし、構文解析器の実装を容易にするための、内部的な改善と見なすことができます。ユーザーがGoコードを書く上での構文やセマンティクスには影響を与えませんが、言語仕様の基盤をより堅牢なものにしました。
関連リンク
- Go言語の公式ウェブサイト: https://golang.org/
- Go言語仕様 (現在のバージョン): https://golang.org/ref/spec
- 現在のGo言語仕様における「Statements」のセクションを参照すると、このコミットで導入された
LabeledStmt
の概念がどのように発展し、現在の形になっているかを確認できます。
- 現在のGo言語仕様における「Statements」のセクションを参照すると、このコミットで導入された
参考にした情報源リンク
- Go言語の公式ドキュメントと仕様書
- Go言語のGitHubリポジトリのコミット履歴
- プログラミング言語の文法に関する一般的な知識(BNF, EBNFなど)