[インデックス 1560] ファイルの概要
このコミットは、Go言語の初期のコンパイラ(gc
)におけるprint
組み込み関数の挙動に関する修正です。具体的には、map
型とchan
型(チャネル型)の値をprint
関数で出力する際に、それらをポインタとして扱うように変更し、sys.printpointer
関数を呼び出すようにしています。これにより、これらの複合型がより適切に表現されるようになります。
コミット
print(map) and print(chan) as pointers.
R=ken
OCL=23520
CL=23520
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/3c5f3a864115a3d06d531adf71df02d208b7ab25
元コミット内容
commit 3c5f3a864115a3d06d531adf71df02d208b7ab25
Author: Russ Cox <rsc@golang.org>
Date: Mon Jan 26 15:36:28 2009 -0800
print(map) and print(chan) as pointers.
R=ken
OCL=23520
CL=23520
---
src/cmd/gc/sys.go | 2 +--
src/cmd/gc/sysimport.c | 2 +--
src/cmd/gc/walk.c | 6 +++---
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/cmd/gc/sys.go b/src/cmd/gc/sys.go
index fc10f181a8..dbe446cb73 100644
--- a/src/cmd/gc/sys.go
+++ b/src/cmd/gc/sys.go
@@ -16,7 +16,7 @@ func printbool(bool);
func printfloat(float64);
func printint(int64);
func printstring(string);
-func printpointer(*any);
+func printpointer(any);
func printinter(any);
func printarray(any);
func printnl();
diff --git a/src/cmd/gc/sysimport.c b/src/cmd/gc/sysimport.c
index bccc8f877f..08b9adfb7f 100644
--- a/src/cmd/gc/sysimport.c
+++ b/src/cmd/gc/sysimport.c
@@ -8,7 +8,7 @@ char *sysimport =
"func sys.printfloat (? float64)\\n"\n
"func sys.printint (? int64)\\n"\n
"func sys.printstring (? string)\\n"\n
-"func sys.printpointer (? *any)\\n"\n
+"func sys.printpointer (? any)\\n"\n
"func sys.printinter (? any)\\n"\n
"func sys.printarray (? any)\\n"\n
"func sys.printnl ()\\n"\n
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index e7a95d2699..48ab2a6c99 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -1983,9 +1983,9 @@ loop:
argtype(on, l->type); // any-1
break;
}
- if(isptr[l->type->etype]) {
+ if(isptr[l->type->etype] || l->type->etype == TCHAN || l->type->etype == TMAP) {
on = syslook("printpointer", 1);
- argtype(on, l->type->type); // any-1
+ argtype(on, l->type); // any-1
break;
}
if(isslice(l->type)) {
@@ -1993,7 +1993,7 @@ loop:
argtype(on, l->type); // any-1
break;
}
- badtype(n->op, l->type, T);\n
+ badtype(OPRINT, l->type, T);\n
l = listnext(&save);\n
goto loop;\n
変更の背景
Go言語の初期開発段階において、print
組み込み関数はデバッグや簡単な出力のために広く利用されていました。しかし、map
(マップ)やchan
(チャネル)のような複合データ型をprint
関数で出力する際に、その内部表現が適切に表示されないという問題がありました。
Go言語では、map
やchan
は参照型であり、その実体はヒープ上に確保され、変数はその実体へのポインタを保持します。したがって、これらの型をprint
で出力する際には、そのポインタ値(メモリ上のアドレス)を表示することが、デバッグや内部状態の理解において有用であると考えられました。
このコミットは、map
とchan
がprint
関数に渡された際に、既存のポインタ型と同様にsys.printpointer
関数を通じてそのアドレスを出力するように修正することで、この問題を解決しようとしたものです。これにより、print
の出力がこれらの型の実際のメモリ表現をより正確に反映するようになります。
前提知識の解説
Go言語のprint
組み込み関数
Go言語には、デバッグや簡単な出力のためにprint
およびprintln
という組み込み関数が存在します。これらはfmt
パッケージのPrintf
やPrintln
とは異なり、より低レベルな出力メカニズムを提供します。特に、コンパイラ内部で型に応じた出力処理を呼び出すために使用されます。
Go言語のmap
型
map
はキーと値のペアを格納するハッシュテーブルの実装です。Go言語においてmap
は参照型であり、make
関数で初期化されたmap
変数は、内部的にハッシュテーブルの実体へのポインタを保持します。map
変数を別の変数に代入すると、ポインタがコピーされるため、両方の変数が同じ基盤となるハッシュテーブルを参照します。
Go言語のchan
型
chan
(チャネル)は、Goルーチン間で値を送受信するための通信メカニズムです。map
と同様に、chan
も参照型であり、make
関数で初期化されたチャネル変数は、チャネルの実体へのポインタを保持します。チャネルを介した通信は、この実体を介して行われます。
ポインタ
ポインタは、メモリ上の特定のアドレスを指し示す変数です。Go言語では、C言語のようなポインタ演算は制限されていますが、変数のアドレスを取得したり、ポインタを介して値にアクセスしたりすることは可能です。参照型(map
, chan
, スライスなど)は、その実体へのポインタを内部的に保持しています。
Goコンパイラ(gc
)の構造
このコミットが修正しているファイルは、Go言語の初期のコンパイラであるgc
(Go Compiler)の一部です。gc
は、Goのソースコードを機械語に変換する役割を担っています。
src/cmd/gc/sys.go
: コンパイラ内部で利用される組み込み関数(print
など)の宣言が含まれています。これらはGo言語のソースコードからは直接呼び出されず、コンパイラが特殊な処理を行うために使用されます。src/cmd/gc/sysimport.c
:sys.go
で宣言された組み込み関数のC言語での定義(またはそのインポート情報)が含まれています。これは、コンパイラがこれらの関数をどのように扱うかを定義する部分です。src/cmd/gc/walk.c
: コンパイラの「ウォーカー」フェーズを担当するファイルです。このフェーズでは、抽象構文木(AST)を走査し、型チェック、最適化、コード生成のための変換など、様々な処理を行います。print
組み込み関数の呼び出しがどのように処理されるかを決定するロジックが含まれています。
技術的詳細
このコミットは、print
組み込み関数がmap
型とchan
型を処理する方法を変更するために、Goコンパイラの3つのファイルに修正を加えています。
-
src/cmd/gc/sys.go
の変更:func printpointer(*any);
からfunc printpointer(any);
へと変更されています。 これは、sys.printpointer
関数が、以前は任意のポインタ型(*any
)を受け取るように宣言されていたのに対し、任意の型(any
)を受け取るように変更されたことを意味します。これにより、printpointer
はより汎用的な引数を受け入れられるようになり、map
やchan
のような参照型を直接渡せるようになります。 -
src/cmd/gc/sysimport.c
の変更:"func sys.printpointer (? *any)\\n"
から"func sys.printpointer (? any)\\n"
へと変更されています。 これは、sys.go
での変更に対応するもので、コンパイラが内部的にsys.printpointer
のシグネチャを認識する方法を更新しています。これにより、コンパイラはprintpointer
が任意の型を受け取ることを正しく理解し、型チェックやコード生成の際に整合性を保つことができます。 -
src/cmd/gc/walk.c
の変更: このファイルは、print
組み込み関数の呼び出しがどのように処理されるかを決定するコンパイラのコア部分です。if(isptr[l->type->etype]) { ... }
の条件文がif(isptr[l->type->etype] || l->type->etype == TCHAN || l->type->etype == TMAP) { ... }
に変更されました。 これは、print
関数に渡された引数の型(l->type->etype
)がポインタ型である場合に加えて、TCHAN
(チャネル型)またはTMAP
(マップ型)である場合にも、sys.printpointer
関数を呼び出すように指示しています。argtype(on, l->type->type);
からargtype(on, l->type);
へと変更されました。 これは、sys.printpointer
に渡す引数の型を決定する部分です。以前は、ポインタの指す先の型(l->type->type
)を渡していましたが、変更後は引数自体の型(l->type
)を渡すようになります。これは、sys.printpointer
のシグネチャがany
になったことと整合しています。map
やchan
はそれ自体が参照型であるため、その型情報をそのままprintpointer
に渡すことで、内部でそのポインタ値を適切に処理できるようになります。badtype(n->op, l->type, T);
からbadtype(OPRINT, l->type, T);
へと変更されました。 これは、print
関数に渡された型が不正である場合にエラーを報告する部分です。n->op
は現在のノードの操作を表しますが、OPRINT
と明示することで、print
操作における型エラーであることをより明確にしています。
これらの変更により、print
関数がmap
やchan
を受け取った際に、それらをポインタとして扱い、sys.printpointer
を通じてそのアドレスを出力する一貫した挙動が実現されます。
コアとなるコードの変更箇所
src/cmd/gc/sys.go
--- a/src/cmd/gc/sys.go
+++ b/src/cmd/gc/sys.go
@@ -16,7 +16,7 @@ func printbool(bool);
func printfloat(float64);
func printint(int64);
func printstring(string);
-func printpointer(*any);
+func printpointer(any);
func printinter(any);
func printarray(any);
func printnl();
src/cmd/gc/sysimport.c
--- a/src/cmd/gc/sysimport.c
+++ b/src/cmd/gc/sysimport.c
@@ -8,7 +8,7 @@ char *sysimport =
"func sys.printfloat (? float64)\\n"\n
"func sys.printint (? int64)\\n"\n
"func sys.printstring (? string)\\n"\n
-"func sys.printpointer (? *any)\\n"\n
+"func sys.printpointer (? any)\\n"\n
"func sys.printinter (? any)\\n"\n
"func sys.printarray (? any)\\n"\n
"func sys.printnl ()\\n"\n
src/cmd/gc/walk.c
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -1983,9 +1983,9 @@ loop:
argtype(on, l->type); // any-1
break;
}
- if(isptr[l->type->etype]) {
+ if(isptr[l->type->etype] || l->type->etype == TCHAN || l->type->etype == TMAP) {
on = syslook("printpointer", 1);
- argtype(on, l->type->type); // any-1
+ argtype(on, l->type); // any-1
break;
}
if(isslice(l->type)) {
@@ -1993,7 +1993,7 @@ loop:
argtype(on, l->type); // any-1
break;
}
- badtype(n->op, l->type, T);\n
+ badtype(OPRINT, l->type, T);\n
l = listnext(&save);\n
goto loop;\n
コアとなるコードの解説
src/cmd/gc/sys.go
および src/cmd/gc/sysimport.c
の変更
これらのファイルにおけるprintpointer
関数のシグネチャの変更は、printpointer
がより汎用的な引数を受け入れられるようにするためのものです。
*any
からany
への変更は、printpointer
が特定のポインタ型だけでなく、任意の型の値を直接受け取れるようになったことを示します。これは、map
やchan
が参照型であり、その実体へのポインタを内部的に持つため、それらの型自体をprintpointer
に渡すことで、内部でポインタ値として処理できるようにするためです。
src/cmd/gc/walk.c
の変更
このファイルは、print
組み込み関数のセマンティクスを定義する上で最も重要な変更を含んでいます。
-
if(isptr[l->type->etype] || l->type->etype == TCHAN || l->type->etype == TMAP)
: この条件文は、print
関数に渡された引数l
の型が、既存のポインタ型(isptr[l->type->etype]
)であるか、新たにTCHAN
(チャネル型)またはTMAP
(マップ型)である場合に真となります。これにより、map
とchan
もポインタと同様の出力パスを通るようになります。 -
argtype(on, l->type);
: この行は、sys.printpointer
関数を呼び出す際に、引数としてl
の型情報全体(l->type
)を渡すように変更されています。以前はl->type->type
(ポインタの指す先の型)を渡していましたが、printpointer
がany
を受け取るようになったため、map
やchan
のような参照型をそのまま渡すことで、その内部のポインタ値をprintpointer
が適切に解釈できるようになります。 -
badtype(OPRINT, l->type, T);
: この変更は、print
関数に不正な型の引数が渡された場合に発生するエラーメッセージをより具体的にするためのものです。n->op
は一般的な操作を表すのに対し、OPRINT
はprint
操作に特化した定数であり、エラーの発生源を明確にします。
これらの変更の組み合わせにより、Goコンパイラはprint(map)
やprint(chan)
が呼び出された際に、これらの型の内部的なポインタ値を抽出し、sys.printpointer
を通じて出力するようになります。これにより、デバッグ時にこれらの複合型のメモリ上の位置を把握できるようになり、開発者にとってより有用な情報が提供されることになります。
関連リンク
- Go言語の
print
組み込み関数に関する議論やドキュメント(当時のものを見つけるのは困難ですが、Goの歴史的な文脈で探す必要があります) - Go言語の
map
型に関する公式ドキュメント - Go言語の
chan
型に関する公式ドキュメント
参考にした情報源リンク
- Go言語のソースコードリポジトリ (GitHub): https://github.com/golang/go
- Go言語の初期のコミット履歴
- Go言語の
map
とchan
の内部実装に関する一般的な知識 - Go言語のコンパイラ(
gc
)の構造に関する一般的な知識I have extracted the commit information and outlined the plan. Now I will perform a web search to gather more context for the "変更の背景" and "前提知識の解説" sections.
My search query will be: "Go language print map chan pointers early compiler" or similar to find historical context.
After the web search, I will compile all the information into the requested Markdown format.
print(default_api.google_web_search(query="Go language print map chan pointers early compiler"))