高校生が2ヶ月で教育用プログラミング言語を作ってU22プロコンで賞をとった話

#前置き
2020/11/29に開催された <a href="https://u22procon.com">U22プログラミングコンテスト2020</a> において経済産業省政務局長賞プロダクト賞及びOBC賞を頂きましたので、開発経緯をまとめてみたいと思います。拙い文章だとは思いますが、U22プログラミングコンテストに応募してみようと考えている方や自作言語に興味がある方への参考になれば幸いです。
##自己紹介
最初にちょっとした自己紹介を...
プログラミングが趣味な一般高校二年生(4月から３年生)です。
プログラミングはScratchを小学生４年生から、JavaScriptを中学１年生からはじめました。高校に入ってからプログラミング学習を本格的に初め、C, C++, Swift, PHP, (SQL), Go などを学習しました。(まだマスターには程遠いですが..)
一番なれている分野はサーバーサイドで、文化祭の物品管理データベースの作成やスーパー混雑共有サービスなどを今までに作りました。
#応募作品について
今回のU22プログラミングコンテスト(以下U22プロコン)で提出した作品は以下の２つです。簡単に紹介します。(詳しくは<a href="https://hmwri.com/peridot">PeriDotのホームページ</a>をご覧ください。)
まず30秒ほどの動画で大まかな特徴を紹介します
####イメージビデオ
<iframe width="560" height="365" src="https://www.youtube.com/embed/RxUNiYDA5vg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
##PeriDot
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234016/63458f37-b14c-b976-4b05-e9dd9c5fb690.png" width="400px">

####種類
プログラミング言語(インタプリタ型/手続き型/動的型付け)
####概要
Scratchなどのビジュアルプログラミングから、C, JavaScript, Pythonなどのテキストプログラミングへのステップアップ を目的とした、教育、学習用として最適化されたシンプルなインタプリタ型言語。
また、日本語でのエラーやインタプリタの評価過程の表示が可能。
####開発言語/環境
GO言語/Mac OS
####開発期間
1ヶ月半
##Peree
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234016/292a53e8-3fdd-1884-fb75-ef5b25814155.png" width="400px">![ウィンドウのキャプチャ 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234016/6984dc36-379f-486a-8ab4-4243c0fad507.png)

####種類
WEBサービス
####概要
PeriDotをweb上で実行可能にしたサービス。アカウント登録をすることでweb上にプロジェクトを保存し他者とシェアすることもできる。一つの画面でソースコードの編集,実行,実行過程の確認までできる。
####開発言語/環境
フロントエンド HTML/CSS/JavaScript(JQuery)
バックエンド(CentOS) PHP/Go/MySQL/Apache
####開発期間
1ヶ月
#受賞までの道のり
作品の締め切りが9/14で提出したのは9/13でした(ギリギリ!)。 そのため、応募すると決めた7月中盤から9/13までの開発過程とその後のプレゼンの準備までどういうことをしたのか書いていきます。詳しい開発方法などを書くときりがないのでざっと紹介します。
##何を開発するか決める(7月中盤)
7月中盤ごろに自分の力試しを兼ねてU22プログラミングコンテストを応募してみようと思いたちました。何を作るか考える中で、どうせなら世の中の課題を解決するものを作ろうと思い、プログラミング教育に焦点をあてたものを作ろうと決めました。
教育現場ではよくJavaScriptや日本語プログラミング言語が使われるのですがどれもいイマイチ教育向きではない。そのため、あ〜もう自分で作ればいいんだな。となって教育用言語を開発することに決めました。
##言語設計及び機能決め(7月後半~8月)
締め切りまで2ヶ月もなかったので開発と言語設計は同時進行で行いました。機能と設計の考案は以下のような流れで進めました。

1. 課題を明確に設定
2. 1の原因を分析
3. 2を踏まえて課題を解決できる設計や機能を考案

個人的にはこの言語設計が最も評価されたのだと思います。
###課題
<B>ビジュアルプログラミングからテキストプログラミングへステップアップできない人が多い</B>

###原因
以下のようなテキストプログラミングの特徴
<dl>
<dt>複雑なルール</dt><dd>実務でも使えるように普通の言語は設計されているためどうしても機能が多くなり複雑になっている</dd>
<dt>予約語の多さ</dt><dd>使いやすさや多機能さを追求するあまり予約後が多くなり、覚える事柄が多くなってしまっている</dd>
<dt>英語でのエラー</dt><dd>ビジュアルプログラミングにはなかったエラーが出るようになりしかも英語で解読が難しい</dd>
<dt>実行過程の不明調さ</dt><dd>どういうふうに処理が進んでいったのかわかりにくく、デバッグも難しい</dd>
<dt>CUIへの抵抗</dt><dd>いきなりテキストだけの世界へ踏み出すのはかなり勇気のいること</dd>
<dt>開発環境構築の難しさ</dt><dd>ダウンロードして環境変数を通して...インストール時点で難しいことをしなければならない</dd>
</dl>
###解決策
解決するための設計/機能
<dl>
<dt>最低限の機能</dt><dd>逐次,繰り返し,分岐処理を学ぶための最低限の機能しかいれない</dd>
<dt>少い予約語</dt><dd>予約語の数を極力減らし,覚えやすいよう簡単な英語を名前に用いる。</dd>
<dt>書きやすい文法</dt><dd>直感的でシンプルな書きやすい文法を目指す</dd>
<dt>柔軟な型</dt><dd>型に極度に配慮する必要のない動的型付け言語</dd>
<dt>従来の言語から逸脱しすぎない</dt><dd>あくまでもステップアップが目的なので、そのまま一般の言語へ移行できるよう特徴的すぎる設計にしない</dd>
<dt>エラーを日本語で表示</dt><dd>エラーへの抵抗を少なくするために親切な日本語でのエラーを実装する</dd>
<dt>処理過程の表示</dt><dd>インタプリタがどうソースを評価していったか表示することで理解及びデバッグを助ける</dd>
<dt>web上(GUI)で実行可能</dt><dd>開発環境構築の必要性をなくす</dd>
</dl>
以上をもとに開発しました。
##参考書籍探し(7月後半)
インタプリタ自作本とかあるかなっと探してみたらこんなものが...!
[Go言語で作るインタプリタ (Thorsten Ball　著、設樂 洋爾　訳)](https://www.oreilly.co.jp/books/9784873118222/)
しかも大好きなGo言語なのでこれはいいと思い即買いしました。
それに加え,サーバーサイドのGo言語も学ぶ必要があったため、こちらの本も購入。
[Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る impress top gearシリーズ (au Sheong Chang  (著), 武舎 広幸 (著), 阿部 和也 (著), 上西 昌弘 (著) )](https://www.amazon.co.jp/Go%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-%E6%A8%99%E6%BA%96%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%A7%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E4%BD%9C%E3%82%8B-impress-gear%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-Sheong-Chang-ebook/dp/B06XKPNVWV/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=go%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80&qid=1616581338&s=books&sr=1-1)
主にこちらの二冊を参考にしながら開発を進めていきました。

##言語コア部分作成(7月後半~8月中旬)
GO言語で作るインタプリタをもとに字句解析器,構文解析器,評価器を作成していきます。書籍のサンプルコードがとても優秀なのでほぼそれを流用という形にはなってしまいますが、単に写すのではなく確実に理解してから写しました。そのため思ったより時間がかかってしまい(夏休み全部かけたのですが)あっという間に8月中旬です。

##オリジナル設計/機能を追加(8月中旬~9/10)
コア部分はできたので、前述したオリジナルの設計と機能を組み込んでいきます。ここで、写しながらも完璧にソースを理解していたことが役立ち、案外すいすい組み込むことがきました。1日1機能追加を目標に開発を進めていきました。

###具体的な改造内容
<dl><dt>繰り返し処理がなかったためloop文を作成</dt><dd>

```:PeriDot
make i = 0
loop  i < 10{
  <<10回繰り返す>>
  i++
}
<<簡略化版>>
loop 10 {
  <<10回繰り返す>>
}
```

</dd>
<dt>予約語の名称の変更(1例)</dt><dd>

```rust:改造前
let a = 1;
```

```go:PeriDot
make a = 1
```
</dd>
<dt>関数の定義方法の変更</dt><dd>

```rust:改造前
let add = fn(a,b){ return a+b; }
```

```go:PeriDot
func add(a,b) { return a+b; }
```
</dd>
<dt>セミコロン,カッコの削除</dt><dd>

```rust:改造前
let a = 2;
if (a%2 == 0) {
  print("aは偶数です");
}
```

```go:PeriDot
make a = 2
if a%2 == 0 {
  SAY("aは偶数です")
}
```
</dd>
<dt>日本語対応</dt><dd>

```go:PeriDot
make りんごの個数 = 2
SAY(りんご)
```
</dd>
<dt>文字列+数の連結可能</dt><dd>

```go:PeriDot
make りんごの個数 = 2
SAY("りんごは"+りんごの個数+"個です")
```
</dd>
<dt>エラーを日本語で表示</dt><dd>

```go:PeriDot
make Array = [1,2,3]
SAY(Array[3])
```
```error:エラー
配列から値を取り出せませんでした。[ 3 ]に対応する値がみつかりません。
(添字は2以下である必要があります)
```
</dd>
<dt>処理過程の表示</dt><dd>

```go:PeriDot
make a = 102
if a%2 == 0 {
  SAY("aは偶数です")
}
```
```log:実行過程
[1] 1行目: a -> 102 「変数(a)を定義し(102)を代入」
[2] 2行目: a -> 102 「変数(a)を参照」
[3] 2行目: 102 % 2 -> 0 「計算」
[4] 2行目: 0 == 0 -> true 「評価(true or false)」
[5] 2行目: ((a % 2) == 0) -> true 「条件がtrueであったためif内を実行」
[6] 3行目: SAY -> 実行 「関数を実行(関数:SAY)」
```
</dd>


##webサービス作成(8月中旬~9/10)
言語作成と並行してwebサービス(Peree)も作りました。
フロントエンドはJQuery、PeriDotの実行/結果返却やプロジェクトの保存/読み出しなどはGo言語、ユーザーのログイン処理などにはMySQLとPHPを使いました。通信ではAjaxを用いることでUXの向上を図り、SQLインジェクション対策やOSコマンドインジェクション対策などのセキュリティ対策も行いました。
図に表すと以下のような感じです。
![Peree仕組み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234016/36048496-3a03-d804-8ca9-28ad6a50bd41.png)

##作品完成(9/10)

##マニュアル&資料作成(9/10~締め切り)
応募のために必要な資料や説明の動画をこの期間に作りました。また、[オンラインマニュアル](https://hmwri.com/peridot/manual/)も作成しました。

##第一次審査通過(10月中旬),第二次審査通過(10月下旬)

##最終審査(11/29)にむけて
第二次審査通過をすると、プレゼンテーション(今年はオンライン)にむけての案内が届くのでそれに従って、プレゼン資料を作っていきます。持ち時間は約10分なのでそれに収まりながらも工夫点を最大限伝えられるよう練習しました。

##最終審査(11/29)
ニコニコ生放送されるゆえにすごい方々に見られながらなのでとても緊張しましたが、なんとか乗り越えることができ、受賞することができました。

#まとめ
簡単に受賞までの経緯をまとめてみました。
U22プログラミングコンテストは、技術に加え課題解決能力も非常に問われるコンテストだと思います。もし応募してみようと思っている方は是非参考にしてください!
最後まで呼んでいただきありがとうございます

<B>[PeriDotホームページ](https://hmwri.com/peridot)
フィードバックやご意見/ご感想を[こちら](https://docs.google.com/forms/d/e/1FAIpQLSexyOKj9uD41kDZoSmfjLTfmzQKXleeo2ks5z8e8QjErYvE2Q/viewform?usp=sf_link)に寄せていただけると大変嬉しいです