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

[インデックス 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言語では、runeintのエイリアスとして定義されていました。しかし、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に変換することで、各文字を個別のコードポイントとして処理できます。

intint32

  • 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型をどのように解釈し、内部的に表現するかという点にあります。

  1. rune32フラグの廃止: 以前のコンパイラには、rune型をintとして扱うかint32として扱うかを制御するrune32というグローバル変数(フラグ)が存在しました。このコミットでは、src/cmd/gc/go.hからEXTERN int rune32;の宣言が削除され、src/cmd/gc/lex.cからもexper配列内の{"rune32", &rune32}のエントリがコメントアウトされました。これは、runeの型がもはや条件付きではなく、常に固定されることを意味します。

  2. runetypeの固定化: src/cmd/gc/lex.clexinit1関数は、字句解析器の初期化を行う部分です。この関数内で、runeシンボルに対応する型(runetype)が定義されていました。変更前はrune32フラグの値に応じてtyp(TINT)int型)またはtyp(TINT32)int32型)が選択されていましたが、このコミットにより、常にrunetype = typ(TINT32);と設定されるようになりました。これにより、runeは常に32ビット符号付き整数として扱われることが保証されます。

  3. テストコードの更新: test/rune.goファイルは、rune型の振る舞いをテストするためのものです。このコミットでは、r7 int32という新しい変数が追加され、既存の[]runeスライスrr7が追加されました。これは、runeint32と互換性を持つことを示すためのテストケースの更新です。これにより、int32型の値をrune型のスライスに直接含めることができるようになり、runeint32のエイリアスとして機能することが確認されます。

この変更により、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スライスにその変数が含まれるようになりました。これは、runeint32のエイリアスとして機能することを確認するためのテストです。

コアとなるコードの解説

このコミットの主要な変更は、Goコンパイラの内部でrune型がどのように扱われるかを根本的に変更するものです。

src/cmd/gc/go.hsrc/cmd/gc/lex.cにおける変更は、コンパイラがrune型をintint32のどちらにするかを選択するロジックを完全に削除し、代わりにint32に固定することを意味します。これは、runeがUnicodeコードポイントを表現するというその目的を考えると、より適切で堅牢な設計です。int型がプラットフォームによってサイズが異なるという不確実性を排除することで、Goプログラムの移植性が向上し、runeのセマンティクスがより明確になります。

test/rune.goの変更は、この新しい定義が実際に機能することを確認するためのものです。int32型の変数を[]runeに直接追加できるようになったことは、runeint32のエイリアスとして正しく機能していることの直接的な証拠となります。

全体として、このコミットはGo言語の文字と文字列処理の基盤を強化し、Unicodeの国際化対応をより確実なものにするための重要な一歩です。

関連リンク

  • Go言語のrune型に関する公式ドキュメントやブログ記事(当時のものがあれば)
  • Unicodeのコードポイントに関する情報

参考にした情報源リンク