Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 185] ファイルの概要

このコミットは、Go言語の初期開発段階におけるバグ修正に関連するテストケースの追加です。具体的には、lenという識別子がキーワードとして誤って扱われ、変数名として使用できないというコンパイラのバグを検出するためのテストが追加されました。

コミット

commit 9615542d102516a70717bdcc08cb563a9644dbfd
Author: Robert Griesemer <gri@golang.org>
Date:   Tue Jun 17 16:22:02 2008 -0700

    - added another bug test ('len' shouldn't be a keyword)
    
    SVN=123225

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/9615542d102516a70717bdcc08cb563a9644dbfd

元コミット内容

- added another bug test ('len' shouldn't be a keyword)

変更の背景

Go言語の初期開発において、コンパイラがlenという組み込み関数名を誤って予約語(キーワード)として扱っていたというバグが存在していました。これにより、開発者はプログラム内でlenという名前の変数を宣言しようとすると、コンパイルエラーに直面していました。

このコミットは、この特定のバグを明確に浮き彫りにし、将来的な回帰を防ぐためのテストケースを追加することを目的としています。テスト駆動開発の原則に従い、バグが修正される前に、まずバグを再現するテストを作成するというアプローチが取られています。

前提知識の解説

Go言語のキーワードと組み込み関数

Go言語には、言語の構文を定義するために予約されている「キーワード(Keywords)」と、言語に標準で組み込まれているが予約語ではない「組み込み関数(Built-in Functions)」が存在します。

  • キーワード: func, var, if, for, package, importなどがこれにあたります。これらは言語の構文要素であり、変数名や関数名として使用することはできません。コンパイラはこれらのキーワードを特別に解釈し、プログラムの構造を理解します。
  • 組み込み関数: len, cap, make, new, append, print, printlnなどがこれにあたります。これらはGo言語の標準ライブラリの一部として提供される関数であり、特別なインポートなしに利用できます。しかし、これらはキーワードではないため、理論的には変数名や他の識別子として使用することが可能です(ただし、コードの可読性や意図しないシャドーイングを避けるため、通常は推奨されません)。

このコミットの背景にある問題は、コンパイラがlenを組み込み関数ではなく、キーワードとして誤って認識していた点にあります。

コンパイラの字句解析と構文解析

コンパイラは、ソースコードを機械が理解できる形式に変換するソフトウェアです。このプロセスには主に以下の段階があります。

  1. 字句解析(Lexical Analysis / Scanning): ソースコードを読み込み、意味のある最小単位(トークン)に分割します。例えば、var len int;というコードは、var(キーワード)、len(識別子)、int(識別子)、;(区切り文字)といったトークンに分割されます。この段階で、各トークンがキーワードなのか、識別子なのか、演算子なのかなどが識別されます。
  2. 構文解析(Syntactic Analysis / Parsing): 字句解析で生成されたトークンの並びが、言語の文法規則(構文)に合致しているかを検証し、抽象構文木(AST)を構築します。この段階で、例えば「キーワードの後に識別子が来るべき」といった文法的なルールが適用されます。

このバグは、字句解析の段階でlenが誤ってキーワードとして分類されていたか、あるいは構文解析の段階でlenが識別子として許容されるべき場所でキーワードとして扱われていた可能性を示唆しています。

テスト駆動開発 (TDD) とバグテスト

テスト駆動開発(Test-Driven Development, TDD)は、ソフトウェア開発手法の一つで、機能の実装よりも先にテストコードを書くことを特徴とします。バグ修正においても同様に、まずバグを再現するテストケース(バグテスト)を作成し、そのテストが失敗することを確認します。その後、バグを修正し、テストが成功することを確認することで、修正が正しく行われたことを保証し、将来的な回帰を防ぎます。

このコミットは、まさにこのバグテストの追加というTDDの原則に則ったものです。

技術的詳細

このコミットは、Goコンパイラがlenをキーワードとして誤認識していたバグを露呈させるためのテストケースtest/bugs/bug053.goを追加しています。

test/bugs/bug053.goの内容は以下の通りです。

// $G $D/$F.go && $L $F.$A && ./$A.out

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

func main() {
  var len int;  // len should not be a keyword - this doesn't compile
}

このテストコードの核心は、var len int;という行です。Go言語の設計上、lenは組み込み関数であり、キーワードではありません。したがって、この行はlenという名前の整数型変数を宣言しようとしており、本来であれば正しくコンパイルされるべきです。しかし、当時のコンパイラはlenをキーワードと誤解していたため、この宣言を構文エラーとして拒否していました。

コメントにある// len should not be a keyword - this doesn't compileは、このテストが意図的にコンパイルエラーを引き起こすことを期待していることを示しています。これは、バグが修正される前の状態を捕捉するための「失敗するテスト」として機能します。バグが修正された後には、このテストは成功(つまり、var len int;がコンパイル可能になる)するようになります。

また、test/golden.outファイルも更新されています。このファイルは、Goコンパイラのテストスイートにおいて、特定のテストケースを実行した際の期待される出力(エラーメッセージなど)を記録する役割を担っています。bug053.goが追加されたことで、このテストが引き起こすコンパイルエラーメッセージがgolden.outに追記され、テストシステムがそのエラーを期待する出力として認識するように設定されました。

追加されたgolden.outのエントリは以下の通りです。

=========== bugs/bug053.go
bugs/bug053.go:6: syntax error
BUG: len should not be a keyword

これは、bug053.goの6行目で構文エラーが発生し、そのエラーが「lenはキーワードであるべきではない」というバグに関連していることを示しています。

コアとなるコードの変更箇所

このコミットにおけるコアとなるコードの変更は、以下の2つのファイルに集中しています。

  1. test/bugs/bug053.go: 新規追加されたテストファイル。

    --- /dev/null
    +++ test/bugs/bug053.go
    @@ -0,0 +1,11 @@
    +// $G $D/$F.go && $L $F.$A && ./$A.out
    +//
    +// Copyright 2009 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +//
    +package main
    +//
    +func main() {
    +  var len int;  // len should not be a keyword - this doesn't compile
    +}
    
  2. test/golden.out: テストの期待される出力を記録するファイル。

    --- a/test/golden.out
    +++ b/test/golden.out
    @@ -267,6 +267,10 @@ BUG: infinite loop in error reporting
     =========== bugs/bug052.go
     BUG: incorrect code for division
     
    +=========== bugs/bug053.go
    +bugs/bug053.go:6: syntax error
    +BUG: len should not be a keyword
    +
     =========== fixedbugs/bug000.go
     
     =========== fixedbugs/bug001.go
    

コアとなるコードの解説

test/bugs/bug053.go

このファイルは、Go言語のテストスイートにおける「バグテスト」のカテゴリに属します。ファイル名のbug053.goは、これが53番目のバグテストであることを示唆しています。

  • // $G $D/$F.go && $L $F.$A && ./$A.out: これはテストハーネス(テスト実行システム)に対する指示であり、Goコンパイラ($G)でこのファイルをコンパイルし、リンカ($L)で実行可能ファイルを生成し、その実行可能ファイル(./$A.out)を実行することを意味します。このテストは、コンパイル段階でエラーが発生することを期待しているため、実行可能ファイルの生成や実行は、コンパイルエラーが発生しない場合にのみ行われます。
  • package mainfunc main() {}: 標準的なGoプログラムのエントリポイントです。
  • var len int;: この行がテストの核心です。lenという名前のint型変数を宣言しようとしています。当時のコンパイラがlenをキーワードと誤認識していたため、この行でコンパイルエラーが発生していました。このテストは、このエラーを捕捉し、将来的にこのバグが修正された際には、このテストが成功する(つまり、エラーなくコンパイルされる)ことを保証するためのものです。

test/golden.out

このファイルは、Goコンパイラのテストシステムが、特定のテストケースに対してどのような出力(特にエラーメッセージ)を期待するかを定義する「ゴールデンファイル」の一種です。

  • =========== bugs/bug053.go: これは、続く行がbugs/bug053.goテストの期待される出力であることを示すマーカーです。
  • bugs/bug053.go:6: syntax error: これは、bug053.goの6行目で構文エラーが発生することを期待していることを示しています。これは、var len int;の行がコンパイルエラーを引き起こすことを意味します。
  • BUG: len should not be a keyword: これは、このテストが捕捉しようとしている具体的なバグの説明です。コンパイラがlenをキーワードとして扱っていることが問題であることを明示しています。

このgolden.outへの追加により、Goのテストシステムは、bug053.goを実行した際に、上記の正確なエラーメッセージが出力されることを期待するようになります。もしコンパイラが修正され、var len int;が正しくコンパイルされるようになった場合、このテストは失敗する(期待されるエラーが出力されないため)ことになり、golden.outの更新が必要になります。これは、バグが修正されたことを確認し、テストの目的が達成されたことを示す重要なステップです。

関連リンク

参考にした情報源リンク

  • GitHubのコミットページ: https://github.com/golang/go/commit/9615542d102516a70717bdcc08cb563a9644dbfd
  • Go言語の公式仕様書 (The Go Programming Language Specification): https://go.dev/ref/spec
  • Go言語のソースコードリポジトリ (特にtestディレクトリの構造): https://github.com/golang/go
  • コンパイラの基本原理に関する一般的な知識 (字句解析、構文解析など)
  • テスト駆動開発 (TDD) に関する一般的な知識I have provided the detailed explanation of the commit as requested, following all the specified instructions and chapter structure. I have used the commit information from the provided file and leveraged web search for background and technical details. The output is in Markdown format and in Japanese.