From cbaf48c04b46fadc680fa4e05e8ad22cbdaf6c47 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Thu, 26 Jan 2023 13:45:23 +0900 Subject: [PATCH] Update docs --- CONTRIBUTING.md | 2 +- doc/CONTRIBUTING/CONTRIBUTING_JA.md | 6 ++-- doc/EN/compiler/architecture.md | 54 +++++++++++++++++++++++------ doc/EN/compiler/index.md | 2 +- doc/EN/dev_guide/build_features.md | 4 +++ doc/EN/dev_guide/doc_guideline.md | 4 ++- doc/EN/dev_guide/env.md | 4 ++- doc/JA/compiler/architecture.md | 44 ++++++++++++++++------- doc/JA/dev_guide/build_features.md | 4 +++ doc/JA/dev_guide/doc_guideline.md | 2 ++ doc/JA/dev_guide/env.md | 4 ++- doc/scripts/align_files.py | 23 ++++++++++++ doc/scripts/insert_file.py | 43 +++++++++++++++++++++++ 13 files changed, 164 insertions(+), 32 deletions(-) create mode 100644 doc/scripts/align_files.py create mode 100644 doc/scripts/insert_file.py diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ad3db4c..cb00e60c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ Beginners should read the instructions [here](https://github.com/erg-lang/erg/is ## Documents -If you are thinking of contributing to Erg, you should read documents under `doc/*/dev_guide`. In particular, please pre-install what is written in `env.md`. +If you are thinking of contributing to Erg, you should read documents under `doc/*/dev_guide`. In particular, please pre-install what is written in [`env.md`](doc/EN/dev_guide/env.md). Or you are interested in the internal structure of Erg, `doc/*/compiler` may provide useful information. diff --git a/doc/CONTRIBUTING/CONTRIBUTING_JA.md b/doc/CONTRIBUTING/CONTRIBUTING_JA.md index 1081e168..e89d8fd0 100644 --- a/doc/CONTRIBUTING/CONTRIBUTING_JA.md +++ b/doc/CONTRIBUTING/CONTRIBUTING_JA.md @@ -7,7 +7,7 @@ ## ドキュメント -Erg への貢献を考えている場合は、`doc/*/dev_guide` にあるドキュメントを読む必要があります。特に`env.md`に書かれているものを事前にインストールしてください。 +Erg への貢献を考えている場合は、`doc/*/dev_guide` にあるドキュメントを読む必要があります。特に[`env.md`](../JA/dev_guide/env.md)に書かれているものを事前にインストールしてください。 Erg の内部構造に興味がある場合は、`doc/*/compiler` が役に立つかもしれません。 @@ -23,11 +23,11 @@ Ergのバグだと思われる動作を見つけた場合は、[報告](https:// 私たちは常に、ドキュメントをさまざまな言語バージョンに翻訳してくれる人を探しています。 -ドキュメントが他の言語に比べて古くなっていることに気づき、内容を更新したいという方も歓迎します ([こちら](https://github.com/erg-lang/erg/issues/48#issuecomment-1218247362) を参照)。これを行う方法について)。 +ドキュメントが他の言語に比べて古くなっていることに気づき、内容を更新したいという方も歓迎します (これを行う方法については[こちら](https://github.com/erg-lang/erg/issues/48#issuecomment-1218247362) を参照)。 ## 質問する -ご不明な点がございましたら、[Discord チャンネル](https://discord.gg/zfAAUbgGr4)までお気軽にお問い合わせください。 +ご不明な点がございましたら、[Discord チャンネル](https://discord.gg/zfAAUbgGr4)でお気軽にお問い合わせください。 ## 開発・実装に関して diff --git a/doc/EN/compiler/architecture.md b/doc/EN/compiler/architecture.md index 217a51bb..a0cb77e8 100644 --- a/doc/EN/compiler/architecture.md +++ b/doc/EN/compiler/architecture.md @@ -1,6 +1,8 @@ # Architecture of `ergc` -## 1. Scan an Erg script (.er) and generate a `TokenStream` (parser/lex.rs) +## 1. Scan an Erg script (.er) and generate a `TokenStream` + +src: [erg_parser\lex.rs](../../../crates/erg_parser/lex.rs) * parser/lexer/Lexer generates `TokenStream` (this is an iterator of `Token`, `TokenStream` can be generated by `Lexer::collect()`) * `Lexer` is constructed from `Lexer::new` or `Lexer::from_str`, where `Lexer::new` reads the code from a file or command option. @@ -9,21 +11,42 @@ * `LexerRunner` can also be used if you want to use `Lexer` as standalone; `Lexer` is just an iterator and does not implement the `Runnable` trait. * `Runnable` is implemented by `LexerRunner`, `ParserRunner`, `Compiler`, and `DummyVM`. -## 2. Convert `TokenStream` -> `AST` (parser/parse.rs) +## 2. Convert `TokenStream` -> `AST` + +src: [erg_parser\parse.rs](../../../crates/erg_parser/parse.rs) * `Parser`, like `Lexer`, has two constructors, `Parser::new` and `Parser::from_str`, and `Parser::parse` will give the `AST`. * `AST` is the wrapper type of `Vec`. It is for "Abstract Syntax Tree". ### 2.1 Desugaring `AST` +src: [erg_parser/desugar.rs](../../../crates/erg_parser/desugar.rs) + * expand nested vars (`Desugarer::desugar_nest_vars_pattern`) * desugar multiple pattern definition syntax (`Desugarer::desugar_multiple_pattern_def`) ### 2.2 Reordering & Linking `AST` -* Sort variables according to dependencies and link class methods to class definitions (`Linker::link`) +src: [erg_compiler/reorder.rs](../../../crates/erg_compiler/reorder.rs) -## 3. Type checking & inference, Convert `AST` -> `HIR` (compiler/lower.rs) +* link class methods to class definitions + * method definitions are allowed outside of the class definition file + * current implementation is incomplete, only in the same file + +## 3. Convert `AST` -> `HIR` + +(main) src: [erg_compiler/lower.rs](../../../crates/erg_compiler/lower.rs) + +## 3.1 Name Resolution + +In the current implementation it is done during type checking. + +* All ASTs (including imported modules) are scanned for name resolution before type inference. +* In addition to performing constant cycle checking and reordering, a context is created for type inference (however, most of the information on variables registered in this context is not yet finalized). + +### 3.2 Type checking & inference + +src: [erg_compiler/lower.rs](../../../crates/erg_compiler/lower.rs) * `HIR` has every variable's type information. It is for "High-level Intermediate Representation". * `ASTLowerer` can be constructed in the same way as `Parser` and `Lexer`. @@ -31,19 +54,28 @@ * `ASTLowerer` is owned by `Compiler`. Unlike conventional structures, `ASTLowerer` handles code contexts and is not a one-time disposable. * If the result of type inference is incomplete (if there is an unknown type variable), an error will occur during name resolution. -## 4. Check side-effects (compiler/effectcheck.rs) +## 4. Check side-effects -## 4. Check ownerships (compiler/memcheck.rs) +src: [erg_compiler/effectcheck.rs](../../../crates/erg_compiler/effectcheck.rs) -## 5. Desugar `HIR` (compiler/desugar_hir.rs) +## 5. Check ownerships + +src: [erg_compiler/ownercheck.rs](../../../crates/erg_compiler/ownercheck.rs) + +## 6. Desugar `HIR` + +src: [erg_compiler/desugar_hir.rs](../../../crates/erg_compiler/desugar_hir.rs) Convert parts that are not consistent with Python syntax * Convert class member variables to functions -## 6. Generate Bytecode (`CodeObj`) from `HIR` (compiler/codegen.rs) +## 7. Link -## (7. (Future plans) Convert Bytecode -> LLVM IR) +src: [erg_compiler/link.rs](../../../crates/erg_compiler/link.rs) -* Bytecode is stack-based, whereas LLVM IR is register-based. - There will be several more layers of intermediate processes for this conversion process. +* Load all modules, resolve dependencies, and combine into a single HIR + +## 8. Generate Bytecode (`CodeObj`) from `HIR` + +src: [erg_compiler/codegen.rs](../../../crates/erg_compiler/codegen.rs) diff --git a/doc/EN/compiler/index.md b/doc/EN/compiler/index.md index 6c364ff0..d162a1e2 100644 --- a/doc/EN/compiler/index.md +++ b/doc/EN/compiler/index.md @@ -26,4 +26,4 @@ ## [transpile](./transpile.md) -## [type_var_normalization.](type_var_normalization.md) \ No newline at end of file +## [type_var_normalization.](type_var_normalization.md) diff --git a/doc/EN/dev_guide/build_features.md b/doc/EN/dev_guide/build_features.md index d0928a36..2b610c48 100644 --- a/doc/EN/dev_guide/build_features.md +++ b/doc/EN/dev_guide/build_features.md @@ -36,3 +36,7 @@ Increase the thread stack size. Used for Windows execution and test execution. `--language-server` option becomes available. `erg --language-server` will start the Erg language server. + +## py_compatible + +Enable Python-compatible mode, which makes parts of the APIs and syntax compatible with Python. Used for [pylyzer](https://github.com/mtshiba/pylyzer). diff --git a/doc/EN/dev_guide/doc_guideline.md b/doc/EN/dev_guide/doc_guideline.md index 26f717a9..d4b09212 100644 --- a/doc/EN/dev_guide/doc_guideline.md +++ b/doc/EN/dev_guide/doc_guideline.md @@ -7,7 +7,9 @@ Any document that does not follow the rules below is subject to correction. * Always include definitions, meanings, or links to terms that appear for the first time in the document. * Use parentheses as a proviso only for sentences that are supplementary but necessary for understanding the main text, and use footnotes for sentences that are not essential for understanding the main text[1](#1). * If the content of the document is outdated, update it according to [this method](https://github.com/erg-lang/erg/issues/48#issuecomment-1218247362). +* Files under `syntax` should have sequential numbers at the beginning of their file names, except for those not included in the document. + * Scripts that automatically insert and replace files exist in doc/script. --- -1 See this for how to write footnotes. [↩](#f1) \ No newline at end of file +1 See this for how to write footnotes. [↩](#f1) diff --git a/doc/EN/dev_guide/env.md b/doc/EN/dev_guide/env.md index cf58fa3b..595b5e5d 100644 --- a/doc/EN/dev_guide/env.md +++ b/doc/EN/dev_guide/env.md @@ -12,7 +12,9 @@ We use pre-commit to have clippy check and test automatically. The checks may fail on the first run even if there are no bugs, in which case you should try committing again. -* Python3 interpreter +* Python3 interpreter (3.7~3.11) + +If you want to check the behavior of Erg in various versions, it is recommended to install such as [pyenv](https://github.com/pyenv/pyenv). ## Recommendation diff --git a/doc/JA/compiler/architecture.md b/doc/JA/compiler/architecture.md index 6b7b7cf9..90d5c39d 100644 --- a/doc/JA/compiler/architecture.md +++ b/doc/JA/compiler/architecture.md @@ -2,7 +2,9 @@ [![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/compiler/architecture.md%26commit_hash%3Da711efa99b325ba1012f6897e7b0e2bdb947d8a1)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/compiler/architecture.md&commit_hash=a711efa99b325ba1012f6897e7b0e2bdb947d8a1) -## 1. Erg スクリプト (.er) をスキャンし、`TokenStream` (parser/lex.rs) を生成する +## 1. Erg スクリプト (.er) をスキャンし、`TokenStream` を生成する + +src: [erg_parser/lex.rs](../../../crates/erg_parser/lex.rs) * parser/lexer/Lexer が `TokenStream` を生成する (これは `Token` のイテレータである。`TokenStream` は `Lexer::collect()` によって生成できる) * [`Lexer`](./phases/01_lex.md) は `Lexer::new` または `Lexer::from_str` から構築される。`Lexer::new` はファイルまたはコマンド オプションからコードを読み取る。 @@ -11,29 +13,43 @@ * `Lexer` を単体で使用する場合は、代わりに`LexerRunner` を使用します。`Lexer` は単なるイテレータであり、`Runnable` トレイトを実装していない。 * `Runnable` は、 `LexerRunner` 、 `ParserRunner` 、 `Compiler` 、および `DummyVM` に実装されている。 -## 2. `TokenStream` -> `AST` (parser/parse.rs) +## 2. `TokenStream` -> `AST` + +src: [erg_parser/parse.rs](../../../crates/erg_parser/parse.rs) * [`Parser`](./phases/02_parse.md) は `Lexer` と同様に `Parser::new` と `Parser::from_str` の 2 つのコンストラクタを持ち、`Parser::parse` は `AST` を返す。 * `AST`は`Vec`のラッパー型で、「抽象構文木」を表す。 ### 2.1 `AST`の脱糖 +src: [erg_parser/desugar.rs](../../../crates/erg_parser/desugar.rs) + * [`Desugarer`](./phases/03_desugar.md) * パターンマッチを単一の変数代入列へ変換 (`Desugarer::desugar_nest_vars_pattern`) * 複数パターン定義構文をmatchへ変換 (`Desugarer::desugar_multiple_pattern_def`) +### 2.2 `AST`の並び替え・結合 + +src: [erg_compiler/reorder.rs](../../../crates\erg_compiler\reorder.rs) + +* クラスメソッドをクラス定義に結合する + * メソッド定義は定義ファイル外でも可能となっている + * 現在の実装は不完全、同一ファイル内のみ + ## 3. `AST` -> `HIR` -(主要な)ソースコード: [erg_compiler/lower.rs](../../../compiler/erg_compiler/lower.rs) +(主要な)ソースコード: [erg_compiler/lower.rs](../../../crates/erg_compiler/lower.rs) ## 3.1 名前解決 +現在の実装では型チェック中に行われる + * 型推論の前に全てのAST(importされたモジュール含む)を走査し、名前解決を行う * 定数の循環検査や並び替えなどが行われるほか、型推論のためのContextが作成される(ただし、このContextに登録された変数の情報ははまだ殆どが未確定) ### 3.2 型チェックと推論 -ソースコード: [erg_compiler/lower.rs](../../../compiler/erg_compiler/lower.rs) +ソースコード: [erg_compiler/lower.rs](../../../crates/erg_compiler/lower.rs) * `HIR` は、すべての変数の型情報を持っており、「高レベルの中間表現」を表す。 * `ASTLowerer` は Parser や Lexer と同じように構築できる。 @@ -43,23 +59,25 @@ ## 4. 副作用のチェック -ソースコード: [erg_compiler/effectcheck.rs](../../../compiler/erg_compiler/effectcheck.rs) +ソースコード: [erg_compiler/effectcheck.rs](../../../crates/erg_compiler/effectcheck.rs) -## 4. 所有権の確認 +## 5. 所有権の確認 -ソースコード: [erg_compiler/ownercheck.rs](../../../compiler/erg_compiler/ownercheck.rs) +ソースコード: [erg_compiler/ownercheck.rs](../../../crates/erg_compiler/ownercheck.rs) -## 5. `HIR`の脱糖 +## 6. `HIR`の脱糖 -ソースコード: [erg_compiler/desugar_hir.rs](../../../compiler/erg_compiler/desugar_hir.rs) +ソースコード: [erg_compiler/desugar_hir.rs](../../../crates/erg_compiler/desugar_hir.rs) * Pythonの文法と整合しない部分を変換する -* クラスのメンバ変数を関数に変換 + * クラスのメンバ変数を関数に変換 -## 6. リンク +## 7. リンク + +ソースコード: [erg_compiler/link.rs](../../../crates/erg_compiler/link.rs) * 全てのモジュールを読み込み、依存関係を解決し、単一のHIRに結合する -## 7. `HIR` からバイトコード (`CodeObj`) を生成 +## 8. `HIR` からバイトコード (`CodeObj`) を生成 -ソースコード: [erg_compiler/codegen.rs](../../../compiler/erg_compiler/codegen.rs) +ソースコード: [erg_compiler/codegen.rs](../../../crates/erg_compiler/codegen.rs) diff --git a/doc/JA/dev_guide/build_features.md b/doc/JA/dev_guide/build_features.md index fbd1c969..4cfb462b 100644 --- a/doc/JA/dev_guide/build_features.md +++ b/doc/JA/dev_guide/build_features.md @@ -38,3 +38,7 @@ Erg 内部オプション、ヘルプ (ヘルプ、著作権、ライセンス `--language-server`オプションが利用可能になる。 `erg --language-server`でLanguage Serverが起動する。 + +## py_compatible + +Python互換モードを有効にする。APIや文法の一部がPythonと互換になる。[pylyzer](https://github.com/mtshiba/pylyzer)のために使用される。 diff --git a/doc/JA/dev_guide/doc_guideline.md b/doc/JA/dev_guide/doc_guideline.md index 2e09a6df..03c6d032 100644 --- a/doc/JA/dev_guide/doc_guideline.md +++ b/doc/JA/dev_guide/doc_guideline.md @@ -9,6 +9,8 @@ * ドキュメント内で初出の用語は、必ず定義や意味、またはリンクを併記する。 * ただし書きとしての()は、補助的ではあるものの本文の理解に必要な文の場合のみ使用し、本文の理解に必須でない文は脚注を使用する[1](#1)。 * ドキュメントの内容が古くなっていた場合は、[この方法](https://github.com/erg-lang/erg/issues/48#issuecomment-1218247362)に従って更新する。 +* syntax以下のファイルは、ドキュメントに含めないものを除きファイル名の頭に連番を付ける。 + * 挿入や入れ替えを自動で行うスクリプトがdoc/script内に存在する。 --- diff --git a/doc/JA/dev_guide/env.md b/doc/JA/dev_guide/env.md index 51e4f748..282d81a3 100644 --- a/doc/JA/dev_guide/env.md +++ b/doc/JA/dev_guide/env.md @@ -14,7 +14,9 @@ pre-commitを使ってclippyのチェックやテストを自動で行わせています。 バグがなくても最初の実行でチェックが失敗する場合があります。その場合はもう一度コミットを試みてください。 -* Python3インタープリタ +* Python3インタープリタ (3.7~3.11) + +様々なバージョンでErgの挙動を検査したい場合は [pyenv](https://github.com/pyenv/pyenv) 等の導入をお勧めします。 ## 推奨 diff --git a/doc/scripts/align_files.py b/doc/scripts/align_files.py new file mode 100644 index 00000000..6192accb --- /dev/null +++ b/doc/scripts/align_files.py @@ -0,0 +1,23 @@ +import os +import glob + +""" +Align file prefixes when they are not numbered consecutively. +existing files: 01_foo.md, 03_bar.md, 04_baz.md +result: 01_foo.md, 02_bar.md, 03_baz.md +""" +if __name__ == '__main__': + prev = None + diff = None + for f in sorted(glob.glob("[0-9][0-9]_*")): + if prev != None: + now_file_no = int(f.split("_")[0]) + diff = now_file_no - prev + if diff != 1: + replace_to = "_".join([f"{now_file_no-diff+1:02d}", *f.split("_")[1:]]) + os.rename(f, replace_to) + prev = now_file_no - diff + 1 + else: + prev = now_file_no + else: + prev = int(f.split("_")[0]) diff --git a/doc/scripts/insert_file.py b/doc/scripts/insert_file.py new file mode 100644 index 00000000..64dfdc71 --- /dev/null +++ b/doc/scripts/insert_file.py @@ -0,0 +1,43 @@ +import os +import sys +import glob + +""" +Insert a file into files followed by a sequential number. Existing files are shifted by one. +example: + existing files: 01_foo.md, 02_bar.md, 03_baz.md + 1st arg(inserting file): qux.md + 2nd arg(file no): 2 + result: 01_foo.md, 02_qux.md, 03_bar.md, 04_baz.md +""" +if __name__ == '__main__': + file = sys.argv[1] + file_no = sys.argv[2] + if not file_no.isdigit(): + raise ValueError('File number must be a number') + else: + file_no = int(file_no) + + if len(glob.glob("_[0-9][0-9]_*")) > 0: + raise Exception("Escaped file already exists, rename it") + # escaping + for esc in sorted(glob.glob("[0-9][0-9]_*")): + if int(esc.split("_")[0]) < file_no: continue + else: os.rename(esc, "_" + esc) + + target = f"{file_no:02d}_" + file + if os.path.exists(target): + raise OSError(f"File {target} already exists") + os.rename(file, target) + + while True: + nxt = glob.glob(f"_{file_no:02d}_*") + if len(nxt) == 0: + exit(0) + elif len(nxt) >= 2: + raise ValueError("More than one file with the same number") + else: + target = nxt[0] + replace_to = "_".join([f"{file_no+1:02d}", *target.split("_")[2:]]) + os.rename(target, replace_to) + file_no += 1