[Feature request] Namespaces for compile-time symbols
- Dominant language
- C++
- Stars
- 1.6k
- Forks
- 193
- Avg merge
- 22h 17m
- Merged PRs (30d)
- 26
Description
The [Zen of Python](https://peps.python.org/pep-0020/) says "Namespaces are one honking great idea", and it has a point.
The main use case for namespaces would be for shared libraries like [rgbds-structs](https://codeberg.org/ISSOtm/rgbds-structs). Currently authors have to either:
1. Give all their macros and constants a unique prefix. This is verbose and noisy when the macros get used often.
2. Pick names for all their macros and constants that risk colliding with names from other libraries or from the users' code.
(C lacks namespaces and also has this problem. It's why they've started using a "[`stdc_`](https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#whats-that-ugly-stdc_-prefix)" prefix for functions like `stdc_popcount`, because "`popcount`" was already known to be a popular user-defined name.)
We could add NAMESPACE name and `ENDNAMESPACE` to RGBASM, which would put all the contained symbols in a new namespace name. Users would then either use namespace-prefixed symbols, or opt-in to the namespace with USENAMESPACE name (if they're certain that none of their own symbols clash with ones defined inside name).
Prior art: [ca65](https://cc65.github.io/doc/ca65.html#ss7.3) has `.scope`/`.endscope` with a `::` separator, and [fasm](https://flatassembler.net/docs.php?article=fasmg_manual#:~:text=The%20%22namespace%22%20command) has `namespace`/`end namespace` with a `.` separator. Beyond assemblers, and even beyond programming languages, there are [many kinds of namespaces](https://en.wikipedia.org/wiki/Namespace#Naming_system), with separators like `::`, `:`, `.`, `/`, `\`, `-`, etc.
Three main questions to answer about this feature:
1. What syntax for declaring and using namespaces? I think `NAMESPACE`, `ENDNAMESPACE`, and `USENAMESPACE` keywords are fine. They're self-descriptive, and they'd be infrequently used so they don't need to be very short.
2. What syntax for namespace separators? Some common choices:
- `::` would conflict with our syntax for exported labels (e.g. `Foo::Bar` is defining and exporting label `Foo` and invoking macro `Bar`).
- `:` would conflict with our syntax for labels (e.g. `Foo:Bar` is defining label `Foo` and invoking macro `Bar`).
- `/` or `-` would conflict with binary operators (e.g. `Foo/Bar` and `Foo-Bar` are numeric expressions).
- `\` would conflict with our syntax for line continuations.
- `@` would conflict with our identifier characters (e.g. `Foo@Bar` is a valid identifier already).
- ***`->` would work***, and we don't yet have any other ideas for arrow-style operators. I'd support `Foo->Bar` for `Foo`-namespaced `Bar`.
- `=>` would also work, but we already have operators `<=`, `>=`, and `>>`, which are visually similar.
3. Should namespaces apply to labels?
- If YES, that would lead to problems:
- Emitting duplicate names in .sym files without their distinguishing namespaces would be confusing, potentially breaking for applications which need to know which symbol is which.
- Emitting namespace-qualified names in .sym files with a new kind of separator would need an update to the [.sym file spec](https://rgbds.gbdev.io/sym), which is not really supposed to depend so closely on RGBASM-specific features.
- Picking a namespace separator that's valid in .sym files would conflict with potential existing names (e.g. `Outer@Inner::`, then `NAMESPACE Outer`, then `Inner::`).
- If ***NO***, that would be less problematic:
- Users might be surprised that some symbols are not affected by namespaces.
- Users might want to have labels in a namespace hierarchy. They'll already be able to do this with nested scopes (#916).
4. Should namespaces be nestable? I think not, at least not initially; it's a complication we can consider adding later *if* there's a visible use case or user demand.
5. Should namespaces be reopenable? I think so, it's harmless and potentially useful, and would match how C++ namespaces work.
6. What should `USENAMESPACE` do inside of an opened `NAMESPACE`? It *could* copy symbols from one namespace to another, but I don't think that's a very important feature, so if it's at all difficult or problematic to implement, we could just make it an error.
**Summary:**
- NAMESPACE name starts a new namespace (or resumes an existing namespace) name for all non-label symbols inside it.
- `NAMESPACE` inside `NAMESPACE` is an error.
- Labels inside a namespace simply ignore the namespace; they all go in the top-level nameless space, and have "scopes" for their own kind of name hierarchy.
- `ENDNAMESPACE` ends the current namespace.
- `ENDNAMESPACE` without an opened `NAMESPACE` is of course an error.
- USENAMESPACE name puts all of name's symbols in the top-level nameless namespace.
- If any symbol in name is already defined at the top level (whether on its own or from a previous `USENAMESPACE`), that's an error.
- `Space->Name` refers to the symbol `Name` in the namespace `Space`.
- `->` is a new token, which should not conflict with existing ones.
Contributor guide
Research direction
Start with RGBASM's symbol and namespace behavior as described in the proposal, and review the related nested-scopes work in issue #916. Resolve the namespace syntax, separator, label handling, nesting, reopening, and USENAMESPACE rules before implementation; done means the behavior and diagnostics are specified consistently.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100