Records and Modules
slightknack opened this issue · 1 comments
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.pn
orX/mod.pn
in 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
mod
operation.
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
Record
variant onData
insrc/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>
, andnest
keywords. - 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
mod
blocks to bytecode, converting them to records - Add support for indexing on records, and the
nest
keyword. - 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.