[インデックス 10682] ファイルの概要
このコミットは、Go言語のコンパイラ(gc
)におけるrune
型の定義に関する重要な変更を導入しています。具体的には、rune
型がint
のエイリアスからint32
のエイリアスへと変更されました。これにより、Go言語におけるUnicode文字の扱いが一貫性を持ち、より明確になります。
コミット
commit 012798a3258f13e4dffe07dda01e035800501f23
Author: Russ Cox <rsc@golang.org>
Date: Fri Dec 9 00:12:07 2011 -0500
gc: rune is now an alias for int32
R=ken2
CC=golang-dev
https://golang.org/cl/5467049
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/012798a3258f13e4dffe07dda01e035800501f23
元コミット内容
gc: rune is now an alias for int32
変更の背景
Go言語のrune
型は、Unicodeのコードポイントを表すために設計されています。初期のGo言語では、rune
はint
のエイリアスとして定義されていました。しかし、int
型はシステムアーキテクチャ(32ビットまたは64ビット)によってサイズが異なるため、rune
が表すコードポイントの範囲や、異なるシステム間での互換性に問題が生じる可能性がありました。
Unicodeのコードポイントは、U+0000からU+10FFFFまでの範囲で定義されており、これらは最大で21ビットを必要とします。したがって、32ビットの符号付き整数型であるint32
は、この範囲のすべてのコードポイントを確実に表現できる最小かつ最も適切な固定幅の型です。
このコミットは、rune
型をint32
のエイリアスとすることで、rune
のサイズと振る舞いを明確にし、異なるプラットフォーム間での一貫性を保証することを目的としています。これにより、Go言語の文字列と文字の処理がより堅牢になり、Unicodeの国際化対応が強化されます。
前提知識の解説
Go言語のrune
型
Go言語において、rune
は組み込み型の一つであり、Unicodeのコードポイントを表すために使用されます。Goの文字列はUTF-8でエンコードされたバイトのシーケンスですが、rune
は個々のUnicode文字(コードポイント)を扱う際に便利です。例えば、文字列を[]rune
に変換することで、各文字を個別のコードポイントとして処理できます。
int
とint32
int
: Go言語のint
型は、プラットフォームに依存する整数型です。32ビットシステムでは32ビット幅、64ビットシステムでは64ビット幅になります。これは、C言語のint
型と同様の特性を持ちます。int32
:int32
型は、常に32ビット幅の符号付き整数型です。その値の範囲は-2,147,483,648から2,147,483,647までです。
Unicodeコードポイント
Unicodeは、世界中の文字を統一的に扱うための文字コード標準です。各文字には一意の「コードポイント」が割り当てられています。コードポイントは通常、U+XXXX
の形式で表記され、XXXX
は16進数です。Unicodeのコードポイントの最大値はU+10FFFF
であり、これは1,114,111という10進数の値に相当します。この値は32ビット整数で十分に表現可能です。
Goコンパイラ(gc
)
gc
は、Go言語の公式コンパイラです。Goのソースコードを機械語に変換する役割を担っています。このコミットは、コンパイラの内部的な型定義と処理ロジックを変更するものです。
技術的詳細
この変更の核心は、Goコンパイラがrune
型をどのように解釈し、内部的に表現するかという点にあります。
-
rune32
フラグの廃止: 以前のコンパイラには、rune
型をint
として扱うかint32
として扱うかを制御するrune32
というグローバル変数(フラグ)が存在しました。このコミットでは、src/cmd/gc/go.h
からEXTERN int rune32;
の宣言が削除され、src/cmd/gc/lex.c
からもexper
配列内の{"rune32", &rune32}
のエントリがコメントアウトされました。これは、rune
の型がもはや条件付きではなく、常に固定されることを意味します。 -
runetype
の固定化:src/cmd/gc/lex.c
のlexinit1
関数は、字句解析器の初期化を行う部分です。この関数内で、rune
シンボルに対応する型(runetype
)が定義されていました。変更前はrune32
フラグの値に応じてtyp(TINT)
(int
型)またはtyp(TINT32)
(int32
型)が選択されていましたが、このコミットにより、常にrunetype = typ(TINT32);
と設定されるようになりました。これにより、rune
は常に32ビット符号付き整数として扱われることが保証されます。 -
テストコードの更新:
test/rune.go
ファイルは、rune
型の振る舞いをテストするためのものです。このコミットでは、r7 int32
という新しい変数が追加され、既存の[]rune
スライスr
にr7
が追加されました。これは、rune
がint32
と互換性を持つことを示すためのテストケースの更新です。これにより、int32
型の値をrune
型のスライスに直接含めることができるようになり、rune
がint32
のエイリアスとして機能することが確認されます。
この変更により、Go言語のrune
型は、プラットフォームに依存しない固定サイズの型となり、Unicodeコードポイントの表現に最適化されます。これは、Goプログラムの移植性と堅牢性を向上させる上で重要なステップです。
コアとなるコードの変更箇所
src/cmd/gc/go.h
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -828,8 +828,6 @@ EXTERN int funcdepth;
EXTERN int typecheckok;
EXTERN int compiling_runtime;
-EXTERN int rune32;
-
/*
* y.tab.c
*/
rune32
というグローバル変数の宣言が削除されました。これは、rune
の型を動的に決定する必要がなくなったことを示します。
src/cmd/gc/lex.c
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -37,7 +37,7 @@ static struct {
char *name;
int *val;
} exper[] = {
-\t{\"rune32\", &rune32},
+//\t{\"rune32\", &rune32},
};
static void
@@ -1842,10 +1842,7 @@ lexinit1(void)\
// rune alias
s = lookup("rune");
s->lexical = LNAME;
-\tif(rune32)
-\t\trunetype = typ(TINT32);\
-\telse
-\t\trunetype = typ(TINT);\
+\trunetype = typ(TINT32);
runetype->sym = s;
s1 = pkglookup("rune", builtinpkg);
s1->lexical = LNAME;
exper
配列からrune32
に関連するエントリがコメントアウトされ、lexinit1
関数内でrunetype
が常にtyp(TINT32)
に設定されるようになりました。これにより、rune
型は常にint32
として扱われます。
test/rune.go
--- a/test/rune.go
+++ b/test/rune.go
@@ -14,8 +14,9 @@ var (
r4 = 'a'/2
r5 = 'a'<<1
r6 = 'b'<<2
+\tr7 int32
-\tr = []rune{r0, r1, r2, r3, r4, r5, r6}
+\tr = []rune{r0, r1, r2, r3, r4, r5, r6, r7}
)
var (
int32
型の変数r7
が追加され、[]rune
スライスにその変数が含まれるようになりました。これは、rune
がint32
のエイリアスとして機能することを確認するためのテストです。
コアとなるコードの解説
このコミットの主要な変更は、Goコンパイラの内部でrune
型がどのように扱われるかを根本的に変更するものです。
src/cmd/gc/go.h
とsrc/cmd/gc/lex.c
における変更は、コンパイラがrune
型をint
とint32
のどちらにするかを選択するロジックを完全に削除し、代わりにint32
に固定することを意味します。これは、rune
がUnicodeコードポイントを表現するというその目的を考えると、より適切で堅牢な設計です。int
型がプラットフォームによってサイズが異なるという不確実性を排除することで、Goプログラムの移植性が向上し、rune
のセマンティクスがより明確になります。
test/rune.go
の変更は、この新しい定義が実際に機能することを確認するためのものです。int32
型の変数を[]rune
に直接追加できるようになったことは、rune
がint32
のエイリアスとして正しく機能していることの直接的な証拠となります。
全体として、このコミットはGo言語の文字と文字列処理の基盤を強化し、Unicodeの国際化対応をより確実なものにするための重要な一歩です。
関連リンク
- Go言語の
rune
型に関する公式ドキュメントやブログ記事(当時のものがあれば) - Unicodeのコードポイントに関する情報
参考にした情報源リンク
- Go言語の公式リポジトリ
- Go Code Review (CL 5467049) - このコミットのコードレビューページ。詳細な議論や背景情報が含まれている可能性があります。
- Go言語の
rune
に関するドキュメント (Go Blog: Strings, bytes, runes and characters in Go) - このブログ記事は、Goにおける文字列、バイト、rune、文字の概念を詳しく解説しており、rune
がUnicodeコードポイントを表すint32
のエイリアスであることについて触れています。 - Unicodeの公式ウェブサイト - Unicodeのコードポイントに関する詳細情報。