共通テスト「情報」サンプル問題のプログラミング言語を作ってみた

[共通テスト「情報」試作問題のプログラミング言語を作ってみた](https://qiita.com/nodai2h_ITC/items/637e9a17dbd35c0d6277) の続編です。共通テスト（旧センター試験）に追加が決まった「情報」の問題で使われている擬似プログラミング言語を実際に実行できる環境を作成しました。言語処理系をイチから作るのではなく JavaScript に変換して実行させることで実装を簡単化しています。実際に動くものは ↓ からどうぞ。

[DNCL2- 大学入試共通テスト「情報」問題言語](https://nodai2hitc.github.io/ictl/)

# はじめに

共通テスト「情報」[試作問題](http://www.ipsj.or.jp/education/9faeag0000012a50-att/sanko2.pdf)に続いて、[サンプル問題](https://www.dnc.ac.jp/albums/abm.php?d=33&f=abm00000307.pdf&n=%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E5%95%8F%E9%A1%8C%E3%80%8E%E6%83%85%E5%A0%B1%E3%80%8F_%E5%95%8F%E9%A1%8C.pdf)が公開されました。サンプル問題でも、試作問題とほぼ同様の擬似言語が使われています。（どのような擬似言語なのかは[サンプルプログラム集](https://nodai2hitc.github.io/ictl_example/)のページや、本記事末尾の[現在判明している仕様](#おまけ現在判明している仕様)を御覧ください。）

これに基づき仕様の変更？に対応したほか、その他いろいろと変更しました。

# サンプル問題に基づく変更点

## for 相当の繰り返し構文の微変更

試作問題では `i を 1 から 100 まで 1 ずつ増やしながら:` だったのが、`i を 1 から 100 まで 1 ずつ増やしながら繰り返す:` と **繰り返す** が入りました。以前の構文でも新しい構文でも動くようにしています。

## while 相当の繰り返し構文が追加

一般的なプログラミング言語における `while` に相当する構文として、`tosenkei < giseki の間繰り返す:` が追加されました。

## 組み込み関数「切り捨て()」の追加

## 組み込み関数「表示する()」の可変長引数化

試作問題では `表示する()` は 1 引数しかとりませんでしたが、サンプル問題では可変個の引数をとっていました。`表示する(1, 2, 3)` などと書いた場合、出力は `123\n` と最後のみに改行が入る仕様のようです。

## 配列の自動初期化

今回のサンプル問題にも違和感のある部分がありました。それが以下。

```
(07) ⎿ Hikaku[m] = Tokuhyo[m]
```

…この行だけ見れば違和感は無いでしょう。ただ問題は、配列 `Hikaku` は**この行で初登場しており、一切初期化処理が無い**という点です。確かに Perl では初期化処理なしにいきなり `$Hikaku[0] = 1;` と書くことができますが[^perl]、JavaScript ではそうした書き方はできません。

[^perl]: Perl 書きではないので分かりませんが、多分 Perl でも推奨される書き方ではないでしょう。

よく見ると試作問題でもサンプル問題でも配列の変数名は大文字で始まっているので、「大文字で始まる変数名は配列であり、必要であれば初回アクセス時に自動初期化される。」という言語仕様なのかもしれません。ただ、「JavaScript に変換して実行する」という作成方針の都合上そうした言語仕様を採用してしまうと辛いので、「実行前に配列っぽい変数名を調べ、あらかじめ初期化しておく」という雑な対応をしました。

## 論理演算子「and」「or」「not」

今回のサンプル問題によると、この言語では論理演算子として`and`, `or`, `not` を使用するようです。Ruby であればそのままでも大丈夫ですが、JavaScript には`and`, `or`, `not`は無いので`&&`, `||`, `!`に変換が必要です。

# それ以外の変更点

## 「配列のすべての要素に代入」を雑な対応に変更

試作問題には`配列 Hindo のすべての要素に 0 を代入する`という要素数が不定の配列に初期値を設定する謎構文があり、当初はこれに対応するため、上の例であればプログラム中のすべての `Hindo[ なんとか ]` を `Hindo[ なんとか ] == undefined ? Hindo.default : Hindo[ なんとか ]` に置き換える、という方法をとりました。

ですが対応方法が複雑で悪影響が起きそうな気がすることと、今回のサンプル問題にはこの構文がなかったことから、「要素数を指定して初期化することもできるのだが、要素数を省略した場合はデフォルトの要素数（試作問題の都合上 26 ）で初期化する。」という雑な対応方法に変更しました。

## else if 相当の構文を追加

試作・サンプル問題には無いのですが、`else if` に相当する構文がないと FizzBuzz を書くのが面倒なので、勝手に `あるいは ○○ ならば:` という構文を追加しました。

## エラーを表示するようにした

試作・サンプル問題等を実行するだけであればエラーは発生しないので以前はエラー処理を一切していませんでしたが、自分で新たにプログラムを書く場合のことも考え、エラー発生時にはエラー内容を出力するようにしました。

ですが、どの行でエラーが発生したのかまでは表示しない[^error]のでデバッグは困難ですね…変換後の JavaScript を表示する機能を付けたので、JavaScript が分かる人はそっちでエラー箇所を探すと良いかもしれません。

[^error]: どの行でエラーが発生したのかを取得する方法は無いんでしょうか…御存知の方がいましたら教えて下さい。

## フォーマッターを追加

近年のプログラミング言語では公式なフォーマッターが存在することが多いので、せっかくだから付けてみました。とはいえ行頭の行番号と`｜`を整える程度ですが。

## 条件分岐・反復構文の挿入ボタンを追加

`i を 1 から 100 まで 1 ずつ増やしながら繰り返す:` みたいな構文を間違えることなく入力するのは地味に面倒なので、挿入ボタンを付けました。

## 試作問題・サンプル問題を別ページに移行

MIT License で公開していたのですが、その中に私が作ったわけではない試作・サンプル問題が含まれているのはマズイのでは？と気付き、それは[別のリポジトリ](https://nodai2hitc.github.io/ictl_example/)に移しました。少し手間が増えてしまいますが、試作問題・サンプル問題を実行してみたい場合はそちらからコピペしてください。

# おまけ：現在判明している仕様

## 基本的な言語仕様

- 動的型の手続き型言語と思われます。
  - 「関数」という存在はあるものの、自分で定義できるのかは不明です。
  - オブジェクト指向的な要素は今のところ見当たりません。（例えば Ruby や JavaScript であれば配列の要素数は `array.length` で調べられますが、この言語では `要素数(Array)` と関数を使って調べる必要があります。）
- 改行は基本的に文の区切りとして認識されるらしく、`;` 等の区切り文字は行末に不要です。
- 制御構文は、Python のように末尾に `:` が付きます。
  - コードブロックは、行頭の `｜`, `⎿` で表します。
    - 行番号を無視して、`｜`, `⎿` を空白で置き換えてしまえば、まさに Python の構文ですね。このように、全体的には Python が一番近い印象を受けます。

## 演算子

- 算術演算子: `+`, `-`, `/`, `%`
  - 乗算の演算子は不明ですが、普通に考えれば `*` でしょう。
  - 除算は、`3480/6` が `580`、`1200/580` が `2.068966` になることから、JavaScript のように「整数型」を持たず「浮動小数点型」のみで整数も扱う言語仕様ではないかと思われます。
- 代入演算子: `=`
  - `sousuu = sousuu + Tokuhyo[m]` という式があるのを見ると、 `+=` 等の自己代入演算子は無いのかもしれません。
- 比較演算子: `!=`, `<`, `>=`, `<=`
  - 等号が一般的な `==` なのか、それとも VBA 等で使われている `=` なのか不明ですが、等号否定が一般的な `!=` （VBA だと `<>`）であることから `==` ではないかと思われます。
  - ところで「公平性を鑑みて独自の日本語表記の疑似言語とした」そうですが、VBA を使って学習した生徒からすると `!=` が説明なしに使われているので少し不公平な気もします。
- 論理演算子: `and`, `or`, `not`