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

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

このコミットは、Go言語のコンパイラの一部である cmd/gc における walk.c ファイルの変更に関するものです。具体的には、マップの要素削除に関連する古いコードパスが削除されています。

コミット

commit 9069721b0eb7c63c669bd8c6752b090918a2f60c
Author: Russ Cox <rsc@golang.org>
Date:   Wed Mar 7 22:03:35 2012 -0500

    cmd/gc: delete old map delete in walk
    
    R=ken2
    CC=golang-dev
    https://golang.org/cl/5783047

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

https://github.com/golang/go/commit/9069721b0eb7c63c669bd8c6752b090918a2f60c

元コミット内容

--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -646,12 +646,6 @@ walkexpr(Node **np, NodeList **init)
 		n->ninit = nil;
 		l = n->list->n;
 		r = n->list->next->n;
-		if(n->right != N) {
-			// TODO: Remove once two-element map assigment is gone.
-			l = safeexpr(l, init);
-			r = safeexpr(r, init);
-			safeexpr(n->right, init);  // cause side effects from n->right
-		}
 		t = l->type;
 		n = mkcall1(mapfndel("mapdelete", t), t->down, init, typename(t), l, r);
 		goto ret;

変更の背景

このコミットは、Go言語のコンパイラ gc におけるマップ操作の内部処理の進化を反映しています。削除されたコードは、マップからの要素削除(mapdelete)に関連するもので、特に「two-element map assignment」(2要素マップ代入)という、かつて存在した、あるいは検討されていたマップ操作の形式に対応するためのものでした。

コミットメッセージにある TODO: Remove once two-element map assigment is gone. というコメントが示すように、このコードは一時的な措置であり、特定の機能(2要素マップ代入)が廃止された、あるいは実装されなくなった時点で削除される予定でした。Go言語の開発過程では、言語仕様やコンパイラの内部実装が継続的に改善されており、不要になった古いコードパスは定期的にクリーンアップされます。

この変更は、コンパイラのコードベースを整理し、将来のメンテナンス性を向上させることを目的としています。不要なコードを削除することで、コンパイラの複雑性を軽減し、バグの潜在的な発生源を減らすことができます。

前提知識の解説

Go言語のコンパイラ gc

gc は、Go言語の公式コンパイラであり、Goのソースコードを機械語に変換する役割を担っています。gc は複数のステージで構成されており、その中には構文解析、型チェック、中間表現の生成、最適化、コード生成などが含まれます。

src/cmd/gc/walk.c

src/cmd/gc/walk.c は、Goコンパイラのバックエンドの一部であり、抽象構文木(AST)を走査("walk")して、より低レベルの中間表現に変換する処理を担当しています。このファイルには、Go言語の様々な構文要素(式、ステートメントなど)がどのようにコンパイラ内部で処理されるかを定義する関数が含まれています。特に、walkexpr 関数は式を走査し、必要に応じて変換や最適化を行います。

Go言語のマップ (map)

Go言語のマップは、キーと値のペアを格納するための組み込みデータ構造です。マップの要素を削除するには、delete 組み込み関数を使用します。コンパイラは delete 関数呼び出しを、内部的なマップ削除関数(例: mapdelete)への呼び出しに変換します。

mapdelete 関数

mapdelete は、Goランタイムが提供する内部関数で、マップから指定されたキーに対応する要素を削除する実際の処理を行います。コンパイラは delete(m, key) のようなGoコードを、この mapdelete 関数への呼び出しに変換します。

safeexpr 関数

safeexpr は、コンパイラ内部の関数で、式を評価し、その評価が副作用を持つ場合に、その副作用が適切な順序で発生するように初期化リスト (init) に追加する役割を担います。これは、式の評価順序が重要となるGoのセマンティクスを保証するために使用されます。

mkcall1 関数

mkcall1 は、コンパイラ内部の関数で、単一の引数を持つ関数呼び出しを表すノードを生成します。このコミットの文脈では、mapdelete 関数への呼び出しを構築するために使用されています。

Two-element map assignment (2要素マップ代入)

Go言語のマップ操作には、v, ok := m[key] のように、値と存在チェックの2つの戻り値を受け取る形式があります。これは「comma-ok idiom」として知られています。 削除されたコードのコメント TODO: Remove once two-element map assigment is gone. は、かつてマップへの代入操作において、キーと値の他に何らかの2つ目の要素(例えば、成功を示すブール値など)を同時に代入するような、現在とは異なるセマンティクスが存在したか、あるいは検討されていた可能性を示唆しています。しかし、現在のGo言語の仕様では、マップへの代入は m[key] = value の形式であり、2要素を同時に代入するような直接的な構文は存在しません。このコメントは、コンパイラの開発初期段階における設計の変遷を示していると考えられます。

技術的詳細

このコミットで削除されたコードブロックは、walkexpr 関数内で OMAPDELETE(マップ要素削除)ノードを処理する部分にありました。

		if(n->right != N) {
			// TODO: Remove once two-element map assigment is gone.
			l = safeexpr(l, init);
			r = safeexpr(r, init);
			safeexpr(n->right, init);  // cause side effects from n->right
		}

この if ブロックは、n->rightN(nil、つまりノードが存在しないことを示す)でない場合に実行されていました。n->right は、OMAPDELETE ノードの文脈では、おそらく「2要素マップ代入」の2つ目の要素、または関連する何らかの補助的な式を指していたと考えられます。

削除されたコードの内部では、lr、そして n->right の各式に対して safeexpr が呼び出されていました。これは、これらの式が副作用を持つ可能性がある場合に、その副作用が適切に処理されるようにコンパイラが保証するためのものです。特に safeexpr(n->right, init); // cause side effects from n->right というコメントは、n->right の評価が何らかの副作用を引き起こすことを意図していたことを示しています。

このコードブロックが削除されたということは、以下のいずれかの理由が考えられます。

  1. 「two-element map assignment」の概念が完全に廃止された: Go言語の設計において、マップの代入や削除に関するセマンティクスが変更され、この「2要素マップ代入」という概念が不要になったため、それに対応するコンパイラコードも不要になった。
  2. 副作用の処理方法が変更された: n->right が表す式の副作用の処理方法が、この if ブロックを必要としない別のメカニズムに置き換えられた。
  3. コードの冗長性: 以前のコンパイラバージョンでは必要だったが、その後のコンパイラの進化により、この特定の safeexpr の呼び出しが冗長になった。

コミットメッセージと TODO コメントから判断すると、最も可能性が高いのは1番目の理由です。Go言語の進化の過程で、マップ操作のセマンティクスが洗練され、この特定のコードパスが不要になったと考えられます。これにより、コンパイラのコードベースが簡素化され、よりクリーンで効率的な実装が実現されました。

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

変更は src/cmd/gc/walk.c ファイルの walkexpr 関数内で行われました。具体的には、以下の6行が削除されました。

--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -646,12 +646,6 @@ walkexpr(Node **np, NodeList **init)
 		n->ninit = nil;
 		l = n->list->n;
 		r = n->list->next->n;
-		if(n->right != N) {
-			// TODO: Remove once two-element map assigment is gone.
-			l = safeexpr(l, init);
-			r = safeexpr(r, init);
-			safeexpr(n->right, init);  // cause side effects from n->right
-		}
 		t = l->type;
 		n = mkcall1(mapfndel("mapdelete", t), t->down, init, typename(t), l, r);
 		goto ret;

コアとなるコードの解説

削除されたコードブロックは、OMAPDELETE ノード(マップからの要素削除を表すコンパイラ内部のノード)を処理する部分にありました。

  • if(n->right != N): この条件は、OMAPDELETE ノードに right サブノードが存在するかどうかをチェックしていました。前述の通り、これは「2要素マップ代入」に関連する補助的な式であった可能性が高いです。
  • // TODO: Remove once two-element map assigment is gone.: このコメントは、このコードが一時的なものであり、将来的に削除されるべきであることを明確に示しています。これは、Go言語の設計が進化し、この特定のマップ代入の概念が廃止されることを予期していたことを意味します。
  • l = safeexpr(l, init);: マップのキーを表す式 lsafeexpr で処理し、副作用があれば初期化リストに追加します。
  • r = safeexpr(r, init);: マップの値を表す式 rsafeexpr で処理し、副作用があれば初期化リストに追加します。
  • safeexpr(n->right, init); // cause side effects from n->right: n->right が表す式を safeexpr で処理し、その副作用を初期化リストに追加します。この行は、n->right の評価が何らかの重要な副作用を持つことを示唆しています。

このコードブロックの削除は、Goコンパイラが OMAPDELETE ノードを処理する際に、もはや n->right の存在を考慮する必要がなくなり、また、それに伴う safeexpr の呼び出しも不要になったことを意味します。これは、Go言語のマップ削除のセマンティクスが簡素化されたか、あるいはコンパイラの内部処理がより効率的になった結果と考えられます。

関連リンク

参考にした情報源リンク

  • Go言語のドキュメント (特にマップとコンパイラに関するセクション): https://go.dev/doc/
  • Go言語のソースコード (特に src/cmd/gc ディレクトリ): https://github.com/golang/go/tree/master/src/cmd/gc
  • Go言語のコンパイラに関するブログ記事や解説 (一般的な情報源):
  • Go言語のコンパイラ内部に関する技術的な議論やメーリングリストのアーカイブ (golang-devなど): https://groups.google.com/g/golang-dev (特定の設計判断の背景を深く掘り下げる場合に有用)

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

このコミットは、Go言語のコンパイラの一部である cmd/gc における walk.c ファイルの変更に関するものです。具体的には、マップの要素削除に関連する古いコードパスが削除されています。

コミット

commit 9069721b0eb7c63c669bd8c6752b090918a2f60c
Author: Russ Cox <rsc@golang.org>
Date:   Wed Mar 7 22:03:35 2012 -0500

    cmd/gc: delete old map delete in walk
    
    R=ken2
    CC=golang-dev
    https://golang.org/cl/5783047

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

https://github.com/golang/go/commit/9069721b0eb7c63c669bd8c6752b090918a2f60c

元コミット内容

--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -646,12 +646,6 @@ walkexpr(Node **np, NodeList **init)
 		n->ninit = nil;
 		l = n->list->n;
 		r = n->list->next->n;
-		if(n->right != N) {
-			// TODO: Remove once two-element map assigment is gone.
-			l = safeexpr(l, init);
-			r = safeexpr(r, init);
-			safeexpr(n->right, init);  // cause side effects from n->right
-		}
 		t = l->type;
 		n = mkcall1(mapfndel("mapdelete", t), t->down, init, typename(t), l, r);
 		goto ret;

変更の背景

このコミットは、Go言語のコンパイラ gc におけるマップ操作の内部処理の進化を反映しています。削除されたコードは、マップからの要素削除(mapdelete)に関連するもので、特に「two-element map assignment」(2要素マップ代入)という、かつて存在した、あるいは検討されていたマップ操作の形式に対応するためのものでした。

コミットメッセージにある TODO: Remove once two-element map assigment is gone. というコメントが示すように、このコードは一時的な措置であり、特定の機能(2要素マップ代入)が廃止された、あるいは実装されなくなった時点で削除される予定でした。Go言語の開発過程では、言語仕様やコンパイラの内部実装が継続的に改善されており、不要になった古いコードパスは定期的にクリーンアップされます。

この変更は、コンパイラのコードベースを整理し、将来のメンテナンス性を向上させることを目的としています。不要なコードを削除することで、コンパイラの複雑性を軽減し、バグの潜在的な発生源を減らすことができます。

前提知識の解説

Go言語のコンパイラ gc

gc は、Go言語の公式コンパイラであり、Goのソースコードを機械語に変換する役割を担っています。gc は複数のステージで構成されており、その中には構文解析、型チェック、中間表現の生成、最適化、コード生成などが含まれます。

src/cmd/gc/walk.c

src/cmd/gc/walk.c は、Goコンパイラのバックエンドの一部であり、抽象構文木(AST)を走査("walk")して、より低レベルの中間表現に変換する処理を担当しています。このファイルには、Go言語の様々な構文要素(式、ステートメントなど)がどのようにコンパイラ内部で処理されるかを定義する関数が含まれています。特に、walkexpr 関数は式を走査し、必要に応じて変換や最適化を行います。

Go言語のマップ (map)

Go言語のマップは、キーと値のペアを格納するための組み込みデータ構造です。マップの要素を削除するには、delete 組み込み関数を使用します。コンパイラは delete 関数呼び出しを、内部的なマップ削除関数(例: mapdelete)への呼び出しに変換します。

mapdelete 関数

mapdelete は、Goランタイムが提供する内部関数で、マップから指定されたキーに対応する要素を削除する実際の処理を行います。コンパイラは delete(m, key) のようなGoコードを、この mapdelete 関数への呼び出しに変換します。

safeexpr 関数

safeexpr は、コンパイラ内部の関数で、式を評価し、その評価が副作用を持つ場合に、その副作用が適切な順序で発生するように初期化リスト (init) に追加する役割を担います。これは、式の評価順序が重要となるGoのセマンティクスを保証するために使用されます。

mkcall1 関数

mkcall1 は、コンパイラ内部の関数で、単一の引数を持つ関数呼び出しを表すノードを生成します。このコミットの文脈では、mapdelete 関数への呼び出しを構築するために使用されています。

Two-element map assignment (2要素マップ代入)

Go言語のマップ操作には、v, ok := m[key] のように、値と存在チェックの2つの戻り値を受け取る形式があります。これは「comma-ok idiom」として知られています。 削除されたコードのコメント TODO: Remove once two-element map assigment is gone. は、かつてマップへの代入操作において、キーと値の他に何らかの2つ目の要素(例えば、成功を示すブール値など)を同時に代入するような、現在とは異なるセマンティクスが存在したか、あるいは検討されていた可能性を示唆しています。Web検索の結果によると、Go 1より前のバージョンでは、マップからの要素削除は m[key] = value, false のような2要素代入構文で行われていました。この構文は、値を代入しつつ、2つ目の要素として false を指定することで削除を意味するという、特殊なものでした。Go 1で専用の delete(m, key) 組み込み関数に置き換えられたため、この古い構文に対応するコンパイラコードは不要になりました。

技術的詳細

このコミットで削除されたコードブロックは、walkexpr 関数内で OMAPDELETE(マップ要素削除)ノードを処理する部分にありました。

		if(n->right != N) {
			// TODO: Remove once two-element map assigment is gone.
			l = safeexpr(l, init);
			r = safeexpr(r, init);
			safeexpr(n->right, init);  // cause side effects from n->right
		}

この if ブロックは、n->rightN(nil、つまりノードが存在しないことを示す)でない場合に実行されていました。n->right は、OMAPDELETE ノードの文脈では、かつての「2要素マップ代入」構文における2つ目の要素、すなわち false の部分、またはそれに伴う補助的な式を指していたと考えられます。

削除されたコードの内部では、lr、そして n->right の各式に対して safeexpr が呼び出されていました。これは、これらの式が副作用を持つ可能性がある場合に、その副作用が適切に処理されるようにコンパイラが保証するためのものです。特に safeexpr(n->right, init); // cause side effects from n->right というコメントは、n->right の評価が何らかの副作用を引き起こすことを意図していたことを示しています。

このコードブロックが削除されたということは、Go言語のマップ削除のセマンティクスが delete(m, key) という専用の組み込み関数に統一され、かつての「2要素マップ代入」構文が完全に廃止されたため、それに対応するコンパイラ内部の処理も不要になったことを意味します。これにより、コンパイラのコードベースが簡素化され、よりクリーンで効率的な実装が実現されました。

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

変更は src/cmd/gc/walk.c ファイルの walkexpr 関数内で行われました。具体的には、以下の6行が削除されました。

--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -646,12 +646,6 @@ walkexpr(Node **np, NodeList **init)
 		n->ninit = nil;
 		l = n->list->n;
 		r = n->list->next->n;
-		if(n->right != N) {
-			// TODO: Remove once two-element map assigment is gone.
-			l = safeexpr(l, init);
-			r = safeexpr(r, init);
-			safeexpr(n->right, init);  // cause side effects from n->right
-		}
 		t = l->type;
 		n = mkcall1(mapfndel("mapdelete", t), t->down, init, typename(t), l, r);
 		goto ret;

コアとなるコードの解説

削除されたコードブロックは、OMAPDELETE ノード(マップからの要素削除を表すコンパイラ内部のノード)を処理する部分にありました。

  • if(n->right != N): この条件は、OMAPDELETE ノードに right サブノードが存在するかどうかをチェックしていました。これは、かつての「2要素マップ代入」構文における2つ目の要素(false)に対応するノードであったと考えられます。
  • // TODO: Remove once two-element map assigment is gone.: このコメントは、このコードが一時的なものであり、将来的に削除されるべきであることを明確に示しています。これは、Go言語の設計が進化し、この特定のマップ代入の概念が廃止されることを予期していたことを意味します。
  • l = safeexpr(l, init);: マップのキーを表す式 lsafeexpr で処理し、副作用があれば初期化リストに追加します。
  • r = safeexpr(r, init);: マップの値を表す式 rsafeexpr で処理し、副作用があれば初期化リストに追加します。
  • safeexpr(n->right, init); // cause side effects from n->right: n->right が表す式を safeexpr で処理し、その副作用を初期化リストに追加します。この行は、n->right の評価が何らかの重要な副作用を持つことを示唆しています。

このコードブロックの削除は、Goコンパイラが OMAPDELETE ノードを処理する際に、もはや n->right の存在を考慮する必要がなくなり、また、それに伴う safeexpr の呼び出しも不要になったことを意味します。これは、Go言語のマップ削除のセマンティクスが delete(m, key) に統一され、コンパイラの内部処理がより効率的になった結果と考えられます。

関連リンク

参考にした情報源リンク