[インデックス 13408] ファイルの概要
このコミットは、Go言語の仕様書 (doc/go_spec.html
) における QualifiedIdent
プロダクション(生成規則)の使用方法を整理し、明確化することを目的としています。具体的には、TypeName
と Operand
の定義において、QualifiedIdent
の扱いをより正確に記述するように変更が加えられています。
コミット
commit 809e06babc883bf756d62b1e1fa971beafcf2713
Author: Robert Griesemer <gri@golang.org>
Date: Tue Jun 26 11:49:19 2012 -0700
go spec: clean up use of QualifiedIdent production.
Fixes #3763.
R=r, rsc, iant, ken
CC=golang-dev
https://golang.org/cl/6333066
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/809e06babc883bf756d62b1e1fa971beafcf2713
元コミット内容
go spec: clean up use of QualifiedIdent production.
Fixes #3763.
R=r, rsc, iant, ken
CC=golang-dev
https://golang.org/cl/6333066
変更の背景
このコミットの背景には、Go言語の仕様書における構文定義の厳密性と明確性の向上が挙げられます。特に、QualifiedIdent
(修飾識別子)の定義と、それが TypeName
(型名)や Operand
(オペランド)といった他の構文要素でどのように使用されるかについて、既存の記述に曖昧さや不正確さがあったと考えられます。
Go言語の仕様書は、言語の挙動を定義する最も権威あるドキュメントであり、その正確性は非常に重要です。コンパイラの実装者、ツール開発者、そしてGo言語のユーザーが、言語の構文とセマンティクスを正確に理解できるように、仕様書の記述は常に洗練され、明確である必要があります。
このコミットで参照されている Fixes #3763
は、当時のGoプロジェクトの課題追跡システムにおける特定の課題を指していると考えられます。しかし、現在のGoプロジェクトのGitHubリポジトリでこの番号の課題を検索しても、関連する情報は見つかりませんでした。これは、課題追跡システムが変更されたか、あるいは非常に古い課題であるため、現在の公開リポジトリからはアクセスできないためと考えられます。しかし、コミットメッセージから、QualifiedIdent
の使用に関する何らかの不整合や不明瞭さが存在し、それが修正の動機となったことは明らかです。
前提知識の解説
このコミットの変更内容を理解するためには、以下のGo言語および形式言語に関する基本的な知識が必要です。
1. Go言語の識別子と修飾識別子
- 識別子 (identifier): プログラム内で変数、関数、型、パッケージなどを識別するために使用される名前です。Go言語では、英数字とアンダースコアで構成され、数字で始まることはできません。
- 修飾識別子 (Qualified Identifier): 別のパッケージで宣言された識別子を参照する際に使用されます。
パッケージ名.識別子
の形式を取ります。例えば、fmt.Println
はfmt
パッケージのPrintln
関数を指す修飾識別子です。
2. 形式文法とEBNF
Go言語の仕様書は、言語の構文を形式的に記述するためにEBNF (Extended Backus-Naur Form) を使用しています。EBNFは、プログラミング言語の構文規則を定義するためのメタ言語です。
- プロダクション (Production): EBNFにおける構文規則の単位です。
非終端記号 = 表現 .
の形式で記述され、非終端記号がどのように展開されるかを示します。 - 非終端記号 (Non-terminal Symbol): 構文規則の左辺に現れる記号で、さらに他の記号に展開される可能性があります。例:
Type
,TypeName
,Operand
。 - 終端記号 (Terminal Symbol): 構文規則の右辺に現れる記号で、それ以上展開されない、言語の基本的な要素(キーワード、識別子、リテラルなど)です。例:
identifier
,.
(ドット),(
(括弧)。 |
(選択): 複数の選択肢のいずれか一つを意味します。例:A = B | C .
は、AがBまたはCのいずれかであることを意味します。[ ]
(オプション): 括弧内の要素が省略可能であることを意味します。例:A = [B] C .
は、AがBの後にCが続くか、Cのみであることを意味します。*
(ゼロ回以上の繰り返し): 直前の要素がゼロ回以上繰り返されることを意味します。+
(一回以上の繰り返し): 直前の要素が一回以上繰り返されることを意味します。
3. Go言語の型システム
Go言語では、すべての値が特定の型を持ちます。型は、その値がどのような種類のデータであるか、そしてその値に対してどのような操作が可能であるかを定義します。
- 型名 (Type Name): 既存の型を参照するための名前です。これは組み込み型(例:
int
,string
)である場合もあれば、ユーザー定義型(例:MyStruct
,MyInterface
)である場合もあります。他のパッケージで定義された型を参照する場合は、修飾識別子を使用します。 - 型リテラル (Type Literal): 既存の型を組み合わせて新しい型を構成する構文です。例:
[]int
(スライス型),struct { x int }
(構造体型),func() string
(関数型)。
技術的詳細
このコミットは、Go言語の仕様書 (doc/go_spec.html
) の以下のセクションに影響を与えています。
-
日付の更新: 仕様書のバージョン日付が「Version of June 22, 2012」から「Version of June 26, 2012」に更新されています。これは、変更が適用された日付を反映するものです。
-
型の定義 (
Type
) の修正: 変更前:Type = TypeName | TypeLit | "(" Type ")" . TypeName = QualifiedIdent .
変更後:
Type = TypeName | TypeLit | "(" Type ")" . TypeName = identifier | QualifiedIdent .
この変更は、
TypeName
が単なるQualifiedIdent
だけでなく、修飾されていない通常のidentifier
(識別子)も含むことを明確にしています。例えば、同じパッケージ内で定義された型を参照する場合、int
やstring
のような組み込み型を参照する場合、あるいはMyType
のようにパッケージ修飾なしでユーザー定義型を参照する場合など、これらはすべてidentifier
です。以前の定義では、TypeName
が常にQualifiedIdent
であると誤解される可能性がありました。この修正により、TypeName
の定義がより正確になり、Go言語の実際の構文と一致するようになりました。 -
オペランドの定義 (
Operand
) の修正: 変更前:Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" .
変更後:
Operand = Literal | OperandName | MethodExpr | "(" Expression ")" . Literal = BasicLit | CompositeLit | FunctionLit . BasicLit = int_lit | float_lit | imaginary_lit | char_lit | string_lit . OperandName = identifier | QualifiedIdent.
この変更は、
Operand
の定義をより詳細かつ正確にしています。QualifiedIdent
が直接Operand
の一部としてリストされるのではなく、新たに導入されたOperandName
プロダクションの下に移動しました。OperandName
は、identifier
またはQualifiedIdent
のいずれかであることを明確に定義しています。これにより、オペランドが修飾されていない識別子(例: ローカル変数、関数パラメータ、同じパッケージ内の定数や関数)である場合と、修飾識別子(例: 別のパッケージの変数や関数)である場合の両方を適切に表現できるようになりました。- この変更は、オペランドが「リテラル、(おそらく修飾された) 識別子、メソッド式、または括弧で囲まれた式」であるというテキストの説明と、EBNFの定義との整合性を高めています。
-
修飾識別子の定義 (
QualifiedIdent
) の修正: 変更前:QualifiedIdent = [ PackageName "." ] identifier .
変更後:
QualifiedIdent = PackageName "." identifier .
この変更は、
QualifiedIdent
の定義から[ PackageName "." ]
のオプション指定を削除し、PackageName "."
が必須であることを明確にしています。これは、QualifiedIdent
が「パッケージ名プレフィックスで修飾された識別子」であるという定義と一致します。もしパッケージ名が省略可能であれば、それは単なる識別子であり、QualifiedIdent
とは区別されるべきです。この修正により、QualifiedIdent
の定義がより厳密になり、その意味が明確になりました。
これらの変更は全体として、Go言語の構文規則の記述をより正確で、曖昧さのないものにすることを目的としています。特に、識別子と修飾識別子の区別を明確にし、それらが型名やオペランドとしてどのように使用されるかを厳密に定義することで、仕様書の解釈の余地を減らし、言語の形式的な定義を強化しています。
コアとなるコードの変更箇所
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
- "Subtitle": "Version of June 22, 2012",
+ "Subtitle": "Version of June 26, 2012",
"Path": "/ref/spec"
}-->
@@ -622,14 +622,15 @@ expressions</a>.
<p>
A type determines the set of values and operations specific to values of that
-type. A type may be specified by a (possibly qualified) <i>type name</i>
-(§<a href="#Qualified_identifiers">Qualified identifier</a>, §<a href="#Type_declarations">Type declarations</a>) or a <i>type literal</i>,
+type. A type may be specified by a
+(possibly <a href="#Qualified_identifiers">qualified</a>) <i>type name</i>
+(§<a href="#Type_declarations">Type declarations</a>) or a <i>type literal</i>,
which composes a new type from previously declared types.
</p>
<pre class="ebnf">
Type = TypeName | TypeLit | "(" Type ")" .
-TypeName = QualifiedIdent .
+TypeName = identifier | QualifiedIdent .
TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
SliceType | MapType | ChannelType .
</pre>
@@ -2026,25 +2027,33 @@ operators and functions to operands.
<h3 id="Operands">Operands</h3>
<p>
-Operands denote the elementary values in an expression.
+Operands denote the elementary values in an expression. An operand may be a
+literal, a (possibly <a href="#Qualified_identifiers">qualified</a>) identifier
+denoting a
+<a href="#Constant_declarations">constant</a>,
+<a href="#Variable_declarations">variable</a>, or
+<a href="#Function_declarations">function</a>,
+a <a href="#Method_expressions">method expression</a> yielding a function,
+or a parenthesized expression.
</p>
<pre class="ebnf">
-Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" .
+Operand = Literal | OperandName | MethodExpr | "(" Expression ")" .
Literal = BasicLit | CompositeLit | FunctionLit .
BasicLit = int_lit | float_lit | imaginary_lit | char_lit | string_lit .
+OperandName = identifier | QualifiedIdent.
</pre>
-
<h3 id="Qualified_identifiers">Qualified identifiers</h3>
<p>
-A qualified identifier is a non-<a href="#Blank_identifier">blank</a> identifier
-qualified by a package name prefix.
+A qualified identifier is an identifier qualified with a package name prefix.
+Both the package name and the identifier must not be
+<a href="#Blank_identifier">blank</a>.
</p>
<pre class="ebnf">
-QualifiedIdent = [ PackageName "." ] identifier .
+QualifiedIdent = PackageName "." identifier .
</pre>
<p>
コアとなるコードの解説
上記の差分は、Go言語の仕様書 (doc/go_spec.html
) におけるEBNF形式の構文定義の変更を示しています。
-
Subtitle
の日付更新:- "Subtitle": "Version of June 22, 2012", + "Subtitle": "Version of June 26, 2012",
これは、仕様書のバージョン日付をコミット日に合わせて更新したものです。
-
TypeName
の定義変更:-TypeName = QualifiedIdent . +TypeName = identifier | QualifiedIdent .
この変更は、
TypeName
がQualifiedIdent
(修飾識別子、例:fmt.Stringer
)だけでなく、identifier
(通常の識別子、例:int
,string
,MyType
)も含むことを明確にしています。これにより、Go言語の型名の実際の使用方法がより正確に反映されます。 -
Operand
の定義変更とOperandName
の導入:-Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" . +Operand = Literal | OperandName | MethodExpr | "(" Expression ")" . Literal = BasicLit | CompositeLit | FunctionLit . BasicLit = int_lit | float_lit | imaginary_lit | char_lit | string_lit . +OperandName = identifier | QualifiedIdent.
Operand
の定義からQualifiedIdent
が直接削除され、新たにOperandName
という非終端記号が導入されました。OperandName
はidentifier
またはQualifiedIdent
のいずれかであると定義されています。この変更により、オペランドが単なる識別子(例:x
,myFunc
)である場合と、修飾識別子(例:pkg.Var
,pkg.Func
)である場合の両方を、より構造化された形で表現できるようになりました。これは、仕様書のテキスト説明とEBNF定義の整合性を高めるためのものです。 -
QualifiedIdent
の定義変更:-QualifiedIdent = [ PackageName "." ] identifier . +QualifiedIdent = PackageName "." identifier .
この変更は、
QualifiedIdent
の定義から[ PackageName "." ]
のオプション指定([]
)を削除し、PackageName "."
が必須であることを示しています。これにより、QualifiedIdent
は常にパッケージ名で修飾された識別子であることを厳密に定義し、単なる識別子とは明確に区別されるようになりました。
これらの変更は、Go言語の構文規則の正確性と明確性を向上させ、特に識別子と修飾識別子の役割と使用範囲をより厳密に定義することを目的としています。
関連リンク
- Go言語の公式ウェブサイト: https://golang.org/
- Go言語の仕様書: https://golang.org/ref/spec (このコミットが変更を加えたドキュメントの最新版)
参考にした情報源リンク
- Go言語の仕様書 (コミット対象のファイル):
doc/go_spec.html
(コミット履歴から参照) - EBNF (Extended Backus-Naur Form) の概念に関する一般的な情報源 (例: Wikipediaなど)
- Go言語の識別子とパッケージに関する一般的な情報源 (Goの公式ドキュメントやチュートリアルなど)
- GitHubのコミットページ: https://github.com/golang/go/commit/809e06babc883bf756d62b1e1fa971beafcf2713
- Go CL (Change List) 6333066: https://golang.org/cl/6333066 (このコミットに対応するGoのコードレビューシステム上の変更リスト)