Open6

Ribbon: S式リーダーの高速化(ネイティブコード化)

okuokuokuoku

誠に遺憾ながら、S式リーダーの高速化のため時間の掛かっているトークナイザだけネイティブコードに置き換えることにした。 ...これでも遅ければ真面目なリーダーを手書きしないといけなくなるので、できればこれでそこそこ使える速度になって欲しい。。

Ribbonには、どっちにせよWebAssembly実行用を想定したインタプリタも別途載せるつもりではあるので、どこかのタイミングでバイトコードインタプリタに載せ替えれば手書きのCコードを減らせるだろう。

prev

https://zenn.dev/okuoku/scraps/7d39bfe05a1861

前は最適化入りで1分弱だった。10倍速の6秒くらいを狙いたい。

okuokuokuoku

移植するコード

トークナイザのコードは今はSchemeで書かれていて、トークナイズした結果はSchemeのvectorで渡すようになっている:

生成したvectorは:

に渡されて、実際のS式に変換される。

vectorの1要素は9要素のvectorで、Schemeのコード内ではtve(Token Vector Entry)と呼んでいる。

https://github.com/okuoku/yuni/blob/38c4bb758bd2228d2a92662b40c298f2f414a09f/lib/yuni/miniread/reader-main.sls#L60-L69

これをCのenumと構造体に変換するのが第一歩かな。

okuokuokuoku

1文字欠ける問題

... 結局全部Cに移植した。こういう事をやりたくなかったからSchemeでreaderを書いたのに。。概ね動いてると思うけど何かオブジェクトの末尾が欠ける。

(define x (string->utf8 "(aaa bbb ccc ddd) 1234 'abcd"))

(define (y x) (write (miniread-utf8-read x)) (newline))

(y x)

とりあえず1個ずらす。これ元のScheme版が間違ってるな。

https://github.com/okuoku/ribbon/commit/4d3fb5f4d2d56173a96fa3b06041e73d3e98abcb

okuokuokuoku

テスト通らない

Test: 20/35 passed.

Failed:
    ['(#\a "hoge")]  Expected: (#\a "hoge\"")  Actual: (#\a "hoge")
    ['("hoge" "hoge")]  Expected: ("hoge\"" "hoge\"")  Actual: ("hoge" "hoge")
    ['("hoge" fuga "hoge")]  Expected: ("hoge\"" fuga "hoge\"")  Actual: ("hoge" fuga "hoge")
    [obj]  Expected: ((100 () (1 2 3) 100))  Actual: ((100 () (1 2 3) 100))
    [obj]  Expected: (100)  Actual: (100)
    [obj]  Expected: (100)  Actual: (100)
    [obj]  Expected: ((100 100))  Actual: ((100 100))
    [obj]  Expected: (("ABC\""))  Actual: (("ABC"))
    [obj]  Expected: ((100 "ABC\""))  Actual: ((100 "ABC"))
    [obj]  Expected: (# (100 100))  Actual: (#(100 100))
    [obj]  Expected: (# ())  Actual: (#())
    [obj]  Expected: (#vu8 (1 2 3 4))  Actual: (#u8(1 2 3 4))
    [obj]  Expected: (#u8 (1 2 3 4))  Actual: (#u8(1 2 3 4))
    [obj]  Expected: (#u8 ())  Actual: (#u8())
    [obj]  Expected: (#vu8 (0))  Actual: (#u8(0))

(微妙に解りづらいが、 Expected が今回移植したC版の出力で、 Actual が元のScheme版になる。)

更に "\"" のような、ダブルクオートを末尾にescapeするようなケースはクラッシュしてしまう。これはゴミ入りの文字列を生成してしまっている。

    [obj]  Expected: (100)  Actual: (100)

これは多分数値がシンボルに化けている。

    [obj]  Expected: ((100 "ABC\""))  Actual: ((100 "ABC"))

これはさっき修正したoff-by-oneの逆パターンかな。。

    [obj]  Expected: (# (100 100))  Actual: (#(100 100))
    [obj]  Expected: (# ())  Actual: (#())

これ以降のvector関連のfailは、 # のようなプレフィックス部分がシンボルに化けていて、残りが単なるリストになっているように見える。