Records and Modules
Passerine's module system is pretty simple. At it's core, a module is defined as:
my_module = mod {
x = 0
y = n -> x + 1
double = a -> 2 * a
-- ...
}
my_module::double 4
-- is 8
Basically a module turns a scope into a struct, where all top-level variables become fields on that struct. As seen in the above example, we use mod to do this.
All files are modules, and are imported using the use keyword.
-- my_module.pn
x = 0
y = n -> x + 1
double = a -> 2 * a
-- ...
-- main.pn
use my_module
my_module::double 3
-- is 2
A folder with a file named mod.pn in it is also a module. This is similar to how Rust behaves:
-- my_module/mod.pn
-- ...
-- main.pn
use nest::my_module
-- ...
Modules are resolved at compile time. Upon using use, Passerine:
- Looks for the file
X.pnorX/mod.pnin the current scope of the file being compiled - If the file has already been compiled, use the cached version
- Insert the compiled file into the current file, wrapping it all in a
modoperation.
All modules must form a tree hierarchy. i.e, there should be only one path from the root ,nest, to any other module. Modules can be mutually recursive, but in this case the full path must be specified:
-- a.pn
use nest::b
print b::x
y = "Hello, "
-- b.pn
use nest::a
print a::y
x = "World!"
-- main.pn
use nest::a
use nest::b
Modules are only executed once, upon first load. Hello, World would be printed to the terminal in the above example. Here's the big ol' todo list. If you'd like to help, I'll mentor anyone through any one of these steps:
- [ ] Implement a
Recordvariant onDatainsrc/common/data.rs, including methods for displaying it. - [ ] TODO: This will require some discussion, but we basically need to add support for paths.
- [ ] Implement lexing/parsing for the index (
::),mod <block>,use <path>, andnestkeywords. - [x] Implement lexing/parsing for record types, e.g.
{ foo: "Bar", baz: 27.5 } - [ ] Implement destructuring on record types, e.g.
{ thing: banana } = { thing: "Hello" } - [ ] Add support for compiling
modblocks to bytecode, converting them to records - [ ] Add support for indexing on records, and the
nestkeyword. - [ ] Add support for loading modules from other files. TODO: We might have to loop in Aspen to resolve these files.
- [ ] Add support for loading modules from other folders. TODO: Aspen, see above step.
- [ ] Polish and make sure everything works together.
The dev branch is a bit of a mess right now as I'm doing some big refactoring, so please make a feature branch off of master and implement any changes there. This will be a 0.9.X feature.
A language currently with the best module system is OCaml. These is a lot this can be borrowed from it.