#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 let modname = ${ foo = | | { }, ... } modname.foo!() ``` こういう感じかなー、あ、でもこうするとモジュール内での相互参照が解決できないか トップレベルでのモジュールの名前解決は後から定義されたシンボルも参照できるので、型推論のやり方はなんか考える必要がありそう 一旦トップレベルの宣言の名前だけを回収して、あとから実際の定義の型推論を行っていく形になる しかし、そうするとラムダ計算として定義する旨味はあんまりないのでは、という気がしてくる --- ``` 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) これマクロとして実装してあるので、分割コンパイルとかは全然考慮されてないけど意味論はすっきり