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

[インデックス 19079] ファイルの概要

このコミットは、Go言語のコンパイラの一部であった src/cmd/gc/gen.c ファイルに対する変更です。gen.c は、Go 1.5でコンパイラがGo言語自体で書き直される以前の、C言語で実装されていたGoコンパイラ(cmd/gc)のコード生成フェーズに関連するファイルでした。具体的には、抽象構文木(AST)を中間表現に変換し、最終的な機械語コード生成のための準備を行う役割を担っていました。

コミット

cmd/gc: 単一行のif文の本体から { } を削除

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/8f8ada008c7b614dea948728ffd69aea22f64ebd

元コミット内容

commit 8f8ada008c7b614dea948728ffd69aea22f64ebd
Author: Jan Ziak <0xe2.0x9a.0x9b@gmail.com>
Date:   Wed Apr 9 15:39:28 2014 +0200

    cmd/gc: drop { } around single-line if-statement body
    
    LGTM=rsc
    R=rsc
    CC=golang-codereviews
    https://golang.org/cl/85890043
---
 src/cmd/gc/gen.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 5a5c1c24c1..17c0a7082d 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -301,9 +301,8 @@ gen(Node *n)
 		break;
 
 	case OLABEL:
-\t\tif(isblanksym(n->left->sym)) {\n+\t\tif(isblanksym(n->left->sym))\n \t\t\tbreak;\n-\t\t}\n \t\t
 \t\tlab = newlab(n);
 

変更の背景

この変更は、Go言語のコンパイラ(当時はC言語で書かれていた)のソースコードにおけるコーディングスタイルの一貫性を保つためのものです。C言語では、if文の本体が単一のステートメントである場合、波括弧 {} を省略することが可能です。GoプロジェクトのC言語コードベースでは、このような場合に波括弧を省略するスタイルが採用されていたと考えられます。このコミットは、既存のコードがそのスタイルに従っていなかった箇所を修正し、コードベース全体の統一性を高めることを目的としています。

前提知識の解説

Go言語の旧コンパイラ (cmd/gc)

Go言語の初期のコンパイラは、C言語で書かれていました。これは cmd/gc と呼ばれ、Go 1.5がリリースされる2015年まで使用されていました。Go 1.5以降、コンパイラ自体がGo言語で書き直され(ブートストラップ)、現在のGoコンパイラはGo言語で実装されています。このコミットは、C言語で書かれた古いコンパイラに対する変更であり、現在のGoコンパイラのコードベースとは直接関係ありません。

C言語における if 文の構文

C言語では、if 文の構文は以下のようになります。

if (条件式) {
    // 複数のステートメント
}

または、本体が単一のステートメントである場合は、波括弧を省略できます。

if (条件式)
    // 単一のステートメント;

このコミットは、後者の形式に統一するための変更です。

isblanksym 関数

isblanksym は、Go言語の旧Cコンパイラ内で使用されていた関数で、特定のシンボルがGoの「ブランク識別子」(_)であるかどうかをチェックするために使われていました。Go言語では、_ は値を破棄するために使用される特別な識別子です。コンパイラは、このようなブランク識別子に関連する処理を適切に行う必要がありました。

技術的詳細

このコミットは、src/cmd/gc/gen.c ファイル内の gen 関数における OLABEL ケースの処理を変更しています。

変更前は以下のようになっていました。

case OLABEL:
    if(isblanksym(n->left->sym)) {
        break;
    }
    
    lab = newlab(n);

変更後は以下のようになっています。

case OLABEL:
    if(isblanksym(n->left->sym))
        break;
    
    lab = newlab(n);

この変更は、C言語の構文規則に基づいています。if 文の直後に続くステートメントが単一である場合、波括弧 {} は省略可能です。このケースでは、if(isblanksym(n->left->sym)) の条件が真の場合に実行されるのは break; という単一のステートメントのみです。したがって、波括弧を削除してもC言語の構文としては有効であり、コードの動作に影響はありません。

この変更の目的は、コードの冗長性を減らし、GoプロジェクトのC言語コードベースにおけるコーディングスタイルガイドライン(もし存在すれば)に準拠することです。これにより、コードの可読性と一貫性が向上します。

コアとなるコードの変更箇所

--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -301,9 +301,8 @@ gen(Node *n)
 		break;
 
 	case OLABEL:
-\t\tif(isblanksym(n->left->sym)) {\n+\t\tif(isblanksym(n->left->sym))\n \t\t\tbreak;\n-\t\t}\n \t\t
 \t\tlab = newlab(n);
 

コアとなるコードの解説

gen 関数は、Goコンパイラのコード生成フェーズの一部であり、抽象構文木(AST)のノード n を処理します。OLABEL は、Go言語のラベル(goto 文のターゲットなど)を表すノードタイプです。

このコードブロックは、OLABEL ノードを処理する際に、そのラベルがブランク識別子 _ に関連付けられているかどうかをチェックしています。

  • n->left->sym: n は現在のASTノードであり、left はその子ノードへのポインタ、sym はそのノードに関連付けられたシンボル(識別子など)を表します。
  • isblanksym(...): この関数は、与えられたシンボルがブランク識別子 _ である場合に真を返します。

変更前は、if 文の条件が真の場合に実行される break; ステートメントが波括弧で囲まれていました。

if(isblanksym(n->left->sym)) {
    break;
}

変更後は、波括弧が削除され、単一の break; ステートメントが if 文の直下に配置されています。

if(isblanksym(n->left->sym))
    break;

この変更は、C言語の構文規則に完全に準拠しており、機能的な違いは一切ありません。純粋にコードのスタイルと一貫性を改善するためのリファクタリングです。

関連リンク

参考にした情報源リンク

  • Google検索: "Go cmd/gc gen.c compiler role"
  • Google検索: "Go coding style single line if statement"
  • Stack Overflow, Medium, Go.dev, Codecademy, Go By Example, Dev.to, Tutorialspoint, YourBasic.org などのGo言語およびC言語に関するドキュメントやチュートリアル。
  • Go言語の公式ドキュメント。
  • GitHubのgolang/goリポジトリのコミット履歴。
  • Go言語のコードレビューシステム (Gerrit) のCL (Change List) 85890043。