Rytl開発日記
from Rytl
参考
Cコンパイラをスクラッチから開発してみた(日記) - Qiita
Goコンパイラをゼロから作って147日でセルフホストを達成した - Qiita
1日目
2019/6/17
特に構想が定まったわけではないが、作りたさが止まらないのと、中間試験が終わったので、ちょっとだけ作ってみる。どうせlexerぐらいまでしか進まないので大丈夫だろう。
とりあえず動かずのを目的に、最初は-も/もないもので進めていく
Rustについて知らないことが多いので、いちいち調べていると凄い時間がかかってしまうが、よくわからないまま使うよりは良いだろうということでその辺はのろのろやっている
monkey-nimとrust_LL_parserを参考に作っているが、両者のアプローチが異なるので、最初戸惑った
Lexerは再帰的に呼び出すわけではないんだな。
前者はLexerオブジェクトに対し、.nextToken()を呼ぶごとに1Tokenを返す
めっちゃインタプリタ的でパースする合間に字句解析しているイメージ
後者はlex()を呼ぶと、input全てをToken列にしVec<Token>を返す
やったこと
+、*、Num用の字句解析
fcb8b12
次やること
-, /,spaceの追加
(,)の追加
monkey-nimなどを参考にTokenTypeの定義
2日目
2019/6/20
あんまり開発に時間が取れないので、こまめにやっていく。
Tokenの追加は、前回のときのとほぼ同じなので-や/、(、)、 などは秒で追加できた。
あと、ファイル分割もした。
ここからは、リファクタとパーサー作りに入る。
そしてインクリメンタルにtokenを増やしていこう。
インデントに意味をもたせるなら、Annotとかをいじればいいのか?
というかまだ、ASTにしたものをどう使うかを考えていないので、どうしようかってなっている。LLVM IRを吐くのか、アセンブリ言語を吐くのか、他の方法をやるか。
ASTの型を作る
単項演算子UniOpと二項演算子BinOp
lhsは右辺値、light-hand side
3日目
2019/6/26
parserを実装した。まだまだRustに慣れておらずRustのIterator周りや、RustのBorrowingなどで躓いた。
やったこと
parserの実装
f4b7f1b
parserとevalを実装
ファイル分割のリファクタリング
4日目
2019/7/4
今日は余り時間がなさそうなので、地味だが大事って感じのエラー周りを実装していく。あと、テストも。
左再帰の除去の除去をし、parserのテスト、Errorの追加をした
5日目
2019/7/5
単項演算子とテストの追加をする。時間がアレば変数も使えるようにしていく
マクロと単項演算子を追加して、テストを修正した。
そろそろ名前決めようぜ
6日目
2019/7/8
multi_peek()と格闘する
2019/7/8 LL(2)パーサーの実装に関して詰まっていることを@ironoir氏に見てもらった
助言を頂いたおかげでとりあえず実装はできた
#bbb66. 汚いが、敢えてそのままcommitした
様々な演算すると頻繁に落ちるので、その演算式をメモっておいて
それを満たすテストケース
落とさないようにするためのエラーハンドリング
を記述しないといけないぞmrsekut.icon
7日目
2019/7/10
ちょっと慣れきたな
出ていたバグを全部潰して、テストを追加した
次やること
%, ^の演算
関数の実装
ASTをformatして出力する関数
いるかな?
実際のファイルを読み込んで実行する機構
コメント
現状、テスト書くのがだるすぎるので何かしらの工夫が必要
#あとで調べる
HashMap
Stringとstr
理解
code:rs
// ↓の理解
pub fn var(s: impl Into<String>, loc: Loc) -> Self {
Self::new(TokenKind::Var(s.into()), loc)
}
//
let s = from_utf8(&inputstart..end)
//
// ↓コレの理解。使い回せるなら使う
fn recognize_many(input: &u8, mut pos: usize, mut f: impl FnMut(u8) -> bool) -> usize {
while pos < input.len() && f(inputpos) {
pos += 1;
}
pos
}
//
clone()
本当に完全に安全なものを作るならCloneやCopyトレイとは実装しないほうがいいの?
これらを使ったときのデメリットはどこ?
deriveの中身
タプルのアクセス方法
p.357になるCellを使った方法
Result型みたいな、型引数とるやつRustでは総称してなんと呼ぶんだ?
HaskellならListモナドみたいな
macroの書き方
そもそもmacroとは
Rustの文字列型
b"0123456789"
コンビネータについて
consume_byte(input, start, b'+').map(|(_, end)| (Token::plus(Loc(start, end)), end))
引数が関数のときの型
f: impl FnMut(u8) -> bool
unwrap, parse()
let n = from_utf8(&input[start..end]).unwrap().parse().unwrap();
Fromってなに
FromStrってなに
関数名()?の?ってなに
fn source(&self) -> Option<&(dyn StdError + 'static)> {
でぃん!
eprintln
rustで書いたところまでをその言語で書くならどんな感じになるのかメモっていけば??