SF(すごくふつう)なブログ

記録・メモ・自己啓発・他

Rustでスクリプト言語を作ってみようとする (1)

Rustでスクリプト言語を作ってみようと思います。

その進捗報告および備忘録をつけていきます。

想定しているゴール

  • Rustで実装されたスクリプト言語の処理系が存在する
  • 字句解析・構文解析VMについてはライブラリを使わずにハンドメイドで実装されている
  • ユーザーがコマンドラインから操作するための何らかのバイナリが存在する

モチベーション

  • Rustの可能性を引き出したい
  • 言語処理系の中身を知りたい

考えている言語

正直はじめてこういった言語処理系を実装してみようとしているので、あまり奇抜なことはできません。なので、基本的に次のような言語を想定します。

  • Luaっぽいプロトタイプ指向言語を目指す

    • Luaソースコードyaccのようなパーサジェネレータを使わずに書かれているので、参考になると考えたため。
    • プロトタイプ指向の言語に興味があるため。
  • Luaの文法をできるだけ簡略化し、自分が実装可能な範囲で制限を加える

    • 実装しきることが現在の第一目標なので。

筆者の能力的な部分

情報系の授業は受けたことがありますが、コンピューターサイエンスを学んだ人間ではありません。ましてや形式文法や構文解析について専門的に学んだ経験もありません。そのような凡プログラマが私です。

Elm Platform 0.13以降/Windows上で日本語を含むUTF8のソースコードをコンパイルすると…

hGetContents: invalid argument (invalid byte sequence)

というエラーが出る。おそらくHaskellがSystemデフォルトのエンコーディング(Shift-JIS)を使っているせいでこういうのが発生する…

回避方法

  1. 日本語でコメント書かない

  2. Shift-JISでソースコード保存

  3. 修正してプルリク

ElmでWebsocketを使ってゲームを作ってみた例

説明

ElmでWebsocketを使って、非常にシンプルなネットゲームを作ってみました。

リポジトリこちら

実際に動いているのはこちら ※サーバー側(Erlang)がうまくバックグラウンドで動かせていないせいで、たまーにしかプレイできません。すんません。僕のErlang力不足が原因です…

構成

サーバー側はErlangだけ、クライアント側はElm+Javascript(Websocketのコネクション周り)で作っています。

クライアント側

Elmで作っています。Elmです。Elmですね。

Elmはリアクティブプログラミングというプログラミングパラダイムの上に存在します。なので、常にリアクティブな思考を持って作る必要があります。

ベースとなるシグナルを考える

僕の中でリアクティブプログラミングは、電気回路のイメージがあります。予め作られた回路(Elmで書かれた関数)に、信号(Signal)を流し込み、駆動する。そういう感じです。

入力シグナル

入力シグナルの中に、ユーザーの入力を全て詰め込みました。というのも、foldpでゲームエントリー関数を畳み込んでしまうと、もうそこに別のユーザー入力(つまりシグナル)を入れるのがかなり難しそうだと感じたからです。

入力シグナル部分

このシグナルを、foldpで初期ゲーム状態を与えた状態で畳み込みます。

ゲームシグナル部分

他にもウェブソケットのシグナルを扱わないといけないのですが、やっかいなことにElmのWebSocketを開く関数は

String -> Signal String -> Signal String

という型を持っていて、予め作ったシグナルを渡さないと返り値のシグナルが貰えないようになっています。つまり、シグナルのループが出来ないんです。ちょっと良い説明が出来ないのですが、foldpでWebSocketの返り値を含むような閉じたシグナルを作ると、そこからWebSocketの入力に何かを突っ込むことが非常に難しい感じになります。

じゃあどうしたの?

WebSocketはJavascript側でハンドルし、Portという仕組みを使ってWebSocketへの入力、返り値をそれぞれ独立したシグナルにしました。

WebSocketシグナル部分

これでfoldpで作るシグナルにWebSocketの返り値シグナルを入れても、WebSocketへ自由に入力させることができます。

出力シグナル

Elmからサーバーサイドへは、WebSocketへの入力を行うことで出力を行います。

出力シグナル部分

ゲーム関数

ゲーム関数は、クライアント側の中心となる存在です。この中で、

  • WebSocketから受け取った返り値の処理
  • 各種計算
  • ゲーム状態の遷移

これらの処理を全て行います。

ゲーム関数部分

この中の処理はもう普通の処理です。foldpとかElm特有の処理は出てきません。

まとめ

やっぱりリアクティブを意識するのが重要な感じがします。このゲームでは

  • FPSとなるシグナル
  • サーバー側からのシグナル

という2つの方向性が違うシグナルが有り、現状ではFPSの方で強制的にサーバー側のシグナルを同期させています。ただそのせいでサーバー側からのシグナルを一部取りこぼす(他のユーザーが生成したブロックの情報が同期されなかったり)ことがあるので、なんともどうしたものか…と思っています。

解決策としては、

  • サーバー側でクライアントが必ず受け取ったことが確認できない限りメッセージをキャッシュする
  • サーバー側とクライアント側のメッセージ送受信間隔を同期させる

ぐらいしか思いつきませぬ。

Elmのメリット

最後に、Elmのメリットをいくつか。

モジュールの分割が楽

モジュールを分割するのが楽です。しかもひとつのjavascriptファイルに簡単にコンパイルできるので、保守性が抜群です。

綺麗に書ける

javascriptのグチャッとしたソースコードに精神を削られている人も多いと思います。きっとElmは心の癒やしになるでしょう…

大洗のあんこう祭りに行ってきた

11月16日に行われた大洗あんこう祭りに行ってきました。大洗というとガールズアンドパンツァーというアニメ作品で一躍有名になった場所です。僕もガルパン経由で知りました。

その大洗で毎年11月に行われているのがあんこう祭りで、ここ数年はガルパンとのコラボが毎年行われているようです。今回その祭りの様子を写真に撮ってきました。

続きを読む

当ブログのコンテンツの引用は自由です。