# TODO/Plans ## General Pipeline - Transform a single file into a `CompilationUnit` AST node. - Gather all `CompilationUnit`s and determine which modules need to be built. - A module corresponds to one syntactical namespace `ns`, but not its children! - For a namespace to be used as a top-level grouping in a file, it must be declared like so: ``` decl pub ns std { decl pub ns core, http, json decl ns internal } ``` Here, `decl` indicates that the namespace is declared for top-level usage in other files. `pub` indicates that the namespace may be read from other namespaces. `std` here is the identifier for the namespace, and the contents inside its brackets are child namespaces. The list of child namespaces are all nested insided `std`, so are referenced like `std::core`, `std::http`, etc. The non-`pub` namespace `internal` is readable from within the namespace `std`, but not from outside of it. - A namespace inside a file but not `decl` (declared) can only have members *in that file*. It cannot be used as a top-level namespace in another file. However, the accessibility rules are similar to top-level namespaces: ``` ns std::core pub fn foo() = bar::baz() ns bar { fn baz = hello() prv fn hello = println("Hello, World!") } ``` In this example, the namespace `bar` is accesible from the rest of the file, but not outside of it. The function `bar::baz` can be called by within `foo`, but `hello`, being private to `bar`, can only be called by `baz`. - Once the namespaces to be compiled have been computed, create a `DmModule` for each namespace. - For each `CompilationUnit`, associate it to the correct `DmModule`, and transform its declarations into the appropriate objects, such as `DmInterface`, `DmImplementation`, `DmFunction`, or `DmConstant`. - Thus, a `DmModule` is a single-file containing all the code for one namespace, but not its child namespaces. Using the above examples, the following DmModules would be created, with their appropriate contents: - `pub ns std`: *no contents, only metadata.* - `pub ns std::core`: - `pub fn std::core::foo` - `ns std::core::bar` - `fn std::core::bar::baz` - `prv fn std::core::bar::hello`: only accessible inside `std::core::bar`. ## More Namespace Rules Top-level namespace declaration: ``` decl pub ns std ``` Nested namespace declaration and members: ``` ns std::core // indicates that all members of this file are in the std::core namespace // Indicates that array is a nested namespace in std::core, and is referencable by std::core::array pub ns array { pub int SomeInterface pub cls SomeClass : SomeInterace pub fn associated_fn() {} } ``` ## Example of std lib would be coded std/std.dm ``` decl pub ns std { decl pub ns core, http, json decl ns internal // only accessible to members of std } ``` std/core/core.dm ``` ns std /* This declaration is merged with the one in std.dm */ decl pub ns core { decl pub ns hkt } ``` std/core/array.dm ``` ns std::core use std::core::hkt::Monad pub int Array : Monad[T] {} impl ByteArray(fld raw_address: USize, fld count: USize) : Array { impl fn map(fab) { let mut rs = List(count) // dynamic list? for (let i in 0..count) { rs << fab(std::internal::mem::get_byte(raw_address + i)) } rs } impl fn flat_map(fab) { let mut rs = [] for (let i in 0..count) { rs << fab(std::internal::mem::get_byte(raw_address + i)) } rs.flatten() } } pub ns array { extern fn _of(ts: ...T): Array pub fn of(ts: ...T) = _of(ts) } ``` std/core/hkt/monad.dm ``` ns std::core::hkt pub hkt Monad[a] { fn [b] map(fab: a -> b) -> T[b] fn [b] flat_map(fab: a -> T[b]) -> T[b] def op fn pipe(fab: a -> b) -> T[b] = map(fab) def op fn pipe(fab: a -> T[b]) -> T[b] = flat_map(fab) } ``` std/core/string.dm ``` ns std::core pub int String : Monad[Char] ```