[インデックス 12253] ファイルの概要
このコミットは、Go言語の実験的なツールである gotype に -comments フラグを追加するものです。このフラグを使用することで、抽象構文木(AST)をデバッグする際に、ソースコード内のコメントも一緒にパースして表示できるようになります。
コミット
commit e952e241ae2f8b33fe60da7640c90afbf0f4307f
Author: Robert Griesemer <gri@golang.org>
Date: Mon Feb 27 21:35:26 2012 -0800
gotype: provide -comments flag
When debugging ASTs, it's useful to also
see the comments on occasion. Usage:
gotype -ast -comments file.go
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5703043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e952e241ae2f8b33fe60da7640c90afbf0f4307f
元コミット内容
gotype: provide -comments flag
ASTをデバッグする際、コメントも時折確認できると便利です。使用法:
gotype -ast -comments file.go
変更の背景
このコミットは、Go言語のコンパイラやツール開発において、コードの抽象構文木(AST)を解析・デバッグする際の利便性を向上させることを目的としています。通常、ASTはプログラムの構造を表現し、コメントは実行には影響しないため、デフォルトではASTのパース時にコメントは含まれません。しかし、コードの意図を理解したり、特定のツール(例えば、ドキュメンテーション生成ツールや静的解析ツール)がコメントに依存する場合、コメントもASTの一部として扱われることが望ましい場合があります。
コミットメッセージにある「When debugging ASTs, it's useful to also see the comments on occasion.」という記述から、開発者がASTを視覚的に確認したり、プログラムの構造を解析したりする際に、コメントが提供する追加情報が役立つという具体的なニーズがあったことが伺えます。特に、gotype のような型情報やASTを表示するツールにおいて、コメントの有無が解析結果の理解度に影響を与える可能性があります。
前提知識の解説
抽象構文木 (Abstract Syntax Tree, AST)
抽象構文木(AST)は、ソースコードの抽象的な構文構造を木構造で表現したものです。コンパイラやインタプリタがソースコードを解析する際の中間表現として広く利用されます。ASTは、実際の構文(括弧やセミコロンなど)の詳細を省略し、プログラムの論理的な構造(変数宣言、関数呼び出し、制御フローなど)に焦点を当てます。
例えば、x = 1 + 2; というコードは、ASTでは以下のような構造で表現されることがあります。
Assignment
├── Variable: x
└── BinaryExpression: +
├── Literal: 1
└── Literal: 2
ASTは、コンパイラの最適化、コード生成、静的解析、リファクタリングツール、IDEのコード補完機能など、様々な場面で利用されます。
Go言語の go/parser パッケージ
Go言語の標準ライブラリには、GoのソースコードをパースしてASTを生成するための go/parser パッケージが含まれています。このパッケージは、ソースコードを読み込み、トークン化し、構文解析を行い、最終的に go/ast パッケージで定義されたASTノードの集合を返します。
go/parser パッケージの ParseFile 関数は、ファイルのパースを行う主要な関数です。この関数には、パースの挙動を制御するための mode 引数があります。この mode はビットフラグの集合であり、例えば parser.ParseComments フラグを設定することで、パース時にコメントもASTに含めるように指示できます。
gotype ツール
gotype は、Go言語の実験的なツールであり、Goのソースファイルやパッケージの型情報を表示したり、ASTを表示したりする機能を提供します。これは、Go言語のコンパイラやツールチェーンの開発者が、コードの内部表現を理解し、デバッグするために使用する低レベルなツールの一つです。このツールは、Goの go/parser や go/types といったパッケージを利用して、ソースコードを解析します。
技術的詳細
このコミットの技術的な核心は、gotype ツールが go/parser パッケージの ParseFile 関数を呼び出す際に、新しい -comments フラグの状態に応じて parser.ParseComments モードを動的に設定する点にあります。
Goの go/parser パッケージでは、ParseFile 関数に渡す mode 引数によって、パースの挙動を細かく制御できます。parser.ParseComments は、その mode フラグの一つで、これを設定すると、パーサーはソースコード内のコメントを読み込み、それらをASTの一部として ast.CommentGroup 型のノードとして格納します。これらのコメントノードは、通常、関連するASTノード(例えば、関数宣言や変数宣言)に紐付けられます。
コミットの変更点を見ると、gotype.go 内で新しいブール型フラグ parseComments が定義されています。このフラグは、コマンドラインで -comments オプションが指定された場合に true になります。
そして、parse 関数内で、printAST フラグ(-ast オプションに対応)と parseComments フラグの両方が true の場合にのみ、mode 変数に parser.ParseComments をビットOR演算で追加しています。これは、コメントのパースがASTの表示と密接に関連しているため、-ast なしで -comments を指定しても意味がないという設計判断に基づいています。
// src/pkg/exp/gotype/gotype.go の変更点
// ...
var (
// ...
parseComments = flag.Bool("comments", false, "parse comments (ignored if -ast not set)")
// ...
)
func parse(fset *token.FileSet, filename string, src []byte) *ast.File {
// ...
if *parseComments && *printAST { // ここで両方のフラグがtrueの場合にのみ
mode |= parser.ParseComments // parser.ParseComments モードを追加
}
// ...
f, err := parser.ParseFile(fset, filename, src, mode) // このmodeでパースを実行
// ...
}
これにより、gotype -ast -comments file.go と実行された場合、file.go のASTがコメント情報を含んだ形で生成され、表示されるようになります。
コアとなるコードの変更箇所
このコミットによる主要なコード変更は以下の2つのファイルに集中しています。
-
src/pkg/exp/gotype/doc.go:gotypeツールのドキュメントに-commentsフラグの説明が追加されました。
--- a/src/pkg/exp/gotype/doc.go +++ b/src/pkg/exp/gotype/doc.go @@ -34,6 +34,8 @@ The flags are: Verbose mode. Debugging flags: +-comments + Parse comments (ignored if -ast not set). -ast Print AST (disables concurrent parsing). -trace -
src/pkg/exp/gotype/gotype.go:parseCommentsという新しいブール型フラグが定義されました。parse関数内で、parseCommentsとprintASTの両方がtrueの場合に、パーサーのmodeにparser.ParseCommentsを追加するロジックが組み込まれました。
--- a/src/pkg/exp/gotype/gotype.go +++ b/src/pkg/exp/gotype/gotype.go @@ -27,8 +27,9 @@ var ( allErrors = flag.Bool("e", false, "print all (including spurious) errors") // debugging support - printTrace = flag.Bool("trace", false, "print parse trace") - printAST = flag.Bool("ast", false, "print AST") + parseComments = flag.Bool("comments", false, "parse comments (ignored if -ast not set)") + printTrace = flag.Bool("trace", false, "print parse trace") + printAST = flag.Bool("ast", false, "print AST") ) var exitCode = 0 @@ -73,6 +74,9 @@ func parse(fset *token.FileSet, filename string, src []byte) *ast.File {\n if *allErrors {\n mode |= parser.SpuriousErrors\n }\n + if *parseComments && *printAST {\n + mode |= parser.ParseComments\n + }\n if *printTrace {\n mode |= parser.Trace\n }\
コアとなるコードの解説
src/pkg/exp/gotype/doc.go
このファイルは gotype ツールのコマンドラインオプションに関するドキュメントを定義しています。追加された行は、新しい -comments フラグとその機能(コメントをパースするが、-ast フラグが設定されていない場合は無視されること)を説明しています。これはユーザーがツールの新しい機能を理解するために不可欠な情報です。
src/pkg/exp/gotype/gotype.go
-
フラグの定義:
parseComments = flag.Bool("comments", false, "parse comments (ignored if -ast not set)")flag.Boolは、コマンドライン引数からブール値のフラグを定義するためのGoの標準ライブラリ関数です。ここでは、commentsという名前のフラグを定義し、デフォルト値をfalseに設定しています。第三引数の文字列は、gotype -hのようにヘルプを表示した際に表示される説明文です。この説明文には、「-astが設定されていない場合は無視される」という重要な制約が明記されています。 -
パースモードの条件付き設定:
if *parseComments && *printAST { mode |= parser.ParseComments }これは、
gotypeがソースファイルをパースする際の挙動を決定する核心部分です。*parseComments: コマンドラインで-commentsフラグが指定されたかどうか(trueまたはfalse)。*printAST: コマンドラインで-astフラグが指定されたかどうか(trueまたはfalse)。&&: 論理AND演算子。両方の条件がtrueの場合にのみ、続くブロックが実行されます。mode |= parser.ParseComments:mode変数にparser.ParseCommentsフラグを追加します。|=はビットOR代入演算子で、既存のmodeの値にparser.ParseCommentsのビットを追加します。これにより、ParseFile関数が呼び出される際に、コメントもASTに含めるようにパーサーに指示されます。
このロジックにより、gotype はユーザーの要求に応じて、コメントを含むASTを生成できるようになり、ASTのデバッグや解析の柔軟性が向上しました。
関連リンク
- Go言語の
go/parserパッケージのドキュメント: https://pkg.go.dev/go/parser - Go言語の
go/astパッケージのドキュメント: https://pkg.go.dev/go/ast - Go言語の
go/tokenパッケージのドキュメント: https://pkg.go.dev/go/token - Go言語のコードレビューシステム (Gerrit) の変更セット: https://golang.org/cl/5703043
参考にした情報源リンク
- Go言語の公式ドキュメント
go/parserおよびgo/astパッケージのソースコード- 抽象構文木に関する一般的なプログラミング言語の概念