Goの仕様はこのHTML1ページにまとまっている。
- The Go Programming Language Specification
仕様に書いてある処理はどうやって実装されているのか調べたかった。
Goの仕様の1文からその仕様に関係する処理系のコードを探す方法をメモしておく。
TL;DR
- GoのLanguage Specificationに書いてある仕様の処理系の実装を探す
- GoのLanguage SpecificationのHTMLはGoリポジトリの
doc
ディレクトリに入っている - Language Specificationのコミットログから仕様の追加日を知る
git log -L 2569,2579:./doc/go_spec.html
- 仕様の追加日周辺から関連コミットを検索する
git log --since="2010/10/01" --until="2010/10/31" --grep "composite"
master
ブランチにもう存在しないファイルのコミットログを見るときは--
をつけてgit log
git log --oneline -- src/cmd/gc/typecheck.c
仕様に関連する処理系の実装を探したい
標準関数などは公式のpackagesを見れば良いのだが、
処理系のコードを単純にgrep
で探すのは難しい。
リポジトリのコミットログから仕様に結びつく処理系の実装を探す。
今回は探してみた仕様は以下の部分の仕様だ。
- Composite literals | The Go Programming Language Specification
Within a composite literal of array, slice, or map type T, elements or map keys that are themselves composite literals may elide the respective literal type if it is identical to the element or key type of T. Similarly, elements or keys that are addresses of composite literals may elide the &T when the element or key type…
[...]Point{{1.5, -3.5}, {0, 0}} // same as [...]Point{Point{1.5, -3.5}, Point{0, 0}}
[][]int{{1, 2, 3}, {4, 5}} // same as [][]int{[]int{1, 2, 3}, []int{4, 5}}
[][]Point{{{0, 1}, {1, 2}}} // same as [][]Point{[]Point{Point{0, 1}, Point{1, 2}}}
map[string]Point{"orig": {0, 0}} // same as map[string]Point{"orig": Point{0, 0}}
必要なものはWebブラウザ、Go本体コードのリポジトリ、git
とgrep
コマンドだけだ。
GoのLanguage SpecificationのHTMLはGoリポジトリのdoc
ディレクトリに入っている
GitHubにもミラーされているが、本当(?)のリモートURLからGo本体のリポジトリを取得してくる。
GoのLanguage SpecificationのHTMLはGo本体のリポジトリに一緒に格納されている。
まず、探したい仕様の行数をgrep
コマンドで確認する。
$ grep -n "Within a composite literal of array, slice" ./doc/go_spec.html
2569:Within a composite literal of array, slice, or map type <code>T</code>,
HTMLでは2569行目にあるらしい。
この周辺のコミットログを探してみると、このコミットで仕様の1文が追加されたようだ。
$ git log --reverse -L 2569,2579:./doc/go_spec.html
commit a12141e5f4e905045dca5dff2669b64d9b93788f
Author: Robert Griesemer <gri@golang.org>
Date: Fri Oct 22 08:58:52 2010 -0700
go spec: relaxed syntax for array, slice, and map composite literals
For elements which are themselves composite literals, the type may
be omitted if it is identical to the element type of the containing
composite literal.
R=r, rsc, iant, ken2
CC=golang-dev
https://golang.org/cl/2661041
diff --git a/doc/go_spec.html b/doc/go_spec.html
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -2097,0 +2098,8 @@
+Within a composite literal of array, slice, or map type <code>T</code>,
+elements that are themselves composite literals may elide the respective
+literal type if it is identical to the element type of <code>T</code>.
+</p>
+
+<pre>
+[...]Point{{1.5, -3.5}, {0, 0}} // same as [...]Point{Point{1.5, -3.5}, Point{0, 0}}
+[][]int{{1, 2, 3}, {4, 5}} // same as [][]int{[]int{1, 2, 3}, []int{4, 5}}
commit 5f49456465f53f96bee03ac8cbe0d564e31576c2
Author: Russ Cox <rsc@golang.org>
Date: Fri Dec 2 14:12:53 2011 -0500
Goはコミットログ中にあるURLを見ればGerrit
上のレビューの経過も確認できる。
- code review 2661041: go spec: relaxed syntax for array, slice, and map compo…
仕様が追加された日の周辺コミットログから実装の追加コミットログを探す
仕様が書き足されたのはFri Dec 2 14:12:53 2011
だった。この日付の周辺で実装が追加されたコミットがないか探してみる。
git log
コマンドで日付範囲を指定し、今回の実装に関連しそうなcompoiste
をキーワードにコミットを探してみる。
$ git log --since="2010/10/01" --until="2010/10/31" --grep "composite"
commit f613015e0eeb9560579bf40dbdb40fac5e371bbc
Author: Robert Griesemer <gri@golang.org>
Date: Fri Oct 22 10:03:14 2010 -0700
go ast/parser/printer: permit elision of composite literal types for composite literal elements
gofmt: added -s flag to simplify composite literal expressions through type elision where possible
R=rsc
CC=golang-dev
https://golang.org/cl/2319041
commit a12141e5f4e905045dca5dff2669b64d9b93788f
Author: Robert Griesemer <gri@golang.org>
Date: Fri Oct 22 08:58:52 2010 -0700
go spec: relaxed syntax for array, slice, and map composite literals
For elements which are themselves composite literals, the type may
be omitted if it is identical to the element type of the containing
composite literal.
R=r, rsc, iant, ken2
CC=golang-dev
https://golang.org/cl/2661041
commit 8ffc4ec5d0c3d17d633c277ba5102da838834f03
Author: Russ Cox <rsc@golang.org>
Date: Thu Oct 21 23:17:20 2010 -0400
gc: implement new composite literal spec
R=ken2
CC=golang-dev
https://golang.org/cl/2350041
それぞれのコミットに書かれているレビュー記録を見てみる。
- code review 2350041: gc: implement new composite literal spec
(Go1.4以前はGoはセルフコンパイルではなかったので、)Cの実装ファイル(src/cmd/gc/typecheck.c
)が見つかった。
- code review 2319041: go ast/parser/printer: permit elision of composite lite
こちらを見るとパーサー(src/pkg/go/parser/parser.go
etc)の関連実装を見ることができた。
master
ブランチにもう存在しないファイルのコミットログを見るときは--
をつけてgit log
現在の実装まで探すときはここからさらにコミットログをたどっていけば良い。
master
ブランチにもう存在しないファイルのsrc/cmd/gc/typecheck.c
に関連するコミットを探したいならば、–をつけて
git log`コマンドを実行する。
$ git log --oneline -- src/cmd/gc/typecheck.c
3af0d791be [dev.cc] cmd/6a, cmd/6g etc: replace C implementations with Go implementations
5c87cf7608 cmd/gc: minor adjustments for C to Go translation
4b27c9d72e cmd/gc: add .y to error about missing x in x.y
77a2113925 cmd/gc: evaluate concrete == interface without allocating
eaa872009d cmd/gc: fix capturing by value for range statements
0e80b2e082 cmd/gc: capture variables by value
b581ca5956 cmd/gc: allow map index expressions in for range statements
a7bb393628 cmd/gc: don't emit write barriers for *tmp if tmp=&PAUTO
8d44ede0dc cmd/gc: simplify code for c2go (more)
e82003e750 cmd/gc: simplify code for c2go
また、GitHubのRESTに慣れているならばアドレス直打ちで同等のコミットログが見れる。
終わりに
もともとTweetでもやもやをつぶやいていた。
Goで ds := [][]int{{1, 2, 3, 4}} が許されるの、ラクなんだけどなんで許される({ []int{1, 2, 3, 4} }って書かなくてもよい)のかよく分かってないhttps://t.co/atstRrjope
— Yoichiro Shimizu (@budougumi0617) June 12, 2019
そうしたら会社の先輩が仕様の場所を教えてくれたので、せっかくだから処理系までちゃんと読んでみようと思った。
https://t.co/HlOvZFgB4j
— Yui TERASHIMA (@terashi58) June 12, 2019
これの後半あたりですね
まだ、Goの実装部分まで追えていないが、長期に渡って開発されているリポジトリのgit
を辿る操作も勉強できてよかった。
ただ、これはGoリポジトリのコミットログが異様にきれい(1PRは1コミット、かならずコミットメッセージにPRのURLが入っている)だからできることなのかもしれない。