# Modules

> How Brine splits a program across files with import, import ... as and from ... import, where module files live, and the rules for imported names.

Source: https://docs.brinelang.org/language/modules/

A module is a `.br` file. `import geometry` loads `geometry.br` from the main file’s directory, and `import util.strings` loads `util/strings.br`. You then write `geometry.area(...)`, or bring names in directly with `from geometry import area`. There are no visibility modifiers: every top-level item in a module can be imported.

```brine
import geometry                  # geometry.br
import util.strings as text      # util/strings.br, used as `text`
from geometry import Point, area # use these two names directly


fn main():
    let q = geometry.Point(x=3.0, y=4.0)
    print(Point(x=0.0, y=0.0).dist(q), area(2.0, 3.0), text.shout("hi"))
```

## A project with modules

[Section titled “A project with modules”](#a-project-with-modules)

In a project made by `brine new`, the main file is `src/main.br`, so modules live under `src/`:

```text
shapes/
├── brine.toml
├── AGENTS.md
├── README.md
└── src/
    ├── main.br
    ├── geometry.br
    └── util/
        └── strings.br
```

A module holds the same items as any file: functions, structs, enums, constants and tests. It has no `main`:

src/geometry.br

```brine
# Points, rectangles and areas.


const ORIGIN_X = 0.0


struct Point:
    x: float
    y: float


    fn dist(self, other: Point) -> float:
        let dx = self.x - other.x
        let dy = self.y - other.y
        return sqrt(dx * dx + dy * dy)


struct Rect:
    w: float
    h: float


    fn area(self) -> float:
        return area(self.w, self.h)


fn area(w: float, h: float) -> float:
    return w * h


test "a 2 by 3 rectangle":
    assert Rect(w=2.0, h=3.0).area() == 6.0
```

src/util/strings.br

```brine
# Small text helpers.


fn shout(s: str) -> str:
    return s.upper() + "!"


fn pad_left(s: str, width: int) -> str:
    if len(s) >= width:
        return s
    return " ".repeat(width - len(s)) + s
```

src/main.br

```brine
import geometry
import util.strings as text
from geometry import Point, area


fn main():
    let p = Point(x=0.0, y=0.0)
    let q = geometry.Point(x=3.0, y=4.0)
    let r = geometry.Rect(w=2.0, h=1.5)
    print(p.dist(q), area(2.0, 3.0), r.area(), geometry.ORIGIN_X)
    print(text.shout("done"), "[" + text.pad_left("7", 3) + "]")


test "points are 5 apart":
    assert Point(x=0.0, y=0.0).dist(Point(x=3.0, y=4.0)) == 5.0
```

```sh
brine run -q
```

Output

```text
5.0 6.0 3.0 0.0
DONE! [  7]
```

```sh
brine test
```

Output

```text
     Built tests [dev] in 0.09s
test points are 5 apart ... ok
test geometry: a 2 by 3 rectangle ... ok


test result: ok. 2 passed; 0 failed; finished in 0.02s
```

`brine test` runs the tests in the main file and in every module it imports. Tests from a module are named with the module first (`geometry: ...`).

Outside a project, `brine run app.br` works the same way: modules are found next to `app.br`.

## `import`

[Section titled “import”](#import)

```brine
import geometry            # use as geometry.area(...), geometry.Point(...)
import util.strings        # use as strings.shout(...)
import util.strings as s   # use as s.shout(...)
import geometry as g       # an alias works for any module
```

* `import a.b.c` loads `a/b/c.br` and binds the last part, `c`. Add `as name` to pick another name.
* Everything in the module is reached through the name: functions (`geometry.area(1.0, 2.0)`), constructors (`geometry.Point(x=1.0, y=2.0)`), types in annotations (`let ps: [geometry.Point] = []`), static methods, enum variants (`geometry.Shape.Circle(1.0)`, also in `match` patterns) and constants (`geometry.ORIGIN_X`).
* Paths are always relative to the **main file’s** directory, also in imports written inside other modules: in `src/util/strings.br`, `import geometry` loads `src/geometry.br`.
* Modules may import each other, including in a cycle.

## `from ... import`

[Section titled “from ... import”](#from--import)

`from m import a, b` makes items of `m` usable without the `m.` prefix:

```brine
from geometry import Point, Rect, area, ORIGIN_X
import geometry    # you can import the module too


fn main():
    let p = Point(x=1.0, y=2.0)
    print(area(2.0, 3.0), geometry.area(1.0, 1.0), p, ORIGIN_X)
```

Two rules keep names unambiguous:

1. `from m import x` only imports items **defined in `m` itself**. If `m` imported `x` from somewhere else, import it from there.
2. A name can’t be both imported and defined in the same module.

```brine
from geometry import Point, area


fn area(r: Point) -> float:
    return r.x * r.y


fn main():
    print(area(Point(x=2.0, y=3.0)))
```

```text
error[E0202]: `area` is imported but this module already has that name
 --> src/main.br:1:29
  |
1 | from geometry import Point, area
  |                             ^^^^ imported here
3 | fn area(r: Point) -> float:
  |    ---- also defined here
  |
  = help: rename one of them, or use `import geometry` and write `geometry.area`
  = run `brine explain E0202` for more about this error
error: could not compile due to 1 error
```

A misspelled name is [E0201](/reference/errors/#e0201), with a suggestion:

```text
error[E0201]: module `geometry` has no item `Pointt`
 --> src/main.br:1:22
  |
1 | from geometry import Pointt
  |                      ^^^^^^ not found
  |
  = help: did you mean `Point`?
  = run `brine explain E0201` for more about this error
error: could not compile due to 1 error
```

## Missing modules

[Section titled “Missing modules”](#missing-modules)

```brine
import geometry
import shape


fn main():
    print(geometry.area(1.0, 2.0))
```

```text
error[E0701]: module `shape` not found
 --> src/main.br:2:1
  |
2 | import shape
  | ^^^^^^^^^^^^ expected a file at `src/shape.br`
  |
  = help: modules are `.br` files next to the main file; `import a.b` loads `a/b.br`
  = run `brine explain E0701` for more about this error
error: could not compile due to 1 error
```

## Checking one module

[Section titled “Checking one module”](#checking-one-module)

`brine check src/geometry.br` type-checks and proves a module on its own, and `brine test src/geometry.br` runs its tests. `brine run` needs a file with `fn main` (error E0703 otherwise). `brine fmt` formats every `.br` file in the project.

## Rules

[Section titled “Rules”](#rules)

* One file is one module. `import a.b` loads `a/b.br` relative to the main file’s directory and binds `b` (or the `as` name).
* Every top-level item is importable; there is no `pub` or `private`.
* `from m import x` imports only items defined in `m`.
* A name can’t be both imported and defined in one module.
* Each module’s tests run with `brine test` once the main file imports it.

Related: [structs](/language/structs/), [testing](/language/testing/), [the CLI](/tooling/cli/), [functions](/language/functions/).
