COBOLは高齢者しか読めないプログラムかどうかを検証するためにFizzBuzzを実装してみた

[「COBOLで書かれた特殊なプログラムなので高齢者しか読めず」というパワーワードに対する反応](https://togetter.com/li/1311821) というTwitterまとめ記事が話題になっており、自分自身もCOBOLを一度も書いたことがなかったので、これは良い機会だと思いCOBOLでFizzBuzzを実装してみました。

環境はUbuntu 16.04 xenial。Linuxで動く[GNU COBOL](https://sourceforge.net/projects/open-cobol/)という物があるらしいのでインストールして、ドキュメントは[ここに](https://open-cobol.sourceforge.io/)すべてまとまっていたので読みながら実装をしてみました。

# インストール

まずGNU COBOLのインストール。元々は Open COBOLという名前だったそうです。

```sh
$ sudo apt-get update
$ sudo apt-get -f install
$ sudo apt-get install open-cobol
```

以上でインストール完了。COBOLコンパイラのバージョンを確認します。

```sh
$ cobc --version
```

```
cobc (OpenCOBOL) 1.1.0
Copyright (C) 2001-2009 Keisuke Nishida / Roger While
Built    Feb 07 2016 10:28:13
Packaged Feb 06 2009 10:30:55 CET
```

無事 OpenCOBOL 1.1.0 がインストールできました。意外と新しく、そして日本人の方が開発されているのですね。

# Hello Worldの実装

次に、[HelloWorldのサンプル](https://open-cobol.sourceforge.io/historical/open-cobol/Hello-World-.html)を参考に実装してみます。

```sh
$ vim hello.cbl
```

```cobol
           IDENTIFICATION DIVISION.
           PROGRAM-ID. hello.
           PROCEDURE DIVISION.
           DISPLAY "Hello World!".
           STOP RUN.
```

編集後、コンパイルして実行。 -x がないと実行形式バイナリではなくシェアードオブジェクトが出力されたので、-x オプションを付けました。細かいオプションは[マニュアル](https://open-cobol.sourceforge.io/HTML/gnucobpg.html#cobc-_002d-The-GnuCOBOL-Compiler)を見て対応。

コードとして、最初に定義部分を3行定義しなくてはいけなかったり、命令の最後が `.` でなくてはいけなかったり、行番号文インデントが必要だったりといろいろと制約が厳しいということにびっくり。

```
$ cobc -x -o hello hello.cbl
$ ./hello
```

```
Hello World!
```

特に問題なくHelloWorldを実装できました。最近の言語だと `print "Hello World!"` などで出力されたりするので新鮮です。

あと実際には以下のように行番号も入れて実装するらしいのですが(よく知らない)、

```cobol
000010     IDENTIFICATION DIVISION.
000020     PROGRAM-ID. hello.
000030     PROCEDURE DIVISION.
000040     DISPLAY "Hello World!".
000050     STOP RUN.
```

この度は、行番号無しで実装していきます。一応この実装でも実行できました。なんかBASICっぽいですね。

# 集計処理の実装

次にサンプルの[集計処理](https://open-cobol.sourceforge.io/HTML/gnucobpg.html#Readability-of-Programs)も実装してみます。

```sh
$ vim sum.cbl
```

```cobol
           IDENTIFICATION DIVISION.
           PROGRAM-ID. SumOfIntegers.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
           01 n   BINARY-LONG.
           01 i   BINARY-LONG.
           01 sumv BINARY-LONG VALUE 0.
           PROCEDURE DIVISION.
           DISPLAY "Enter a positive integer"
           ACCEPT n
           PERFORM VARYING i FROM 1 BY 1 UNTIL i > n
               ADD i TO sumv
           END-PERFORM
           DISPLAY "The sum is " sumv.
```

以上のように実装してみました。データ定義部分とループ実装が増えています。

```sh

$ cobc -x -o sum sum.cbl
$ ./sum
```

```
Enter a positive integer

100
The sum is +0000005050
```

こんな感じで問題なく実装できました。

データ定義部分をまとめなくてはならず。業務ではPICという領域確保をしながらデータ構造を構築するようです。あとサンプルにあったsumが予約語で使えませんでした。COBOLは予約語が非常に多いことでも有名な言語だそうです。大変ですね。

# FizzBuzzの実装

最後に FizzBuzz を実装します。文法は、 [COBOLプログラミング入門](http://tallercolibri.com/) というサイトにきれいにまとまっていたので、コーディングフォーマットやルール含めて一旦確認して実装していきます。

```sh
$ vim fizzbuzz.cbl
```

```cobol
           IDENTIFICATION DIVISION.
           PROGRAM-ID. FizzBuzz.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
           01 n   BINARY-LONG.
           01 i   BINARY-LONG.
           01 m3  BINARY-LONG.
           01 m5  BINARY-LONG.
           PROCEDURE DIVISION.
           DISPLAY "Enter a positive integer for Fizz Buzz"
           ACCEPT n
           PERFORM VARYING i FROM 1 BY 1 UNTIL i > n
               COMPUTE m3 = FUNCTION MOD(i 3)
               COMPUTE m5 = FUNCTION MOD(i 5)
               IF m3 = 0 AND m5 = 0 THEN
                   DISPLAY "FizzBuzz"
               ELSE IF m3 = 0 THEN
                   DISPLAY "Fizz"
               ELSE IF m5 = 0 THEN
                   DISPLAY "Buzz"
               ELSE
                   DISPLAY i
               END-IF
               END-IF
               END-IF
           END-PERFORM.
```

以上のように実装できました。

ELSE IFは本来ない文法なのでIF ELSE文を工夫して配置しています。あと、制御文の中では命令文の終わりを表す `.` は入力しないとのことでそこで少しハマりました。文法難しいですね...。あと剰余演算子がないので関数で計算です。意外といろんなものがない...。

```
$ cobc -x -o fizzbuzz fizzbuzz.cbl
$ ./fizzbuzz
```

以上を実行すると、

```
Enter a positive integer for Fizz Buzz
15
+0000000001
+0000000002
Fizz
+0000000004
Buzz
Fizz
+0000000007
+0000000008
Fizz
Buzz
+0000000011
Fizz
+0000000013
+0000000014
FizzBuzz
```

このように FizzBuzz を実装、実行することができました。お疲れ様でした！

# 結論

**文法は複雑だけども、 COBOLは高齢者以外も読める！** ということが体感できました。でもたぶん今後COBOLを書くことは無いんじゃないかなと思いますw 最近良く書くScala/JS/C++/Golangのほうが格段に楽ですね。

なおいろいろCOBOLの文法を調べてたら、自分のターゲッティング広告がすべてCOBOL人材募集している広告になりましたw なおこの度のコードは [GitHubのリポジトリ](https://github.com/sifue/try-cobol)においてありますので必要があれば使ってください。