<!-- Sema documentation — Language Overview
     Sema is a new AI-native, neurosymbolic programming language most models
     have not been trained on. Full corpus: https://sema.49.12.246.95.sslip.io/llms-full.txt
     Install language support: https://sema.49.12.246.95.sslip.io/install-skill/ -->

# Language Overview

> A tour of Sema's core language — scalars, ADTs, traits, generics, effects, and static typing with local inference.

Sema's surface is Python-shaped: indentation blocks, `def`, `struct`, `enum`,
keyword arguments, comprehensions, and f-strings. If you can read Python, you can
read Sema. But Sema is **explicitly not a Python superset** — the semantics are
new, and a handful of familiar-looking constructs behave differently on purpose.

This page is the hub for the core language. It gives you the shape of everything;
each subsection below links to a page that goes deep.

:::note[What "core" means here]
This section covers the **deterministic** half of Sema — the part with the same
guarantees you'd expect from a strongly typed language. The **generative** half
(models implementing functions, calibrated similarity, semantic verbs) lives in
[Neurosymbolic](/neurosymbolic/semantic-values/), and the **operational** half
(policies, monitors, budgets) lives in [Governance](/governance/effects/). The
two halves share one type system and one verification story.
:::

## The three ideas that make Sema Sema

Before the tour, three sentences that everything else hangs on:

1. **A model can implement a function.** `simulate def … by <model>:` gives a
   function a declarative body that a language model fulfills — fenced by a `sem`
   descriptor, a token `budget`, and contracts that are actually checked. See
   [/neurosymbolic/simulate/](/neurosymbolic/simulate/).
2. **Effects are part of the type.** Every function carries a capability row like
   `!{fs.read, model.invoke}`. The deterministic core is `!{}` — provably no
   model, no I/O. The compiler tracks it; policies constrain it. See
   [/language/functions-and-effects/](/language/functions-and-effects/).
3. **There are no classes.** Composition is **traits + algebraic data types**,
   Rust-style — not inheritance. Trait objects give you open-world polymorphism;
   `enum` + `match` give you closed-world exhaustiveness. See
   [/language/traits-enums-generics/](/language/traits-enums-generics/).

## A one-screen tour

```sema
from finops.domain import Currency

# An algebraic data type: a product (struct) with fields and an invariant.
struct Money (Mergeable, Semantic):
    currency: Currency
    minor_units: i64
    invariant minor_units >= 0
    def combine(self, other: Money) -> Money !{}:
        require self.currency == other.currency
        return Money(currency=self.currency, minor_units=self.minor_units + other.minor_units)

# A sum type: exactly one of these variants, some carrying a payload.
enum Escalation:
    none
    notify(channel: str)
    page(oncall: str, deadline: Duration)

# A trait declares required behavior + provided defaults. No base class.
trait Mergeable:
    sem "Types with an associative combine, safe for unordered parallel reduction"
    def combine(self, other: Self) -> Self !{}
    law associative: combine(combine(a, b), c) == combine(a, combine(b, c))

# A bounded generic: works for any T that is Ord; the bound is the obligation.
def maximum[T: Ord](xs: list[T]) -> T !{}:
    mut best = xs[0]
    for x in xs:
        best = best.max2(x)          # a default method provided by the Ord trait
    return best

# The effect row `!{}` is a proof: this function performs no model calls and no I/O.
def total(prices: list[Money]) -> Money !{}:
    mut sum = prices[0]
    for p in prices[1:]:
        sum = sum.combine(p)
    return sum
```

Everything above is deterministic and checkable before it runs. The pieces:

## Scalars and numerics

`int` (arbitrary precision by default), sized integers `i8..i64` / `u8..u64`, and
floats `f16`/`f32`/`f64` (plus `bf16`/`f8` cast forms), `bool`, `str`, `bytes`.
Arithmetic is **checked**: overflow is a typed `OverflowError`, never a silent
wrap; division by zero raises, never returns `NaN`. Width casts (`f16(x)`,
`i8(x)`) round through the real format, so a sized type is observable, not
cosmetic.

→ [/language/types/](/language/types/)

## Algebraic data types — no `null`

`struct` for products and `enum` for sums, with generics. There is **no `null`**:
absence is `Option[T]` (`Some(x)` / `None`) and fallibility is `Result[T, E]`
(`Ok(x)` / `Err(e)`). `None` is a variant you consume by `match` or `?`, never a
reference you compare for identity.

→ [/language/types/](/language/types/) · [/language/error-handling/](/language/error-handling/)

## Traits, enums, and generics — instead of classes

Sema has **no classes and no inheritance by design**. Behavior is declared by
`trait` (required signatures + default methods + laws) and supplied by `struct`
and `enum` via `impl` or a header list. Generics are `[T]` with bounds (`[T:
Ord]`), erased at runtime. Trait objects (`list[Renderer]`) give you open-world
polymorphism; `enum` + `match` give you closed-world exhaustiveness.

→ [/language/traits-enums-generics/](/language/traits-enums-generics/)

## Functions and effects

`def name(x: T) -> R !{effects}:`. The effect row is part of the signature and
part of the function *type*, so a higher-order function cannot smuggle effects its
own row does not admit. An omitted row is **inferred** (fail-closed to `!{}`),
never a wildcard grant. Lambdas are `lambda x: e` or `x => e`.

→ [/language/functions-and-effects/](/language/functions-and-effects/) ·
[/governance/effects/](/governance/effects/)

## Control flow and pattern matching

`if`/`elif`/`else`, `for`, `while`, `with` for scoped resources, and the
declarative `loop … until <cond> max_iters N:` for bounded agent loops. `match` /
`case` destructures structs, enums, tuples, and regex captures, with
exhaustiveness checking and guards.

→ [/language/control-flow/](/language/control-flow/) ·
[/language/pattern-matching/](/language/pattern-matching/)

## Errors as typed values

No unwinding exceptions, no `raise`. Failures are typed values: `Result[T, E]`,
propagated with `?`, handled with flat `expect … / except E as e:` arms.
Contracts (`require`/`ensure`/`invariant`) raise `ContractViolation`.

→ [/language/error-handling/](/language/error-handling/)

## Modules and operators

One `.sema` file is a module; a package is the tree under a `sema.toml`.
Declarations are private by default; `pub` marks the public surface. Standard
library modules import explicitly (`from std.belief import Belief`). Operators are
functions with symbolic names and can be overloaded per type; the equality family
(`==`, `is`, `~=`) is central — `~=` returns a graded `Sim`, not a `bool`.

→ [/language/modules/](/language/modules/) · [/language/operators/](/language/operators/)

## Equations — mathematics as syntax

`equation` blocks let you transcribe mathematical notation (∀, Σ, ∇, argmin, ‖·‖)
directly; the compiler lowers it to typed, pure, natively-executed code. Native
tensors and stdlib math bindings sit alongside.

→ [/language/equations/](/language/equations/)

## How Sema differs from Python — the short list

Sema adopts the [Codon divergence list](https://github.com/exaloop/codon): the
dynamic features that break static compilation are gone.

- **No classes / inheritance / metaclasses / monkey-patching** — traits + ADTs.
- **No `null`** — `Option[T]` / `Result[T, E]`.
- **No `try`/`raise`/`finally` unwinding** — typed failures + `expect`/`except` + `with`.
- **No `assert`** — it is a reserved, rejected token with a fix-it to `ensure`/`check`.
- **No heterogeneous collections** — `list[T]`, `dict[K, V]`, `set[T]` are homogeneous.
- **Immutable bindings by default** — `mut` opts into rebinding; values are value-semantic.
- **Checked arithmetic** — overflow and division-by-zero raise, no silent wrap or `NaN`.

Everything that parses must have an effect or fail loudly — Sema's **no silent
no-ops** ethos. `sema check` flags any directive it does not recognize, so a typo
never quietly does nothing.

:::tip[Verify as you go]
The syntax on this site is new. Run `sema check <project>` after every edit — it
does the static leg (arity, fields, effect rows, trait conformance) — then
`sema run` and `sema assure`. See [/start/toolchain/](/start/toolchain/) and
[/reference/cli/](/reference/cli/).
:::
