Skip to content

[Feature request] Namespaces for compile-time symbols #1891

@Rangi42

Description

@Rangi42

The Zen of Python 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. 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_" 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 has .scope/.endscope with a :: separator, and fasm has namespace/end namespace with a . separator. Beyond assemblers, and even beyond programming languages, there are many kinds of namespaces, 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, 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 ([Feature request] Nested label 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementTypically new features; lesser priority than bugsrgbasmThis affects RGBASM

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions