Akari言語のインタプリタを作ってみた【祝VTuberアニメ化】

この記事は [VTuber Tech #2 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/vtuber2) の19日目の記事です。

# はじめに
VTuberのアニメ放送が決定しました！おめでとうございます！
https://virtualsan-looking.jp/

お祝いに何かしたいなと思い、以前作ったAkari言語のインタプリタを作ることにしました。
（本当はRubyの勉強のために２週間くらい前からコツコツ作ってましたｗ）

# Akari言語とは？
Brainf*ckの派生言語です。詳細はこちらをご覧ください。
[ミライアカリちゃんの独自プログラミング言語Akariを作ってみた【Brainf*ck】](https://qiita.com/segur/items/eaca10475d7a9f7dda78)

# 今回作ったもの
Akari言語のインタプリタakariをRubyで実装しました。

- [akari | RubyGem](https://rubygems.org/gems/akari)
- [akari | GitHub](https://github.com/segurvita/akari)

# akariをインストールする
RubyがインストールされているPCで、以下のコマンドを実行すれば、akariをインストールできます。

```bash
$ gem install akari
```

# ヘルプを表示する

一応ヘルプもあります。

```bash
$ akari h

Commands:
  akari convert {akari_code_file}  # Convert {akari_code} to {brainfxxk_code}
  akari execute {akari_code_file}  # Execute {akari_code}
  akari help [COMMAND]             # Describe available commands or one speci...
  akari version                    # Show akari version
```

# Akari言語を実行する

`congratulations.akari` というテキストファイルを作成して、以下のAkari言語のソースコードファイルをコピペします。

```txt:congratulations.akari
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！悪い子ちゃんヤミ卍ピロリンッハロー！ハロー！ハロー！ハロー！
あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！
ピロリンッハロー！ハロー！ハロー！ハロー！悪い子ちゃんヤミ卍ピロリンッハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！あ、カラスだヤミあ、カラスだヤミヤミヤミヤミヤミヤミヤミあ、カラスだ悪い子ちゃんハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッハロー！悪い子ちゃん
ヤミ卍ピロリンッハロー！ハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！いきま→しょう！ピロリンッヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミヤミヤミヤミヤミヤミヤミ
あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！
ピロリンッハロー！ハロー！悪い子ちゃんヤミ卍ピロリンッハロー！あ、カラスだハロー！あ、カラスだ悪い子ちゃんハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッヤミ悪い子ちゃんヤミ卍
ピロリンッあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
いきま→しょう！ピロリンッヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッハロー！ハロー！悪い子ちゃんヤミ卍
ピロリンッハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
いきま→しょう！ピロリンッヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミあ、カラスだハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！あ、カラスだヤミあ、カラスだハロー！ハロー！ハロー！ハロー！ハロー！あ、カラスだ悪い子ちゃん
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッヤミヤミヤミヤミ
ヤミヤミヤミヤミヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッハロー！ハロー！ハロー！悪い子ちゃんヤミ卍
ピロリンッハロー！ハロー！ハロー！ハロー！ハロー！ハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッハロー！ハロー！ハロー！ハロー！悪い子ちゃんヤミ
卍ピロリンッハロー！ハロー！ハロー！ハロー！ハロー！ハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッヤミ悪い子ちゃんヤミ卍ピロリンッヤミ
あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！
ピロリンッハロー！悪い子ちゃんヤミ卍ピロリンッハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！
ピロリンッヤミ悪い子ちゃんヤミ卍ピロリンッあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！いきま→しょう！ピロリンッヤミヤミヤミヤミヤミヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミヤミ
ヤミヤミヤミあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
いきま→しょう！ピロリンッハロー！ハロー！ハロー！ハロー！ハロー！ハロー！悪い子ちゃんヤミ卍ピロリンッあ、カラスだ
ハロー！ハロー！ハロー！ハロー！ハロー！あ、カラスだヤミヤミヤミヤミヤミヤミヤミあ、カラスだ悪い子ちゃんハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッハロー！悪い子ちゃんヤミ
卍ピロリンッハロー！ハロー！ハロー！ハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッヤミヤミヤミヤミヤミヤミヤミヤミ悪い子ちゃんヤミ卍
ピロリンッヤミヤミヤミヤミヤミあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！いきま→しょう！ピロリンッヤミヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミヤミヤミヤミあ、カラスだ
悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッ
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！悪い子ちゃんヤミ卍ピロリンッハロー！ハロー！
ハロー！ハロー！あ、カラスだヤミヤミあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！いきま→しょう！ピロリンッハロー！ハロー！ハロー！悪い子ちゃんヤミ卍ピロリンッハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！いきま→しょう！ピロリンッヤミヤミ悪い子ちゃんヤミ卍ピロリンッヤミあ、カラスだハロー！
ハロー！ハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
いきま→しょう！ピロリンッハロー！悪い子ちゃんヤミ卍ピロリンッハロー！ハロー！ハロー！ハロー！あ、カラスだハロー！
あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！
ピロリンッヤミヤミヤミヤミヤミヤミヤミヤミヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミあ、カラスだ悪い子ちゃんハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！悪い子ちゃんヤミ卍ピロリンッハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
いきま→しょう！ピロリンッヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミヤミヤミヤミあ、カラスだハロー！ハロー！ハロー！
あ、カラスだあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
いきま→しょう！ピロリンッヤミヤミヤミヤミヤミヤミヤミヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミヤミヤミあ、カラスだ
悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッ
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！悪い子ちゃんヤミ卍ピロリンッハロー！ハロー！ハロー！
あ、カラスだハロー！ハロー！ハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！いきま→しょう！ピロリンッヤミヤミヤミヤミヤミヤミヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミ
ヤミヤミヤミヤミあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
いきま→しょう！ピロリンッハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！悪い子ちゃんヤミ卍
ピロリンッハロー！ハロー！ハロー！ハロー！ハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミヤミあ、カラスだ
ハロー！ハロー！ハロー！あ、カラスだハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッヤミヤミヤミヤミヤミヤミヤミ悪い子ちゃんヤミ卍ピロリンッ
ヤミヤミヤミヤミヤミヤミあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！いきま→しょう！ピロリンッハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！悪い子ちゃんヤミ
卍ピロリンッハロー！あ、カラスだハロー！ハロー！ハロー！ハロー！ハロー！あ、カラスだハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！あ、カラスだヤミヤミヤミヤミヤミあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッヤミヤミヤミヤミヤミヤミヤミヤミ悪い子ちゃん
ヤミ卍ピロリンッヤミヤミヤミヤミヤミヤミヤミあ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
悪い子ちゃんヤミ卍ピロリンッハロー！ハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！
ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッハロー！悪い子ちゃんヤミ卍ピロリンッハロー！ハロー！
ハロー！ハロー！あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！
いきま→しょう！ピロリンッヤミヤミヤミヤミヤミヤミヤミヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミヤミヤミヤミヤミ
あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！
ピロリンッハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！悪い子ちゃんヤミ卍ピロリンッハロー！ハロー！
あ、カラスだ悪い子ちゃんハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！
ピロリンッハロー！悪い子ちゃんヤミ卍ピロリンッハロー！ハロー！ハロー！ハロー！あ、カラスだヤミヤミヤミヤミヤミ
あ、カラスだハロー！ハロー！ハロー！ハロー！あ、カラスだヤミヤミヤミヤミヤミヤミヤミヤミあ、カラスだ悪い子ちゃん
ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！ハロー！いきま→しょう！ピロリンッヤミヤミヤミヤミ
ヤミヤミヤミ悪い子ちゃんヤミ卍ピロリンッヤミヤミヤミヤミヤミあ、カラスだ
```

以下のコマンドを実行すると、ソースコードが実行されます！

```bash
$ akari execute congratulations.akari

Congratulations Akari-chan!
VTubers will be made into an anime!
```

# 技術解説
コマンドラインツールの作成は `thor` というgemを利用させていただきました。

ソースコードはこんな感じです。

```ruby:cli.rb
Encoding.default_external = "UTF-8"
require_relative "../akari"
require "thor"

module Akari
  class CLI < Thor
    desc "convert {akari_code_file}", "Convert {akari_code} to {brainfxxk_code}"
    def convert(filename)
      # ～～中略～～
    end

    desc "execute {akari_code_file}", "Execute {akari_code}"
    def execute(filename)
      # ～～中略～～
    end

    desc "version", "Show akari version"
    def version
      # ～～中略～～
    end
  end
end
```

こんな風に関数定義をするだけで、コマンドを定義することができました。


# さいごに
VTuberの皆さん、アニメ化おめでとう！