Fortranの面倒なことはユーザスニペットにやらせよう


概要

VSCodeのユーザースニペットの機能を利用して,Fortranの変数宣言等を簡略化しました.

使用環境

  • Visual Studio Code 1.40.1
  • Modern Fortran Extension 2.1.1

VSCodeのユーザースニペット

VSCodeには,コードの断片とそれに対応する記述子を登録しておき,記述子を入力するだけで対応するコード断片を呼び出すことができます.
VSCodeでは,VSCodeが認識しているファイル形式ごとに,ユーザースニペットの設定を記述します.まずは,Fortranのソースファイルを認識させるために,Modern Fortran拡張をインストールしておきましょう.

VSCodeのメニューバーから,ファイル→基本設定→ユーザースニペットと辿ると,VSCodeが認識しているファイル形式の一覧が出てきます.

その中から,FortranFreeFormを選択すると,FortranFreeForm.jsonが作られます.

FortranFreeForm.json
{
    // Place your snippets for FortranFreeForm here. Each snippet is defined under a snippet name and has a prefix, body and
    // description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
    // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the
    // same ids are connected.
    // Example:
    // "Print to console": {
    //  "prefix": "log",
    //  "body": [
    //      "console.log('$1');",
    //      "$2"
    //  ],
    //  "description": "Log output to console"
    // }
}

FortranFreeForm.json(というか新規のユーザースニペットファイル)にはコメントが書かれており,それによると,記述するのは以下の4項目です.

  • スニペットの識別名
  • 記述子
  • 変換されるコード断片
  • スニペットの説明文

識別名は,他のスニペットと重複していなければよいだけなので,識別名はスニペットの説明文と同じとしておくと楽でしょう.

Fortranで登録しておいた方がよいスニペット

Fortranは,配列の取扱いが柔軟であるため,プログラムの実行部分は比較的楽に記述できます.
一方で,型宣言などの宣言部は,非常に長々と書く必要があり,肝心の数値計算のアルゴリズムを記述する前に疲れてしまいます.

手続きの名前と仮引数を書いた後,絶対に欠かすことのできないimplicit noneを書き,仮引数の型宣言を書きます.Fortranは,属性を付与することで変数の特徴(静的変数である,動的割付である,手続き内で読込専用である,など)を指定します.また,Fortranの型名にも,安全でない方言(real*4, real(4)など)が蔓延しています.Fortran2008からは標準で型名が定められましたが,それがreal(real32)と長く,さらにreal32というパラメータを使うにはiso_fortran_envモジュールをuseする必要があるなど,雪だるま式に記述量が増えていきます.

これらのような,言ってしまえば数値計算の本質に関わらない所は,スニペットに登録して簡略化してしまいましょう.
以下のような項目を登録しておくと便利です.

  1. implicit none
  2. Fortranの組み込みモジュールのuse
  3. 型宣言
  4. 名前付きの構文

implicit none

implicit noneは,FortranをFortranたらしめている,最も重要な記述です.本来は標準でimplicit noneが有効になっているべきですが,FORTRANとの後方互換維持のために,そうはなっていません.そのため,数ストロークで入力できるように,スニペットとして登録しておきます.

    "Disable implicit typing": {
        "prefix": "imp",
        "body": [
            "implicit none"
        ],
        "description": "Disable implicit typing"
    }

Fortranの組み込みモジュールのuse

Fortranでは,モジュールをuseする際,組み込みのモジュールに対しては,intrinsicを付けることで,ユーザ定義のモジュールと区別をしています.また,モジュール名もiso_c_bindingieee_arithmetic等,それほど長くはないですが,打ちにくい名前になっています.
これらもスニペットに登録することで,入力の簡略化が測れます.useあるいはus+1文字くらいが適切でしょう.

    "Using iso_fortran_env module": {
        "prefix": "usf",
        "body": [
            "use,intrinsic :: iso_fortran_env"
        ],
        "description": "Using iso_fortran_env module"
    },
    "Using iso_c_binding module": {
        "prefix": "usc",
        "body": [
            "use,intrinsic :: iso_c_binding"
        ],
        "description": "Using iso_c_binding module"
    }

型宣言

integer(int32)real(real32)等は,個別にスニペットに登録しておくと,入力効率が劇的に改善します.
i4r4などとして登録しておき,allocatable属性付きの宣言は,記述子にaを足す,などと独自のルールを決めるとよいでしょう.

    "Declaration of binary32": {
        "prefix": "r4",
        "body": [
            "real(real32)"
        ],
        "description": "Declaration of binary32"
    },
    "Declaration of binary64": {
        "prefix": "r8",
        "body": [
            "real(real64)"
        ],
        "description": "Declaration of binary64"
    },
    "Declaration of 4-bytes-integer": {
        "prefix": "i4",
        "body": [
            "integer(int32)"
        ],
        "description": "Declaration of 4-bytes-integer"
    }

名前付きの構文

Fortranでは,do構文やif構文,block構文などに名前を付けることができます.Fortran拡張をインストールすると,各構文に対するスニペットが利用できるようになりますが,名前付きの構文に関しては用意されていません.特に名前付きblock構文に関しては,スニペットを用意して簡単に利用できるようにすることで,コードの可読性が劇的に向上します.

このとき,$から始まる特殊な記述を用いると,簡単に記述できます.$1,$2,...をコード断片に記述しておくと,記述子がコード断片に変換された後,$1が書かれた場所にカーソルキーが移動します.tabキーで$2, $3...と移動していきます.$0は最後にカーソルが来ます.
ラベル付きの記述(${1:ラベル})も可能です.

    "named do constructor": {
        "prefix": "ndo",
        "body": [
            "${1:name} : do $2 = $3, $4",
            "    $0",
            "end do ${1:name}"
        ],
        "description": "named do constructor"
    },
    "named block constructor": {
        "prefix": "nblock",
        "body": [
            "${1:blockname} : block",
            "    $2",
            "end block ${1:blockname}"
        ],
        "description": "named block constructor"
    }

ユーザスニペットを使った効果

ユーザスニペットを設定したことで,記述がどれくらい簡略化できるか,簡単なプログラムで確認してみます.

ユーザスニペット設定前

ユーザスニペットを設定する前は,Modern Fortran拡張によって,programdoの入力を簡略化できています.しかし,intrinsicが入力候補に出てこなかったり,real64のように,入力候補に出てはくるが,結局残り1文字まで入力しなければならないなど,今一な感じがします.また,名前付きdo構文には対応していません.

ユーザスニペット設定後

ユーザスニペット設定後は,useの記述,型名,名前付きdo構文が簡単に入力できていることが確認できます.

まとめ

FortranはOS以前に誕生したプログラミング言語の後継であり,モダンな言語と比較して,後方互換のために様々な制約があります.そういった面倒くさいところは,ツールを使って解決しましょう.