kitten
kitten copied to clipboard
Finish module system
The existing hack is a hacky hack which is actually worse than #include
.
I have two possible implementations in mind. One is akin to a mix of Haskell’s and Perl’s module systems. Important examples:
import foo | all default-exported things from foo |
import foo (bar) | only bar from foo |
import qualified foo | all default-exported things from foo with a foo. prefix |
import qualified foo (bar) | only foo.bar from foo |
… as f | as above but with f. instead of foo. |
module bar () | export nothing |
module bar (baz) | export only baz |
module bar (qualified baz) | export baz as bar.baz |
module bar (module quux) | re-export everything from quux |
module bar (qualified module quux) | re-export everything from quux with a quux. prefix |
The other option is to can the notion of modules entirely, and:
- Export everything from a file by default
- Allow hiding internal definitions somehow (
private def
?) - Use namespaces?
Either way, I want to discourage deep hierarchies. At worst it should go package.module.definition
.
Here’s my latest thinking on this.
Definitions will be private by default. In most circumstances, when we look up a name in the dictionary, we’ll give a vocabulary qualifier representing where we’re looking it up from. The metadata for a definition will contain some attribute that determines its visibility, based on the vocab hierarchy.
define foo (…) { … }
about foo:
visibility: public
The export
element will be syntactic sugar for adding this metadata.
// "export" <element>
export define foo (…) { … }
export type Bar { … }
// "export" <name>
define foo (…) { … }
type Bar { … }
export foo
export Bar
// "export" "{" <name>* "}"
define foo (…) { … }
type Bar { … }
export:
foo
Bar
The import
statement just brings a name into scope by declaring a local synonym, which can be re-exported.
// "import" <name>
// synonym bar (foo::bar)
import foo::bar
// "import" <name> "{" <name>* "}"
// synonym bar (foo::bar)
// synonym Baz (foo::Baz)
import foo:
bar
Baz
There are no wildcard imports—it should always be possible to grep the source for where an identifier came from.
The old compiler would search for files corresponding to imported modules; I’m not sure that was the right approach, so for now the compiler will only operate on a batch of sources, in dependency order. Later on, the front-end can do proper dependency calculation and loading.