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

[インデックス 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/parsergo/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つのファイルに集中しています。

  1. 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
    
  2. src/pkg/exp/gotype/gotype.go:

    • parseComments という新しいブール型フラグが定義されました。
    • parse 関数内で、parseCommentsprintAST の両方が true の場合に、パーサーの modeparser.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

  1. フラグの定義:

    parseComments = flag.Bool("comments", false, "parse comments (ignored if -ast not set)")
    

    flag.Bool は、コマンドライン引数からブール値のフラグを定義するためのGoの標準ライブラリ関数です。ここでは、comments という名前のフラグを定義し、デフォルト値を false に設定しています。第三引数の文字列は、gotype -h のようにヘルプを表示した際に表示される説明文です。この説明文には、「-ast が設定されていない場合は無視される」という重要な制約が明記されています。

  2. パースモードの条件付き設定:

    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 および go/ast パッケージのソースコード
  • 抽象構文木に関する一般的なプログラミング言語の概念