Documentation

TE0010 — Multi‑Module (Tiny Layer)

Back to documentation index
---
{
  "@context": "https://nxdlang.org/schema",
  "doc_id": "TE010",
  "title": "",
  "description": "",
  "layer": "Examples",
  "category": "Tiny Examples",
  "keywords": [],
  "doc_version": "1.0",
  "status": "active"
}
---


#  TE0010 — Multi‑Module (Tiny Layer)

#  Problem Statement
Demonstrate NXD’s multi‑module system:

- Two modules: `math.ops` and `app.main`
- `EXPORT` controls visibility
- `IMPORT` brings symbols into scope
- `INIT` blocks run in dependency order
- Namespaces follow dot‑notation
- No cyclic INIT dependencies

This example shows a clean two‑module project where `app.main` imports and uses `math.ops`.

---

#  Canonical NXD (≤30 lines)
```nxd
MODULE math.ops

EXPORT FUNC ADD
EXPORT FUNC MUL

INIT:
    PRINTLN("math.ops init")

FUNC ADD(X: int, Y: int): int:
    RETURN X ADD Y

FUNC MUL(X: int, Y: int): int:
    RETURN X MUL Y


MODULE app.main
IMPORT math.ops

INIT:
    PRINTLN("app.main init")

FUNC MAIN():
    LET A SET ADD(3, 4)
    LET B SET MUL(A, 10)
    PRINTLN(B)
    RETURN none
```

---

#  Semantic Notes
- `EXPORT FUNC ADD` and `EXPORT FUNC MUL` make these functions public.  
- `IMPORT math.ops` brings exported symbols into `app.main`.  
- `INIT` blocks run in topological order:  
  1. `math.ops`  
  2. `app.main`  
- Dot‑notation module names map cleanly to file paths.  
- No cyclic INIT dependencies exist.  
- Left‑to‑right evaluation ensures `MUL(A, 10)` evaluates `A` first.  
- Backend lowering must preserve module boundaries and visibility.

---

#  Backend Outputs

### Nim
```nim
# math/ops.nim
static:
  echo "math.ops init"

proc add(x, y: int): int = x + y
proc mul(x, y: int): int = x * y

# app/main.nim
import math/ops

static:
  echo "app.main init"

proc main() =
  let a = add(3, 4)
  let b = mul(a, 10)
  echo b
```

---

### Elixir
```elixir
# math/ops.ex
defmodule Math.Ops do
  @on_load :init
  def init(), do: IO.puts("math.ops init")

  def add(x, y), do: x + y
  def mul(x, y), do: x * y
end

# app/main.ex
defmodule App.Main do
  @on_load :init
  def init(), do: IO.puts("app.main init")

  def main() do
    a = Math.Ops.add(3, 4)
    b = Math.Ops.mul(a, 10)
    IO.puts(b)
  end
end
```

---

### D
```d
// math/ops.d
module math.ops;

static this() {
    writeln("math.ops init");
}

int add(int x, int y) { return x + y; }
int mul(int x, int y) { return x * y; }

// app/main.d
module app.main;

import math.ops;

static this() {
    writeln("app.main init");
}

void main() {
    int a = add(3, 4);
    int b = mul(a, 10);
    writeln(b);
}
```

---

#  Audit Rules
- Module names must match file paths.  
- Exports must be explicit; unexported symbols remain private.  
- INIT blocks must execute in dependency order.  
- Imports must not create cyclic INIT dependencies.  
- Backend lowering must preserve namespace structure.  
- No implicit conversions allowed in arithmetic.  

---
  
These examples form the **canonical foundation** of NXD:

- CRUD  
- Concurrency  
- Channels  
- Ownership  
- Security  
- Error Handling  
- Generics  
- Runtime  
- Compiler Plugin  
- Multi‑Module