[インデックス 1423] ファイルの概要
このコミットは、Go言語の初期開発段階における内部的な変更を記録したものです。gosrc
ディレクトリ内のコードが再びコンパイルできるようにするための修正と、保留中の変更のチェックインが含まれています。特に、このコードベースは当時のGo言語の既存の仕様とは完全に一致しないものの、大規模なコードベースであり、コンパイル可能であることが強調されています。将来的にはこのコードは廃止される予定であるとも述べられています。
コミット
commit af065a0c7783d33e01e75f43e07db681dadbf21e
Author: Robert Griesemer <gri@golang.org>
Date: Tue Jan 6 16:26:45 2009 -0800
- make code in gosrc compile again, check in all pending changes
(this code doesn't match the existing language at this point,
but it's a large code base which compiles - will eventually go
away)
- enable compilation of it again in run.bash
R=r
DELTA=1147 (534 added, 311 deleted, 302 changed)
OCL=22176
CL=22176
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/af065a0c7783d33e01e75f43e07db681dadbf21e
元コミット内容
- make code in gosrc compile again, check in all pending changes
(this code doesn't match the existing language at this point,
but it's a large code base which compiles - will eventually go
away)
- enable compilation of it again in run.bash
変更の背景
このコミットは、Go言語の初期開発フェーズ、具体的には2009年1月に行われたものです。コミットメッセージから、gosrc
ディレクトリ内のコードが一時的にコンパイルできない状態になっていたことが伺えます。Go言語は2007年後半にGoogleで開発が始まり、2009年11月に一般公開されました。このコミットは、その公開前の内部開発段階におけるスナップショットであり、Robert Griesemer氏(Go言語の主要設計者の一人)によって行われました。
当時のGo言語の仕様はまだ流動的であり、このgosrc
内のコードベースは、現在のGo言語とは異なる古い言語仕様に基づいている可能性が高いです。コミットメッセージにある「this code doesn't match the existing language at this point, but it's a large code base which compiles - will eventually go away」という記述は、このコードが一時的なものであり、最終的には新しい言語仕様に合わせたコードに置き換えられる予定であったことを示唆しています。
変更の主な目的は、開発中のコンパイラがこの大規模なコードベースを再びコンパイルできるようにし、開発の継続性を確保することでした。また、run.bash
スクリプトでこのgosrc
のコンパイルを再度有効にすることで、ビルドプロセスに統合されています。
前提知識の解説
このコミットの変更内容を理解するためには、以下のGo言語(または一般的なコンパイラ)に関する基本的な概念を理解しておく必要があります。
- AST (Abstract Syntax Tree): 抽象構文木。ソースコードの構文構造を木構造で表現したものです。コンパイラの構文解析フェーズで生成され、その後の意味解析やコード生成の基盤となります。
ast.go
ファイルはこのASTのノード定義を含んでいます。 - Scanner (Lexer): 字句解析器。ソースコードを読み込み、トークン(予約語、識別子、演算子、リテラルなど)のストリームに変換するコンパイラの最初のフェーズです。
- Parser (構文解析器): トークンのストリームを読み込み、言語の文法規則に従ってASTを構築するコンパイラのフェーズです。
parser.go
ファイルはこの機能を提供します。 - Type System: 型システム。プログラミング言語におけるデータ型の定義、型チェックの規則、型推論などを扱うシステムです。
type.go
やglobals.go
の一部で定義されています。 - Object: プログラム内のエンティティ(変数、定数、関数、型など)を表す抽象概念です。
object.go
やglobals.go
で定義されています。 - Scope: スコープ。識別子(変数名など)が有効なプログラムの領域を定義します。スコープはネストすることができ、識別子の解決(どの宣言に対応するかを見つけること)に用いられます。
globals.go
でScope
構造体が定義されています。 - Compilation Unit: コンパイル単位。コンパイラが一度に処理するソースコードの単位です。Go言語では通常、パッケージがこれに該当します。
compilation.go
はこのコンパイルプロセスを管理します。 - Export/Import: パッケージ間で定義を共有するメカニズムです。
export.go
とimport.go
は、コンパイラがパッケージのインターフェースをエクスポート(外部に公開)およびインポート(取り込み)する方法を扱います。 new()
とmake()
: Go言語におけるメモリ割り当ての組み込み関数です。new()
はゼロ値で初期化された型のポインタを返し、make()
はスライス、マップ、チャネルといった組み込み型を初期化して返します。このコミットでは、new(*Type)
のような古い形式からnew(Type)
のような新しい形式への変更が見られます。これは、Go言語の初期の文法が現在のものと異なっていたことを示唆しています。
技術的詳細
このコミットは、Go言語のコンパイラ(gosrc
)の複数のコンポーネントにわたる広範な変更を含んでいます。主な変更点は以下の通りです。
-
ASTノードの拡張と統一:
usr/gri/gosrc/ast.go
:Literal
,Object
,Deref
,Selector
,Call
,Tuple
といった新しいASTノードが導入され、それぞれにop()
メソッドが追加されています。これにより、ASTノードの種類を識別するための統一的なメカニズムが提供されます。特にTuple
ノードの導入は、複数の戻り値を扱うGo言語の特性をASTレベルで表現するための重要な変更です。new(*Type)
のようなポインタ型を返すnew
の呼び出しがnew(Type)
のように値型を返すように変更されています。これはGo言語の初期の文法が現在のものと異なっていたことを示唆しており、より現代的なGoのnew
の振る舞いに近づけるための変更と考えられます。
-
エラー報告の改善:
usr/gri/gosrc/compilation.go
:LineCol
関数が追加され、ソースコード内の位置(行と列)を正確に特定できるようになりました。また、Error
関数が大幅に改善され、エラーメッセージにファイル名、行番号、列番号を含めるようになりました。これにより、コンパイルエラーのデバッグが容易になります。エラー報告の頻度を制限するロジック(errdist
とnerrors
)も導入されています。
-
型システムとオブジェクト定義の更新:
usr/gri/gosrc/globals.go
:Type
構造体のフィールド名が変更されています(例:len_
からlen
、aux
からkey
)。これは、型システムが進化し、より明確なセマンティクスを持つようになったことを示しています。Object
構造体にはBUILTIN
(組み込み関数)のkind
が追加され、Expr
インターフェースにop()
メソッドが追加されています。usr/gri/gosrc/object.go
:BUILTIN
という新しいオブジェクトの種類が追加され、組み込み関数を識別できるようになりました。
-
パーサーロジックの修正とセマンティックチェックの分離:
usr/gri/gosrc/parser.go
:- パーサーの内部状態を保持するフィールド名が変更されています(例:
S
からscanner
、C
からtokchan
)。 semantic_checks
フラグが削除され、パーサーが構文解析に専念し、セマンティックチェックのロジックがexpr.go
のような別のモジュールに分離されたことを示唆しています。これにより、コンパイラの各フェーズの責任がより明確になります。- 関数シグネチャの解析ロジックが変更され、レシーバーの有無に応じた
FUNCTION
とMETHOD
の区別がより明確になりました。また、複数の戻り値を扱うためのTuple
型が導入されています。 ParseQualifiedIdent
、ParseVarType
、ParseTypeName
、ParsePointerType
などの関数で、セマンティックチェックのロジックが削除または簡略化されています。ParseOperand
からNIL
,IOTA
,TRUE
,FALSE
,NEW
といったリテラルやキーワードの直接的なASTノード生成が削除され、より汎用的なExpr
パッケージの関数を呼び出すように変更されています。ParseSelectorOrTypeAssertion
,ParseIndexOrSlice
,ParseCall
,ParseUnaryExpr
,ParseBinaryExpr
といった式解析の関数が、新しく導入されたExpr
パッケージの関数を呼び出すように変更されています。これにより、式に関するセマンティックな処理がExpr
パッケージに集約され、パーサーは構文解析に集中できるようになります。ParseSimpleStat
における変数宣言(:=
)と代入(=
)の処理が改善され、複数の変数と式の対応関係がより厳密にチェックされるようになりました。
- パーサーの内部状態を保持するフィールド名が変更されています(例:
-
新しい
expr.go
ファイルの導入:usr/gri/gosrc/expr.go
が新規に作成されています。このファイルは、式のセマンティックな処理(型チェック、デリファレンス、セレクタ、インデックス、スライス、関数呼び出しなど)をカプセル化する役割を担っています。これにより、コンパイラの設計がモジュール化され、保守性が向上しています。
-
run.bash
の変更:src/run.bash
で、usr/gri/gosrc
ディレクトリのコンパイルをコメントアウトしていた部分が解除され、再びコンパイルが有効になっています。
これらの変更は、Go言語のコンパイラが初期の実験的な段階から、より構造化され、堅牢な設計へと移行していく過程を示しています。特に、ASTの統一、エラー報告の改善、セマンティックチェックの分離、そしてexpr.go
のような新しいモジュールによる機能の集約は、コンパイラの品質と保守性を高める上で重要なステップです。
コアとなるコードの変更箇所
src/run.bash
:- L52-L57:
usr/gri/gosrc
のコンパイルを有効化。
- L52-L57:
usr/gri/gosrc/ast.go
:- L14-L20: 新しい定数
LITERAL
,OBJECT
,DEREF
,SELECT
,CALL
,TUPLE
の定義。 - L28, L40, L55, L79, L94, L110: 各ASTノードに
op()
メソッドを追加。 - L38, L53, L77:
new(*Type)
からnew(Type)
への変更。 - L67-L74:
Deref
構造体とNewDeref
関数の追加。 - L89-L96:
Call
構造体とNewCall
関数の追加。 - L104-L128:
Tuple
構造体とNewTuple
関数の追加。
- L14-L20: 新しい定数
usr/gri/gosrc/compilation.go
:- L22-L44:
LineCol
関数と改善されたError
関数の追加。 - L133-L134:
comp.src_file
とcomp.src
の初期化。 - L137-L138, L143-L144:
new(*Scanner.Scanner)
からnew(Scanner.Scanner)
、new(*Parser.Parser)
からnew(Parser.Parser)
への変更。 - L140:
make(chan *Scanner.Token, 100)
への変更。 - L148-L149: エラーチェックの変更。
- L22-L44:
usr/gri/gosrc/export.go
:- L174-L175:
Type.VOID
ケースの追加。 - L179-L180:
Type.ALIAS
,Type.MAP
のtyp.aux
からtyp.key
への変更。 - L183:
Type.TUPLE
ケースの追加。 - L186:
typ.len_
からtyp.len
への変更。 - L189:
typ.flags
からtyp.aux
への変更。 - L192:
Type.FUNCTION
にType.METHOD
を追加し、typ.flags
からtyp.len
への変更。 - L200:
Type.REFERENCE
の削除。 - L270:
Universe.types.len_
からUniverse.types.len
への変更。
- L174-L175:
usr/gri/gosrc/expr.go
:- L1-L164: 新規ファイル。
Deref
,Select
,AssertType
,Index
,Slice
,Call
,UnaryExpr
,BinaryExpr
といった式のセマンティック処理を行う関数群を定義。
- L1-L164: 新規ファイル。
usr/gri/gosrc/globals.go
:- L31-L32:
Type
構造体のフィールド名変更 (flags
削除,len_
からlen
,aux
からkey
,elt
のコメント変更)。 - L54:
List
構造体のlen_
からlen
への変更。 - L69-L73:
Flags
構造体からscan
,parse
,ast
,deps
フラグの削除。 - L77:
Environment
構造体のError
フィールドの型変更。 - L84-L88:
Compilation
構造体にsrc_file
,src
,nerrors
,errpos
フィールドの追加。 - L91:
Expr
インターフェースにop()
メソッドの追加。 - L114:
Elem
構造体のtype
からexport type
への変更。 - L119, L124, L129, L134, L139:
new(*Type)
からnew(Type)
への変更。 - L191:
List
のlen_
からlen
への変更。 - L196:
List
のlen_
からlen
への変更。 - L200:
new(*Elem)
からnew(Elem)
への変更。 - L242-L244:
ExprAt
関数の追加。 - L294-L296:
Add
関数の追加。
- L31-L32:
usr/gri/gosrc/go.go
:- L20-L25:
PrintHelp
から古いフラグの説明を削除。 - L49, L81, L88:
new(*Type)
からnew(Type)
への変更。 - L69-L74: コマンドライン引数処理から古いフラグの処理を削除。
- L83:
env.Error = &Compilation.Error;
の追加。
- L20-L25:
usr/gri/gosrc/import.go
:- L200-L202:
Type.VOID
ケースの追加。 - L204-L205:
Type.TUPLE
ケースの追加。 - L207-L208:
typ.aux
からtyp.key
への変更。 - L211:
typ.len_
からtyp.len
への変更。 - L214:
typ.flags
からtyp.aux
への変更。 - L217:
Type.FUNCTION
にType.METHOD
を追加し、typ.flags
からtyp.len
への変更。 - L225:
Type.REFERENCE
の削除。
- L200-L202:
usr/gri/gosrc/object.go
:- L9-L10:
BUILTIN
定数の追加。 - L27:
BUILTIN
の文字列表現を追加。
- L9-L10:
usr/gri/gosrc/parser.go
:- L12:
import Expr "expr"
の追加。 - L15-L16:
semantic_checks
フィールドの削除。 - L18-L19:
S
からscanner
、C
からtokchan
へのフィールド名変更。 - L52, L65:
indent
のインクリメント/デクリメントロジックの変更。 - L70, L72:
P.S.Scan()
からP.scanner.Scan()
、<- P.C
から<- P.tokchan
への変更。 - L89-L90:
S
からscanner
、C
からtokchan
への引数名変更。 - L95:
P.S.Error
からP.scanner.Error
への変更。 - L137-L139:
semantic_checks
関連のコード削除。 - L157-L160:
MakeFunctionType
の引数とロジック変更(check_recv
削除、p0
のチェック強化)。 - L164-L165:
typ.flags
からtyp.len
への変更。 - L168-L173: 戻り値の型処理の変更(
Tuple
の導入)。 - L189-L190:
typ.flags & Type.RECV
からtyp.form == Type.METHOD
への変更。 - L213: エラーメッセージの変更。
- L313-L349:
ParseQualifiedIdent
からsemantic_checks
関連のコード削除。 - L376-L390:
ParseVarType
からsemantic_checks
関連のコード削除。 - L399-L413:
ParseTypeName
からsemantic_checks
関連のコード削除。 - L427:
typ.len_
からtyp.len
へのコメント変更。 - L445, L448, L452:
typ.flags
からtyp.aux
への変更。 - L479-L494:
TryResult
からParseResult
への変更とロジック修正。 - L499-L530:
ParseAnonymousSignature
からParseSignature
への変更とロジック修正。 - L579, L590, L609:
sig.entries.len_
からsig.entries.len
への変更。 - L668:
typ.aux
からtyp.key
への変更。 - L707-L879:
ParsePointerType
からsemantic_checks
関連のコード削除と、暗黙的な前方宣言のロジック修正。 - L892-L915:
ParseNew
関数の削除。 - L989-L1000:
ParseOperand
からsemantic_checks
関連のコード削除と、AST.NewObject
の呼び出し。 - L1010-L1024:
NIL
,IOTA
,TRUE
,FALSE
,NEW
の処理を削除。 - L1071-L1094:
ParseSelectorOrTypeAssertion
からsemantic_checks
関連のコード削除と、Expr.Select
,Expr.AssertType
の呼び出し。 - L1115-L1140:
ParseIndexOrSlice
からsemantic_checks
関連のコード削除と、Expr.Slice
,Expr.Index
の呼び出し。 - L1164-L1167:
ParseCall
からsemantic_checks
関連のコード削除と、Expr.Call
の呼び出し。 - L1221-L1228:
ParseUnaryExpr
のロジック修正。 - L1261-L1270:
ParseBinaryExpr
からAST.BinaryExpr
の直接生成を削除し、Expr.BinaryExpr
の呼び出し。 - L1309-L1317:
ConvertToExprList
のロジック修正。 - L1327-L1328:
ParseIdentOrExpr
のロジック修正。 - L1368-L1384:
ListArity
関数の追加。 - L1389-L1400:
ParseSimpleStat
におけるラベル宣言のロジック修正。 - L1403-L1419:
ParseSimpleStat
における変数宣言(:=
)のロジック修正。 - L1422-L1439:
ParseSimpleStat
における代入(=
)のロジック修正。 - L1739-L1757:
ParseImportSpec
からsemantic_checks
関連のコード削除と、pkg.obj.pnolev
のリセット。 - L1831-L1832:
typ.aux
からtyp.key
への変更。 - L2012-L2014:
ResolveForwardTypes
からsemantic_checks
関連のコード削除。
- L12:
コアとなるコードの解説
このコミットの核心は、Go言語コンパイラの内部構造をよりモジュール化し、セマンティック解析の責任を明確に分離することにあります。
-
ASTの統一と拡張:
ast.go
におけるop()
メソッドの導入と新しいASTノード(特にTuple
)の追加は、コンパイラがGo言語の構文要素をより一貫した方法で表現し、処理できるようにするための基盤を築いています。Tuple
の導入は、Goの多値戻り値や多重代入といった特徴をASTレベルでサポートするために不可欠です。また、new(*Type)
からnew(Type)
への変更は、Go言語の初期の文法が現在のものと異なっていたことを示唆しており、より現代的なGoのnew
の振る舞いに近づけるための変更と考えられます。 -
expr.go
の導入によるセマンティック解析の分離: 最も重要な変更の一つは、usr/gri/gosrc/expr.go
という新しいファイルが導入されたことです。このファイルは、式のデリファレンス、セレクタ(フィールドアクセスやメソッド呼び出し)、インデックス、スライス、関数呼び出しといった、式のセマンティックな側面を処理する関数群をカプセル化しています。これにより、parser.go
は純粋な構文解析に集中できるようになり、コンパイラの各フェーズの責任が明確に分離されました。これは、コンパイラの設計原則における「関心の分離」を具現化したものであり、コードの可読性、保守性、拡張性を大幅に向上させます。 -
パーサーの簡素化:
parser.go
からsemantic_checks
フラグが削除され、多くのセマンティックチェックロジックがexpr.go
に移動したことで、パーサーのコードが大幅に簡素化されました。これにより、パーサーはトークンストリームからASTを構築するという本来の役割に集中できるようになります。例えば、以前はパーサー内で直接行われていた型チェックやオブジェクト解決の一部が、Expr
パッケージの関数を呼び出す形に変更されています。 -
エラー報告の改善:
compilation.go
におけるLineCol
関数と改善されたError
関数は、コンパイルエラーの診断能力を飛躍的に向上させます。正確な行番号と列番号、そしてエラーメッセージの表示は、開発者が問題を迅速に特定し、修正するために不可欠です。
これらの変更は、Go言語のコンパイラが初期のプロトタイプ段階から、より洗練された実用的なツールへと進化していく過程における重要なマイルストーンを示しています。モジュール化された設計は、将来の機能追加や言語仕様の変更にも柔軟に対応できる基盤を提供します。
関連リンク
- Go言語公式ウェブサイト: https://go.dev/
- Go言語の歴史に関する情報: https://go.dev/doc/history
参考にした情報源リンク
- Web検索結果 (Google Search): "golang gosrc compiler 2009 Robert Griesemer af065a0c7783d33e01e75f43e07db681dadbf21e"
- このコミットハッシュは公開されているGoリポジトリの履歴には見つかりませんでしたが、Robert Griesemer氏がGo言語の主要設計者の一人であり、2007年後半から開発が始まったGo言語の初期段階の内部コミットである可能性が高いことが示唆されました。
- Go言語の歴史に関するWikipedia記事など、Go言語の初期開発に関する一般的な情報源。