A Module is the fundamental unit of compilation, linking, and code reuse in Ribbon. Unlike in some languages where a module is synonymous with a single source file, a Ribbon module is a collection of source files, dependencies, and language configurations defined by a single Module Definition File.

This explicit definition is essential to Ribbon’s design. Because the Ribbon Meta-Language (RML) allows for powerful syntax extension, the compiler cannot know how to parse a source file without first being told which “dialect” of Ribbon it should be using. The module definition file provides this critical, static context.

The Module Definition File (.rmod)

Every module is defined by a .rmod file. This file uses a simple, non-extensible subset of RML syntax, ensuring that the build orchestrator can always parse it reliably. Its primary purpose is to act as a manifest for the module.

Example

graphics.rmod:

;; `graphics` is the canonical name of this module, used for dependency resolution.
module graphics.
  ;; The list of source files that constitute this module's implementation.
  ;; Paths are relative to the .rmod file and can include directories,
  ;; which will be scanned recursively for `.rib` files.
  sources = [
    "renderer.rib",
    "shaders/",          ;; Includes all .rib files in this directory
    "mesh/",
  ]

  ;; A map of modules this module depends on.
  ;; The keys ('std', 'gpu') are the local aliases used in `import` statements.
  ;; The values are dependency specifiers (e.g., version strings, paths).
  dependencies = {
    std = package "core@0.1.0",
    gpu = github "tiny-bow/rgpu#W7SI6GbejPFWIbAPfm6uS623SVD",
    linalg = path "../linear-algebra",
  }

  ;; A list of language extension modules to activate for this module.
  ;; The compiler will load the public interfaces of these extensions
  ;; to configure the parser with their custom syntax rules and macros.
  extensions = [
    std/macros,
    std/dsl/operator-precedence,
    gpu/descriptors,
    linalg/vector-ops,
  ]

The Two-Phase Parsing Model

This module system enables a robust, two-phase compilation process that fully supports Ribbon’s dynamic nature:

This system allows the build orchestrator to operate deterministically on static manifests while empowering the compiler to handle the fully dynamic and extensible nature of the Ribbon language itself. It is the key to enabling a powerful, LISP-like development experience on a modern, incrementally-compiled foundation.