Skip to content

Volume 10: Modules and Imports

1. Introduction

This volume defines modules, imports, namespaces, visibility, and source-level organization in the Rethon programming language. It describes modules, module names, module scope, module-level declarations, public visibility, private visibility, explicit public declarations, deferred internal visibility, source-level namespaces, import statements, module imports, selected imports, import aliases, qualified names, name resolution across modules, import conflicts, circular imports, re-exports, package management deferral, future extensions, and summary.

This document is part of the official Rethon Language Specification. It is normative rather than descriptive. Implementations, tooling, documentation systems, and other source-processing tools shall treat the rules in this volume as authoritative.

This volume does not define filesystem layout commitments, package distribution details, dependency-resolution mechanics, or runtime module-loading strategy. It defines the source-level organization of modules and the language-level rules for importing names across module boundaries.

Rethon is Python-inspired in language philosophy and Python-first in surface syntax where practical. It uses modules as source-level namespaces, public visibility by default, compiler-enforced private visibility, explicit public visibility, deferred internal visibility, leading underscores as naming conventions only, and Python-like import syntax.

Modules are the unit of source organization and public API exposure at the language level.

2. Modules

A module shall be a source-level unit of organization.

A module shall group declarations, define a namespace, and act as a boundary for imports and visibility.

Example:

module math:
    public def sqrt(value: float) -> float:
        ...

A module shall not be confused with package management, build tooling, or runtime loader mechanics.

A module is a source-level namespace unit. A package is a distribution and dependency-management unit as defined in Volume 19. These terms shall not be used interchangeably.

A module shall define source-level names and source-level exposure rules.

A module may contain declarations, type declarations, protocol declarations, functions, structs, classes, and import statements.

A module shall use the declaration and visibility rules established elsewhere in the specification.

3. Module Names

A module name shall be an identifier or dotted identifier sequence that names a module namespace.

Module names should normally use lowercase names and may use dots to reflect hierarchical organization where the language syntax and module system permit it.

Examples:

module math:
    pass

module collections.text:
    pass

A module name shall not be reserved solely because it names a module.

A module name should describe the module's conceptual namespace or source area.

Module names shall be distinct from type names, protocol names, function names, and member names within their namespace.

4. Module Scope

A module shall introduce a module scope.

Names declared at module scope shall belong to the module's namespace and shall be visible according to the visibility rules of this volume.

Module scope shall be the outermost source-level scope for declarations contained in the module.

Example:

let version: str = "1.0"
public def parse(text: str) -> str:
    return text

Module scope shall contain top-level declarations and import declarations.

A name introduced at module scope shall be visible at its declaration point, subject to any later name-resolution or import rules.

5. Module-Level Declarations

A module may contain module-level declarations of any kind permitted by the language.

Examples include:

  • functions
  • structs
  • classes
  • protocols
  • type aliases
  • constants
  • imported names

Module-level declarations shall follow the same declaration rules as other declarations, including visibility, mutability, and type annotation requirements where applicable.

Example:

public let app_name: str = "Rethon"
private let default_port: int = 8080

Module-level declarations shall participate in module namespace resolution and import behavior.

6. Public Visibility

Public visibility shall be the default visibility.

A declaration without an explicit visibility modifier shall be public unless a more specific language rule states otherwise.

Example:

let version: str = "1.0"

A public declaration shall be visible to importers of the module according to the import rules of this volume.

Explicit public shall be allowed for clarity and documentation purposes.

Example:

public def parse(text: str) -> str:
    return text

Using public shall not change the meaning of a declaration that is already public by default.

7. Private Visibility

private shall be supported and shall be compiler-enforced.

Example:

private def helper(text: str) -> str:
    return text.strip()

A private declaration shall be accessible only within the lexical region that defines it and any nested regions permitted by the language.

Private declarations shall not be importable from outside their allowed scope.

Private visibility shall apply to module-level declarations and to members of structs, classes, protocols, and other declaration kinds where the language syntax permits it.

8. Explicit Public Declarations

public shall be supported explicitly for clarity.

Example:

public struct Point:
    public x: int
    public y: int

Explicit public shall be useful when the programmer wants the source contract to stand out clearly, even though public is already the default.

Explicit public shall not alter semantics beyond making visibility explicit in source form.

9. Deferred Internal Visibility

internal shall be deferred until the module and package model is more mature.

Rethon shall not define internal semantics before the module and package model can clearly describe module boundaries, package boundaries, and cross-module exposure rules.

Until then, public and private shall be the operative visibility forms.

When the module and package model is finalized, internal may be added if it remains useful and coherent.

10. Source-Level Namespaces

Modules shall define source-level namespaces.

The declarations contained in a module shall belong to that module's namespace and shall be resolved through that namespace in the source model.

A module namespace shall be the primary organization boundary for imports and qualified names.

Modules shall support readable source organization without requiring ordinary code to depend on filesystem or build-system details.

11. Import Statements

Import statements shall follow Python-like import and from ... import ... syntax.

Examples:

import math
from collections import deque

Python-like import syntax shall be preferred because it matches the language's Python-first surface direction and is readable in ordinary source code.

Import statements shall introduce imported names into the current module scope according to the rules of this volume.

12. Module Imports

A module import shall import a module namespace.

Example:

import math

A module import shall make the module namespace available under the imported name.

A module import shall not automatically import every name from the module into the current scope unless a later language rule explicitly defines such behavior for a particular form.

Module imports shall be explicit and predictable.

13. Selected Imports

A selected import shall import a named declaration from a module.

Example:

from math import sqrt

A selected import shall import only the named declaration or declarations explicitly listed in the import statement.

Selected imports shall support clear and concise access to commonly used names.

A selected import shall import only public names unless the importing scope is permitted by the visibility rules to access private declarations directly.

14. Import Aliases

Import aliases shall be supported.

Example:

import collections.text as text
from math import sqrt as root

An alias shall introduce an alternate local name for the imported module or declaration.

An alias shall not alter the underlying module identity or declaration identity.

Import aliases shall be useful for disambiguation, readability, and concise access to long or conflicting names.

15. Qualified Names

Qualified names shall be supported for module and member access.

Example:

import math
let value = math.sqrt(4.0)

A qualified name shall refer to a name accessed through a module namespace or other later-defined namespace form.

Qualified names shall remain source-level names and shall be resolved by the language's name-resolution rules.

Qualified names shall not imply runtime reflection or dynamic lookup beyond the language's ordinary import and namespace semantics.

16. Name Resolution Across Modules

Name resolution across modules shall be explicit and deterministic.

A name shall resolve first in the local scope, then in imported namespaces, then in any other language-defined lookup paths permitted by the surrounding rules.

A private declaration shall not participate in cross-module resolution outside its allowed scope.

Public names shall be eligible for import and qualified access according to the visibility and import rules of this volume.

Name resolution shall preserve static typing and readable source contracts.

17. Import Conflicts

Import conflicts shall be diagnosed unless the programmer disambiguates them explicitly.

Example:

from math import parse
from text import parse

If two imported names would bind the same local identifier, the program shall either be rejected or require an alias that removes the ambiguity.

Example:

from math import parse as math_parse
from text import parse as text_parse

Import conflict handling shall favor clarity and compiler diagnostics over silent shadowing.

18. Circular Imports

Circular imports shall be diagnosed or tightly constrained.

The language shall not encourage import cycles that make source-level resolution ambiguous or fragile.

A later module system may allow carefully controlled circular references when they are safe and well defined, but ordinary source code should not rely on import cycles as a common pattern.

Implementations shall report circular import problems clearly when they prevent reliable resolution or loading.

19. Re-Exports

Re-exports shall be deferred or require explicit future syntax.

This volume does not commit to a general re-export mechanism.

If a future module system introduces re-exports, that feature shall be specified separately with explicit syntax and visibility rules.

For now, imported names shall be treated as imported names, not as an implicit redefinition of the module's public API surface.

20. Package Management Deferral

Package management shall be deferred to a later volume.

This volume establishes modules, namespaces, and imports without defining package distribution, dependency resolution, build-system integration, or source-tree conventions.

The language shall remain free to refine package management later without changing the source-level module and visibility rules defined here.

21. Future Extensions

This volume defines the current direction for modules and imports in Rethon, but future specification work may refine the model in carefully controlled ways.

Possible future extensions include:

  • explicit internal visibility once the package model is mature
  • re-export syntax
  • import-time aliasing refinements
  • package-level namespaces or package-qualified names
  • finer-grained module loading rules
  • additional visibility modifiers if later justified
  • module-level annotations for tooling or documentation, provided they remain source-visible and non-semantic unless explicitly defined otherwise

Any future extension shall preserve the current direction:

  • modules are source-level namespaces
  • public visibility is the default
  • private is compiler-enforced
  • public may be written explicitly
  • internal remains deferred
  • leading underscores are naming conventions only
  • imports use Python-like syntax
  • package management remains a separate future concern

22. Summary

Modules shall be the source-level namespaces of Rethon.

Declarations shall be public by default, private shall be compiler-enforced, public shall be available explicitly, and internal shall remain deferred until the module and package model is finalized.

Leading underscores shall remain naming conventions only and shall not define visibility.

Import statements shall use Python-like import and from ... import ... syntax, support aliases, and rely on explicit compiler-enforced name resolution.

Package management shall be deferred to a later volume so that the module and import model can remain focused on source-level organization and visibility.