range over functionをもう少し真面目に追う
実装周りや諸々
資料はここに貼る
コミット
初期段階での展望(wiki)
issue
直接使う例は面白い。つまるところrangeのときにコンパイラが頑張ってくれる
func PrintAllElements[E comparable](s *Set[E]) {
s.All()(func(v E) bool {
fmt.Println(v)
return true
})
}
なるほど range over function だ
このcmd/compileの話をmermaidなどでいじれると良い
内部のmainはinternal/gc.Main
( 📝ちなみにgcはgo compilerの略)
呼び出し自体はnoderのirgenで行われてる
実装はinternal/rangefunc.Rewrite
わりとコメントがたくさん書かれてる
実装
実装から把握したい
フロントエンドでparseしてIRを作ってバックエンドで最適化をしてバイナリを吐くイメージ
💭 たぶんインライン展開含めた最適化自体はヒューリスティック的なコストの換算でやってる気がする。一旦そちらは無視する。
range over integerも一緒に挙げられてるけれどコミット自体には見るところが無いような気がする
noderが確かastをwalkしてirを作る君だった気がする
irgenの手前でRewriteしてるのかな?
(最適化自体はたぶん特別にはしてなくて後々のoptimizer任せになってるとおもう)
正解はnoderの中のLoadPackage()の中の...checkFiles()の中でrangefunc.Rewrite()を呼んでいた。
- コメント読む
- コミット読む
たぶん、以下のような感じで呼ばれてる
package cmd/compile/internal/gc
func gc.Main(archInit func(*ssagen.ArchInfo))
func noder.LoadPackage(filenames []string)
func noder.unified(m noder.posMap, noders []*noder.noder)
func noder.writePkgStub(m noder.posMap, noders []*noder.noder) string
func noder.checkFiles(m noder.posMap, noders []*noder.noder) (*types2.Package, *types2.Info, map[*syntax.FuncLit]bool)
func rangefunc.Rewrite(pkg *types2.Package, info *types2.Info, files []*syntax.File) map[*syntax.FuncLit]bool
- gc.Main https://github.com/golang/go/blob/ad6ee21bbf3ef5bec6f29046a9eab096f3202d5c/src/cmd/compile/internal/gc/main.go#L61
- noder.LoadPackage https://github.com/golang/go/blob/ad6ee21bbf3ef5bec6f29046a9eab096f3202d5c/src/cmd/compile/internal/noder/noder.go#L27
- noder.checkFiles (call rangefunc.Rewrite()) https://github.com/golang/go/blob/ad6ee21bbf3ef5bec6f29046a9eab096f3202d5c/src/cmd/compile/internal/noder/irgen.go#L182
- rangefunc.Rewrite https://github.com/golang/go/blob/ad6ee21bbf3ef5bec6f29046a9eab096f3202d5c/src/cmd/compile/internal/rangefunc/rewrite.go#L602
わりとrangefunc.Rewriteのコメントに色々書いてある。
雑に言うとインライン化可能なクロージャの呼び出しへの変換になっていて細々とした注意事項がある感じ(ところでネストした時の変換の話を真面目に追えていない)。
インライン展開自体は別の箇所で行われている。
💭panic時のcall stackというか位置の表示はどうしているんだろうな?(おそらくsetpos()的な命令(?)が存在しているか消えてなくなってる)
コミット自体はテストがめちゃくちゃ生成されていると言うこととrangefunc.Rewrite()が本体と言うことがわかれば十分そう。あとは普通にコードを読むだけになる。
go/astとほとんど変わんないので何故かなんとなく読めるな。。