> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sensecode.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Modules

> Splitting a program across files with import ... as ..., and how member access works.

## `import ... as ...`

```sns math_utils.sns theme={null}
def square(x) -> Int:
    return x * x

def add(a, b) -> Int:
    return a + b

pi = 3.14159
```

```sns main.sns theme={null}
import "./math_utils.sns" as math

print(math.square(5))   # 25
print(math.add(2, 3))   # 5
print(math.pi)           # 3.14159
```

The path is relative to the *importing file*, resolved once per absolute
path and cached — importing the same module twice from different places in
a program executes it once. A member (`.square`, `.pi`) is read the same
way a `SenseModule`'s namespace is read for anything: whatever the module's
top-level `TypedDecl`/plain assignment/`fn` bindings are.

## Circular imports are caught, not silently broken

```sns a.sns theme={null}
import "./b.sns" as b
```

```sns b.sns theme={null}
import "./a.sns" as a
```

Running either file raises a clear `SenseImportError` naming the cycle,
rather than infinite-looping or silently returning a half-initialized
module.

## File extension

Sense source files use `.sns`.

## What's not here yet

No package manager, no versioned dependencies, no registry — module
resolution is relative file paths only, for now. See
[Roadmap](/roadmap) (Phase 5, Developer Experience) for what's planned.

## Continue

<CardGroup cols={2}>
  <Card title="Python Interop" icon="plug" href="/language/python-interop">
    `import python "module"` — calling straight into the Python ecosystem.
  </Card>

  <Card title="Testing" icon="flask" href="/language/testing">
    A real testing framework: isolated `test` blocks and `sense test`.
  </Card>
</CardGroup>
