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

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

# 使用環境
- Visual Studio Code 1.40.1
- Modern Fortran Extension 2.1.1

# VSCodeのユーザースニペット
VSCodeには，コードの断片とそれに対応する記述子を登録しておき，記述子を入力するだけで対応するコード断片を呼び出すことができます．
VSCodeでは，VSCodeが認識しているファイル形式ごとに，ユーザースニペットの設定を記述します．まずは，Fortranのソースファイルを認識させるために，[Modern Fortran拡張](https://marketplace.visualstudio.com/items?itemName=krvajalm.linter-gfortran)をインストールしておきましょう．

VSCodeのメニューバーから，ファイル→基本設定→ユーザースニペットと辿ると，VSCodeが認識しているファイル形式の一覧が出てきます．
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224040/eec854b2-0b98-3405-da38-2a83cf80b574.png)


その中から，FortranFreeFormを選択すると，FortranFreeForm.jsonが作られます．
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224040/67cd70c8-fd73-62e3-0815-b6fc93d42ab4.png)


```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`
1. Fortranの組み込みモジュールの`use`
1. 型宣言
1. 名前付きの構文

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

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

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

```json
	"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)`等は，個別にスニペットに登録しておくと，入力効率が劇的に改善します．
`i4`や`r4`などとして登録しておき，`allocatable`属性付きの宣言は，記述子に`a`を足す，などと独自のルールを決めるとよいでしょう．

```json
	"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:ラベル}`）も可能です．

```json
	"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拡張によって，`program`や`do`の入力を簡略化できています．しかし，`intrinsic`が入力候補に出てこなかったり，`real64`のように，入力候補に出てはくるが，結局残り1文字まで入力しなければならないなど，今一な感じがします．また，名前付き`do`構文には対応していません．

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224040/1f047518-30ee-c99f-6b3e-53dba7be3932.gif)

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

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224040/55fed2e9-728a-dc6f-e043-9c3aeecb3e5c.gif)


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