読者です 読者をやめる 読者になる 読者になる

プログラミング言語作成ハンズオンに参加してきた #lang_impl

プログラミング言語作成ハンズオンに参加してきました。楽しかったです!

プログラミング言語を作成したことがないので、こういう勉強会で教えてもらえるのはすごくありがたいです。

connpass.com

午前中はざっとプログラミング言語処理系についての説明。その後、今回のハンズオン用に作られたnubという言語を拡張していきます。

github.com

やったこと

  • 午前中の説明に出てきた内容と用意されたソースコードの対応を考える
  • ANTLRというものを使っておりこれが何かを考える。これはパーサジェネレータで、g4ファイルを元にパーサを生成してくれる。最初はANTLRというものがパーサそのもの?などと何も分かっていない勘違いをしていたのだが、NubParserクラスが自動生成されているようだったので、勘違いに気がついた
  • 用意されたコードの役割をざっと把握できたので、最初に累乗演算子 ** を導入。これは +* を参考にして、とくに問題なくできた
  • 次に、文字列リテラルを導入。test-inputディレクトリに用意されていた string.nub を実行できるようにした
  • その次は、Stringに対して指定した位置にある文字を取得するindexOf関数をnub言語で実装できるようにすることに
    • Stringを文字の配列っぽい感じで扱いたい
    • そもそも配列がないので作らないと
    • よくわからなかったので、ペアで実装することに
    • 文法はLispを真似て cons car cdr を作る
    • まずは cons 。文法ファイルをいじる。なんかどの辺に書けばいいのだろうか悩む。専用の抽象構文木を作ったけどBinaryOperator使えばよかったのかも。インタプリタ( Evaluatorクラス )では、長さが2の Object[] で実装
    • 次は car cdr 。これも文法ファイルのどの辺に書けばいいのか悩む。。処理の優先順位をどうしたいかで決めればいいのかなぁ。単項演算子のための抽象構文木を作って対応
    • ペアができた。 println(car(cons(1, cons(2, 3)))) こんな風に書ける
    • Stringリテラルの実装を作ったペアで表現するようにした。 "Hello"(H(e(l(l(o))))) といった風に
    • indexOf関数を定義できるようになった
  • 最後は文字列の長さを返すlength関数をnubで作れるようにすることに
    • 空のペアかどうかを調べる isNil という文法を導入
    • length関数を定義できるようになった

というわけで実装したものです。

GitHub - bati11/nub at study

全体的に

nubという言語を拡張するということだったが、上に書いた通り自分は cons car cdr でペアを作れるようにした。だけど、拡張というのはこういうことでいいのか、自分がやってることは正しいのか?というのが不安でした。実装に夢中になってしまったけど、チューターの方にもっと聞けばよかったかもしれない。

あとは、今回やってみて思ったのは、プログラミング言語の作成というのはインタプリタの実装も含んでいるのだなぁということでした。なぜかは分からないけど、仕様が決まっているインタプリタが読めるような何かを出力するイメージを持っていました。でも、インタプリタも一緒に作るんだなぁ。文法・抽象構文木、それからインタプリタを実装するときに、今どれを実装しているのか、という頭の切り替えをしっかりやらないとごちゃごちゃしてくるなぁと感じました。これは水島さんがブログ記事で書いてるメタとベタの話と近いことを言ってるのかもしれないです。

プログラミング言語作成ハンズオンを開催しました - kmizuの日記

おわりに

もうちょっと色々いじってみたいなぁ、とりあえず以下のことはやってみたいです。

この勉強会のおかげでもっと踏み込んでみたいなぁという気持ちになりました、ありがとうございました!

GRUBの設定でカーネルが認識するメモリ容量を制限する

Linux

もう年末です。今年のISUCONではpixivさんの社内ISUCONで練習させていただきました。

inside.pixiv.net

その時に気になったことがありまして。インスタンスタイプがc4.largeなのにメモリが1Gしかなくて、なんでかなーと。

$ free -m
             total       used       free     shared    buffers     cached
Mem:           998        236        762         12         11        105
-/+ buffers/cache:        119        879
Swap:            0          0          0

$ cat /proc/meminfo 
MemTotal:        1022972 kB

c4.largeのメモリは3.75GBのはずですが、1Gしか認識されていません。

どこかで制限しているのだろうけど・・・OSが認識していない、OSが起動する前に制限してる?ブートローダー?と思ったらそうでした。

/boot/grub/grub.cfg を確認すると、 mem=1G という記述があります!

linux   /boot/vmlinuz-3.16.0-4-amd64 root=UUID=e0f20fc2-3ca6-416b-8907-4050fe6120ab ro mem=1G init=/bin/systemd console=hvc0 console=ttyS0

この設定を変えてみます。 /boot/grub/grub.cfg を直接変更するのではなく、 /etc/default/grub を編集します。

参考 GRUB を設定する 〜 GRUB 2 編 - いますぐ実践! Linuxシステム管理 / Vol.202

/etc/default/grub を確認してみると

$ cat /etc/default/grub | grep GRUB_CMDLINE_LINUX
GRUB_CMDLINE_LINUX_DEFAULT="init=/bin/systemd console=hvc0 console=ttyS0"
GRUB_CMDLINE_LINUX="mem=1G"

ありますねー、 mem=1G という記述が。 GRUB_CMDLINE_LINUX にはカーネルの起動パラメータを記述できます。ここに起動パラメータを記述してOSが認識するメモリ容量を制限していました。

GRUB_CMDLINE_LINUX から mem=1G の記述を消して、以下のコマンド実行します。

$ sudo update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.16.0-4-amd64
Found initrd image: /boot/initrd.img-3.16.0-4-amd64
done

再度 /boot/grub/grub.cfg を確認してみると mem=1G がなくなっています。

linux   /boot/vmlinuz-3.16.0-4-amd64 root=UUID=e0f20fc2-3ca6-416b-8907-4050fe6120ab ro  init=/bin/systemd console=hvc0 console=ttyS0

インスタンスを再起動して、確認してみると

$ free -m
             total       used       free     shared    buffers     cached
Mem:          3774        245       3529         16         11        109
-/+ buffers/cache:        124       3650
Swap:            0          0          0

$ cat /proc/meminfo 
MemTotal:        3865596 kB

使用できるメモリが増えました!