Continue(s)

Twitter:@dn0t_ GitHub:@ogrew

0918 ヒグチアイ。

f:id:taiga006:20190918204012j:plain

最近は、ヒグチアイが好きだ。
きっかけはある土曜の夕方、消すのが面倒で流しっぱなしにしていたradikoから流れてきた彼女の歌声だった。
そのとき聴こえた曲名は忘れてしまったが、彼女の強い歌声とハーモニックな曲調に強く惹かれた。

便利な時代の便利なインターネットのおかげで僕はすぐに彼女の曲をYoutubeで聴くことができた。
それにしてもヒグチアイという名前がよい。本名なのかはたまた芸名というやつなのかそれはこの際どちらでもよい。
力強さと愛らしさを敷き詰めたような、収まりの良い5文字。
ところで僕の苗字はそれだけで5文字ある。メジャーな苗字でもないので自己紹介は苗字で済ませることが多い。
そのせいか特に名前を書くときは昔から名前のほうの数文字はどうも蛇足なような気がする。
決して嫌いな名前ではないのだけれど。
幕が閉じきる前の演者の小さなおふざけのような、お母さんにばれないように子供がかごに入れたスナック菓子のような、くすぐったい蛇足感。

でも、それが僕にとって多分ちょうどいいのだと思う。
僕がヒグチアイでないように、彼女も僕(の名前)ではないからあんな素敵な声で強いメッセージを歌えるのだと思う。

当たり前か。

一番の友だちは
裏側の自分だから

いつまでも勝てなくて
ときどきはつらくなる

迷った道で拾った何かを
ポケットにつめて

ぽたり - ヒグチアイ

marshmallow-qa.com

Golangで四則演算するだけのコンパイルができた。

🐬はじめに

speakerdeck.com

buiderscon2019でのDQNEOさんのライブコーディングの発表を見て「コンパイラ作るの夢ある〜面白そ〜」となったのでforkして0からやってみました。 といってGoで書いたのでほとんど写経。ちなみに更にその親玉のchibicc8ccなんかの実際のコードも見てみました。

github.com

📝メモ

...
        case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
            intLiteral := readNumber(char)
            token := &Token{
                kind:  "intliteral",
                value: intLiteral,
            }
            tokens = append(tokens, token)
            fmt.Printf(" '%s'", token.value)
        case ';', '+', '-', '*', '/':
            token := &Token{
                kind:  "punct",
                value: string([]byte{char}),
            }
            tokens = append(tokens, token)
            fmt.Printf(" '%s'", token.value)
...

このあたりの部分はByteReaderさんが処理したものをTokenizerさんがTokenごとにうまく分割しているところ。
readNumberメソッドは数字がその後も続くようだったら最後まで見に行くやつ。

...
        switch token.value {
        case "+", "-", "*", "/":
            return &Expr{
                kind:     "binary",
                operator: token.value,
                left:     expr,
                right:    parseUnaryExpr(),
            }
...

このあたりはTokenの2つ目を見た後にそれが演算子Tokenだった場合はそれにさらに続くと期待される数値Tokenをパースさせようとするところ。
parseUnaryExprの中でparseUnaryExprを呼び出して再帰的になっている。

ちなみに余談なんですがアセンブリコードに出てくるmovq addqのqってなんなんだろう?と思って調べてみました。

検索して出てくるサンプルコードを見ていると、movq や addq ではなく mov, add と書かれているものもあります。q は quad word の略で、4 語長つまり 64bit データを扱うことを意味します。x86 では命令にビット長を明示指定することができ、b : byte (8bit)、w : word (16bit)、l : long word (32bit)、q : quad word (64bit) が指定できます。x86 はもともと 16bit CPU である 8086 から出発しているので、16bit を基準の語長(ワードサイズ)としています。

多くの場合、movq と書かず単に mov とだけ書けばアセンブラが自動的に適切な長さを判断してくれるのですが、この資料では長さを明示する方を選びました。

初学者向け x86/MacOSX 64bit アセンブリ

ということでqなくても問題なく動作しました。


root@e1219eb59aea:/mnt# echo -n '4*7' | go run main.go | ./asrun
------------ assembly(a.s) ------------
#Tokens: '4' '*' '7'

  .global main
main:
  mov $4, %rax
  mov $7, %rcx
  imul %rcx, %rax
  ret
------------    result     ------------
28
root@e1219eb59aea:/mnt# echo -n '12/3' | go run main.go | ./asrun
------------ assembly(a.s) ------------
#Tokens: '12' '/' '3'

  .global main
main:
  mov $12, %rax
  mov $3, %rcx
  mov $0, %rdx
  idiv %rcx
  ret
------------    result     ------------
4

てな具合で写経しながらではあるものの四則演算のできるアセンブリコードを吐かせることにも無事成功。

型があるとだいぶ楽ですね。
楽しかったのでまた続きをやる…かも?

参考

github.com

github.com

github.com

github.com