Files
quartz-research-note/content/mimiumのモジュールシステム.md
Matsuura Tomoya(Windows) 90b0e36115
All checks were successful
Build / build (push) Successful in 11m36s
[obsidian] vault backup: 2025-08-03 22:54:20[
2025-08-03 22:54:21 +09:00

148 lines
4.1 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#mimium
モジュールシステムの意味論と実装について考える
### 必要要件
理想としては、以下を全部満たしたい
- 分割コンパイルしたうえで、コンパイル済みのモジュールは変更がなければ再利用できる
- 操作的意味論的にもある程度一貫性がある
- モジュール内ではシンボルの相互参照が可能(後から定義されるシンボルでも参照可能)
で、デザインチョイスのトレードオフとしては意味論を楽にしようと思うと分割コンパイルがめんどくさくなる
複数のコードを合体させるときに、流用されるコードの複製が増える問題
ただ、どっちみちDSPにおけるコードの量なんてたかが知れているのではという問題も
実際、そこまでモジュール内での相互参照って必要かというのもある、Letrecで十分じゃね
モジュールの循環参照が起きたらどうなるのかという問題もある
#### モジュール内での宣言一覧
```rust
//関数のvisibilityセッティングはRustとおなじ感じ
pub fn (){
}
pub const Foo = 100
pub type Bar = Constructor(()->float) //新しい型宣言
pub type alias Hoge = ()->float //エイリアス宣言
```
#### モジュールの宣言
```rust
mod(macro) modname{
//toplevel_decls
}
```
- モジュール単位でMIRとバイトコードを生成して、あとからリンクできるようにする
- ただし、ステージ0マクロの展開もしないといけないので、ASTも出力して保持していないといけない
モジュールを値としてレコード型に型付けできると話が早いんだけど、それ一級モジュールの機能だよな
#### 意味論
```rust
stage(1)
mod(0) modname{
//toplevel_decls
fn foo(){
...
}
}
modname::foo!()
```
これがあったとすると、
```rust
extern modname = ${
foo = | | { },
...
}
modname.foo!()
```
こういう感じかなー、あ、でもこうするとモジュール内での相互参照が解決できないか
トップレベルでのモジュールの名前解決は後から定義されたシンボルも参照できるので、型推論のやり方はなんか考える必要がありそう
一旦トップレベルの宣言の名前だけを回収して、あとから実際の定義の型推論を行っていく形になる
しかし、そうするとラムダ計算として定義する旨味はあんまりないのでは、という気がしてくる
`extern name : Type `という宣言に変換さえできれば意味論を保ってコンパイルはできそう
型がつけられさえすればいいから、そこで循環する定義にならなければOK
```rust
//modA.mmm
use modB
pub fn hoge(){
modB::hoge()
}
//modB.mmm
use modA
pub fn hoge(){
modA::hoge()
}
```
(ランタイムで無限ループするけどそれはいいとして)変換するとこう
```rust
// modA.mmm
extern modB:{
hoge: ?
}
fn hoge(){
modB.hoge()
}
//modB.mmm
extern modA:{//実際は型コンストラクタとかで覆って区別できるようにすべき
hoge: ?
}
fn hoge(){
modA.hoge()
}
```
`modA::hoge : 'a ()->'a, modB::hoge : 'a ()->'a `
ここまでしか型は決定できないということに
---
```
Program = FunctionDefinition
|GlobalDeclaration
|ModuleDeclaration
|use ModuleName
ModuleDeclaration = Visibility(stage) { Program }
```
Pythonのモジュールシステム [Python's Import System - Module object|Regular/Namespace Packages|Finders & Loaders|Relative imports - YouTube](https://www.youtube.com/watch?v=QCSz0j8tGmI)
モジュールはオブジェクトであり、`__file__`などはモジュールオブジェクトに付属するメンバ変数
[[Gluon]]のモジュール [Modules - Gluon Documentation](https://gluon-lang.org/doc/crates_io/book/modules.html)
これマクロとして実装してあって、それこそレコードとして出力されるだけなので、分割コンパイルとかモジュール内相互参照とかは全然考慮されてないけど意味論はすっきり