Skip to content

Instantly share code, notes, and snippets.

@hakatashi
Last active September 22, 2018 13:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hakatashi/8e3dfb0e8fd6c00b165a4ca65ffed95c to your computer and use it in GitHub Desktop.
Save hakatashi/8e3dfb0e8fd6c00b165a4ca65ffed95c to your computer and use it in GitHub Desktop.
2018年度TSG夏合宿 言語実装ハッカソン&コードゴルフ

2018年度TSG夏合宿 言語実装ハッカソン&コードゴルフ

おはようございます!

このマニュアルでは、今回の夏合宿のために急遽用意した企画、「言語実装ハッカソン&コードゴルフ」の解説をしていきます。

事前準備

開発環境として、以下を用意しておくと当日すんなり開発に着手できる。

  • Docker
  • 開発したい言語のベースとなるesolang-boxイメージ
  • dobi
  • 最新のRuby
  • 当日実装する言語のアイデア

Docker

Dockerインストールメモ - Qiita なども参照。

Windows Professional

以下のリンクから Docker for Windows をダウンロードしてインストールする。

https://docs.docker.com/docker-for-windows/install/#install-docker-for-windows-desktop-app

cmdもしくはPowershellを開き、docker run hello-world を実行する。Hello from Docker! と表示されれば成功。

Windows Home Edition

以下のリンクから Docker Toolbox for Windows をダウンロードしてインストールする。

https://docs.docker.com/toolbox/toolbox_install_windows/

スタートメニューなどに Docker Quickstart Terminal なるものが追加されるので、ここからターミナルを起動する。

その中で docker run hello-world を実行する。Hello from Docker! と表示されれば成功。

Mac

以下のリンクから Docker for Mac をダウンロードしてインストールする。

https://docs.docker.com/docker-for-mac/install/

ターミナルを開き、docker run hello-world を実行する。Hello from Docker! と表示されれば成功。

Linux

適当に頑張れ。

esolang-boxイメージ

実際にプログラミング言語を開発する際には、なにか別のプログラミング言語、例えばRubyやPythonなどを使ってインタプリタを実装することになる。esolang-box上でプログラミング言語を動かす際にもベースとなる言語のDockerイメージが必要になる。

esolang-boxのライブラリにはプログラミング言語を実装する上で必要になる環境は一通り揃っているので、実装のベースにしたい言語をあらかじめ自分の得意なプログラミング言語の中から選んでおく。これを List of Boxes から選び、以下のコマンドでローカル環境に事前にダウンロードしておく。

docker pull esolang/<言語の名前>

例えば、ベースの言語として

をダウンロードする。

dobi

esolang-boxの開発に必要となるソフトウェア。

Releases · dnephin/dobi から最新のバイナリをダウンロードしてきて、どこかパスの通るところに配置しておく。

最新のRuby

esolang-boxの開発に必要。2.5系であれば問題ない。

Rubyのインストール - ruby-lang.org などを参考に。

当日実装する言語のアイデア

ここから先のマニュアルを読んで、当日実装する言語のアイデアを考えておくとよい。

前半戦 言語実装ハッカソン

1日目、みなさんには即席でオリジナルの言語を実装してもらいます。

オリジナルの言語と言っても、作ってもらうのはCとかPythonとかの本格的なものではなく、他のプログラミング言語で実装されるお遊び程度のプログラミング言語です。厳密なレキサーや複雑な文法を導入する必要はありませんし、簡単な文字列処理で実装できる範疇のもので構いません。

下のようなesolangの実装を見てみると雰囲気がつかめるかもしれません。

必ずしもゼロから言語を実装する必要はありません。既存の言語になんらかの (面白い) 制約を加えたものや、文法が異なるものもOKです。

どうしてもアイデアが思いつかない/実装が困難な場合はorenonoのようなツールを使ってBrainfuck方言を一瞬で作成することができます。が、面白みがないのでできればもう少しひねった言語を考えてほしいです。

複数言語の提出もOKです。

提出締切は原則9/22が終わるまで (JST) です。これ以降に提出すると博多市の睡眠時間が犠牲になります。

2日目のコードゴルフ大会の前に実装した言語についての簡単なプレゼンを行ってもらいます。提出方法はのちほど案内します (たぶんGoogleスライド)。

制約

コードゴルフに使用するという要件から、実装してもらう言語は以下の制約を満たす必要があります。

  • 任意長の文字列の入力と出力を持つ
  • ほぼ任意のタスクを実装できる (おおむねチューリング完全である)
    • よくあるダメなパターンが、数値入力しか受け付けないなど。

ソースコードがテキストファイルである必要はありません。

アイデア帳

面白いプログラミング言語のアイデアはいくらでも転がっています。特に以下のページが非常に充実しています。とても参考になるのでまずはここを眺めてみましょう。

博多市がざっと眺めて面白そうだと思ったアイデアはこんな感じ。

  • 野球やサッカーのルールをベースにした言語
  • 結び目理論に基づく言語
  • ソースコードがアニメGIFの言語
  • Cと文法が同じだが挙動が全く異なる言語

参考図書

参考図書として、

  • Rubyで作る奇妙なプログラミング言語
  • RubyでつくるRuby
  • きつねさんでもわかるLLVM
  • あなたの知らない超絶技巧プログラミングの世界

の4冊を用意したので、参考にしてください。

これらの参考図書のうち最初の2冊はP社の備品なので、特に丁寧に扱ってください。

esolang-box開発手順

esolang-box内に実装を持つこともできますが、更新がめんどくさいので各々のGitHubアカウントにリポジトリを作って開発することを推奨します。

言語が開発できたら、esolang-boxをフォークしてプルリクエストを送信してください。

esolang-boxの開発には以下のソフトウェアが必要です。インストールしてください。

開発した言語をesolang-boxリポジトリに追加するために、以下のファイルを編集する必要があります。

  • 言語一覧ファイル (boxes.yml)
  • Dockerfile (boxes/<言語名>/Dockerfile)
  • 起動スクリプト (boxes/<言語名>/script)
  • テスト (spec/boxes_spec.rb)
  • テストアセット (spec/assets/hello.<言語名>, spec/assets/cat.<言語名>)
  • テストアセットのコピーライト (spec/assets/README.md)

言語一覧ファイル (boxes.yml)

リポジトリに含まれるプログラミング言語の一覧と依存関係を記述したファイルです。

ベースにした言語の下に、プログラミング言語の名前とURLを記述します。例えば、Rubyで実装した**「すごい言語」**を追加したい場合は以下のように編集します。

--- a/boxes.yml
+++ b/boxes.yml
@@ -30,6 +30,9 @@ base:
     ruby:
       _name: Ruby 2.5.0
       _link: https://www.ruby-lang.org/
+      sugoi-lang:
+        _name: すごい言語
+        _link: https://github.com/hakatashi/sugoi-lang
       golfscript:
         _name: GolfScript
         _link: http://www.golfscript.com/golfscript/tutorial.html

boxes.ymlを編集したあとは、必ず ruby build.rb を実行してください。dobi.yamlが更新されます。

Dockerfile (boxes/<言語名>/Dockerfile)

実装した言語を動かすためのDockerイメージをビルドするための手順を書いたファイルです。

すでにある実装例を参考にしてほしいですが、だいたい以下の手順が含まれます。

  1. FROM句でベースとなるDockerイメージを指定する
  2. プログラミング言語のソースコードをホームディレクトリにcloneする
  3. (必要なら) ビルドを実行する
  4. /bin/<言語名> から /bin/script へのシンボリックリンクを貼る
  5. script ファイルを /root/script にコピーする

Pythonの例

FROM esolang/python3

RUN git clone --depth 1 https://github.com/stestoltz/Width.git ~/Width && \
    ln -s /bin/script /bin/width

COPY script /root/script

Rubyの例

FROM esolang/ruby

RUN git clone --depth 1 https://github.com/m-ender/alice.git ~/alice && \
    ln -s /bin/script /bin/alice

COPY script /root/script

Node.jsの例

FROM esolang/node

RUN git clone --depth 1 https://github.com/TehFlaminTaco/MaybeLater.git ~/MaybeLater && \
    ln -s /bin/script /bin/maybelater

COPY script /root/script

C/C++の例

FROM esolang/build-base

RUN cd /tmp && \
    git clone --depth 1 https://github.com/aaronryank/Cubically.git && \
    cd Cubically && \
    make && \
    mv cubically /usr/bin/cubically && \
    rm -rf /tmp/* && \
    ln -s /bin/script /bin/cubically

COPY script /root/script

起動スクリプト (boxes/<言語名>/script)

Dockerコンテナ内でプログラミング言語を起動するためのbashスクリプトです。

ソースコードのパスが第一引数で、入力が標準入力で与えられるので、標準出力に実行結果を出力してください。

標準エラー出力にビルドなどの情報を出力することができます。

Pythonの例

#!/bin/sh

cat - | /usr/bin/python3 ~/Width/width.py "$1"

Rubyの例

#!/bin/sh

cat - | /usr/local/ruby-2.5.0/bin/ruby ~/alice/interpreter.rb "$1"

Node.jsの例

#!/bin/sh

cat - | /usr/bin/node ~/MaybeLater/interpreter.js "$1"

C/C++の例

#!/bin/sh

cat - | /usr/bin/cubically f "$1"

テスト (spec/boxes_spec.rb)

追加した言語が正常に動くことを確かめるためのテストファイルです。

テストでは原則として Hello, World! プログラムとcatプログラムを用います。

こんな感じでテストを追加してください。

--- a/spec/boxes_spec.rb
+++ b/spec/boxes_spec.rb
@@ -679,4 +679,9 @@ describe 'esolang-box', v2: true do
   describe 'whenever' do
     it { expect(result_of(subject, 'hello.whenever')).to eql("Hello, World!\n") }
   end
+
+  describe 'sugoi-lang' do
+    it { expect(result_of(subject, 'hello.sugoi-lang')).to eql("Hello, World!") }
+    it { expect(result_of(subject, 'cat.sugoi-lang', 'meow')).to eql("meow") }
+  end
 end

テストアセット (spec/assets/hello.<言語名>, spec/assets/cat.<言語名>)

テストで実行される Hello, World! プログラムとcatプログラムの内容です。

  • spec/assets/hello.<言語名> に Hello, World! プログラムを追加
  • spec/assets/cat.<言語名> にcatプログラムを追加

テストアセットのコピーライト (spec/assets/README.md)

assetsディレクトリに含まれるファイルのコピーライト表記です。

hello.<言語名>cat.<言語名> の出典となるURLと作者名 (たぶん自分) を記述してください。

--- a/spec/assets/README.md
+++ b/spec/assets/README.md
@@ -75,6 +75,7 @@ Contents under this directory retains their original licenses.
 * `cat.stackcats`: [m-ender](https://github.com/m-ender/stackcats/blob/master/examples/cat.sks)
 * `cat.stk`: Original
 * `cat.strm`: [matz](https://github.com/matz/streem/blob/master/examples/01cat.strm)
+* `cat.sugoi-lang`: [hakatashi](https://github.com/hakatashi/sugoi-lang/blob/master/cat.sugoi-lang)
 * `cat.suzy`: Original
 * `cat.sqlite3.sql`: Original
 * `cat.swift`: Original
@@ -186,6 +187,7 @@ Contents under this directory retains their original licenses.
 * `hello.starry`: [esolangs.org](https://esolangs.org/wiki/Starry#Hello.2C_world.21)
 * `hello.strm`: [matz](https://github.com/matz/streem/blob/master/examples/02hello.strm)
 * `hello.spl`: [Karl Hasselström and Jon Åslund](http://shakespearelang.sourceforge.net/report/shakespeare/#sec:hello)
+* `hello.sugoi-lang`: [hakatashi](https://github.com/hakatashi/sugoi-lang/blob/master/hello.sugoi-lang)
 * `hello.suzy`: Original
 * `hello.sqlite3.sql`: Original
 * `hello.swift`: [developer.apple.com](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html)

ビルド

以下のコマンドを実行すると、esolang/<言語名> というDockerイメージが生成されます。

$ docker pull esolang/<ベースとなる言語> # やってなければ
$ ruby build.rb # やってなければ
$ dobi <言語名>
dobiを使わない場合

何らかの理由でdobiを使わない場合、以下の手順でdobiを使わずビルドすることができる。

$ docker pull esolang/<ベースとなる言語> # やってなければ
$ cd boxes/<言語名>
$ docker build -t esolang/<言語名> .

実行

以下のコマンドを実行すると、カレントディレクトリにあるファイル hoge を実行できます。

$ docker run --rm -v `pwd`:/code:ro esolang/<言語名> <言語名> /code/hoge

テスト実行

Ruby 2.5 をインストールし、以下のコマンドを実行するとテストを実行できます。

$ gem install bundler # なければ
$ bundle install
$ bundle exec rspec -e <言語名>

後半戦 コードゴルフ大会

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment