mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 21:01:10 +00:00
3.8 KiB
3.8 KiB
ergc のアーキテクチャ
1. Erg スクリプト (.er) をスキャンし、TokenStream
(parser/lex.rs) を生成する
- parser/lexer/Lexer が
TokenStream
を生成する (これはToken
のイテレータである。TokenStream
はLexer::collect()
によって生成できる)Lexer
はLexer::new
またはLexer::from_str
から構築される。Lexer::new
はファイルまたはコマンド オプションからコードを読み取る。Lexer
はイテレータとしてトークンを順次生成できるので、一度にTokenStream
を取得したい場合はLexer::lex
を使う。Lexer
はLexError
をエラーとして出力するが、LexError
自体には表示するだけの情報がない。エラーを表示したい場合は、LexerRunner
を使用してエラーを変換する。Lexer
を単体で使用する場合は、代わりにLexerRunner
を使用します。Lexer
は単なるイテレータであり、Runnable
トレイトを実装していない。Runnable
は、LexerRunner
、ParserRunner
、Compiler
、およびDummyVM
に実装されている。
2. TokenStream
-> AST
(parser/parse.rs)
Parser
はLexer
と同様にParser::new
とParser::from_str
の 2 つのコンストラクタを持ち、Parser::parse
はAST
を返す。AST
はVec<Expr>
のラッパー型で、「抽象構文木」を表す。
2.1 AST
の脱糖
- パターンマッチを単一の変数代入列へ変換 (
Desugarer::desugar_nest_vars_pattern
) - 複数パターン定義構文をmatchへ変換 (
Desugarer::desugar_multiple_pattern_def
)
3. AST
-> HIR
(compiler/lower.rs)
3.1 名前解決
- 型推論の前に全てのAST(importされたモジュール含む)を走査し、名前解決を行う
- 定数の循環検査や並び替えなどが行われるほか、型推論のためのContextが作成される(ただし、このContextに登録された変数の情報ははまだ殆どが未確定)
3.2 型チェックと推論 (compiler/lower.rs)
HIR
は、すべての変数の型情報を持っており、「高レベルの中間表現」を表す。ASTLowerer
は Parser や Lexer と同じように構築できる。ASTLowerer::lower
は、エラーが発生しなければ、HIR
とCompileWarnings
のタプルを出力する。ASTLowerer
はCompiler
によって所有されている。ASTLowerer
は従来の構造体とは異なり、文脈を保持し、1 回限りの使い捨てではない。- 型推論の結果が不完全な場合(未知の型変数がある場合)、名前解決時にエラーが発生する。
4. 副作用のチェック (compiler/effectcheck.rs)
4. 所有権の確認 (compiler/memcheck.rs)
5. HIR
の脱糖 (compiler/desugar_hir.rs)
-
Pythonの文法と整合しない部分を変換する
-
クラスのメンバ変数を関数に変換
6. HIR
からバイトコード (CodeObj
) を生成 (compiler/codegen.rs)
(7. (今後の予定) バイトコード -> LLVM IR)
- バイトコードはスタックベースだが、LLVM IR はレジスタベースである。 この変換プロセスには、さらにいくつかの中間プロセスのレイヤーが必要となる。