# Fortis: AI-written code people can review

Fortis is a statically checked, compiled language for software written mostly by AI agents. **People can read, review and trust it because every decision is written in the source.** Ownership, changes, failures and effects are explicit.

Status: v0.0.1 release candidate. Language 1.0 is still being built and is not released.

## Examples

### Failures you can see (`mean.ft`)

Source: `README.md`. Expected output: `mean of 4 readings: 25`.

```fortis
import fortis.host { Host }

export error Empty {
  code: "demo.empty"
}

pure try func mean(readings: ListView[Int<0..1000>]) Int {
  let n = readings.count()
  if n <= 0 {
    fail Empty()
  }
  let mut total = 0
  for r in readings {
    total = Int.add(total, r) or fail
  }
  return total / n
}

export func main(args: List[String]) Void {
  let caps = Host.capabilities()
  let mut readings: List[Int<0..1000>] = List.of(12, 30, 18)
  editable readings.push(40)
  let m = mean(readings) catch e {
    report e
    recover 0
  }
  caps.console.print("mean of ${readings.count()} readings: ${m}")
}
```

Notes:

1. **Checked purity** — `pure` rules out effects such as I/O and clock access. The checker verifies it. (lines 7)
2. **Declared failure** — `try` declares that `mean` can fail. Its caller must handle the outcome. (lines 7)
3. **Bounded input** — `Int<0..1000>` carries a range. `ListView` gives read-only access. (lines 7)
4. **Visible propagation** — `Int.add` checks overflow. `or fail` passes the failure to the caller. (lines 14)
5. **Explicit changes** — `mut` declares a mutable binding. `editable` marks the call that changes the list. (lines 21–22)
6. **Caller’s recovery** — `catch` handles the failure, reports it and recovers with `0`. (lines 23–25)
7. **Host authority** — `main` obtains capabilities from the host. Printing uses the console capability. (lines 20, 27)

### Cleanup without a collector (`resource.ft`)

Source: `docs/guide/07-ownership.md#17`. Expected output: `working
release 2
release 1
done`.

```fortis
import fortis.host { Capabilities, Console, Host }

class Resource {
  export id: Int
  export console: Shared[Console]
  cleanup(editable self) Void {
    self.console.print("release ${self.id}")
  }
}

func work(console: Shared[Console]) Void {
  let first = Resource(id: 1, console: console.retain())
  let second = Resource(id: 2, console: console.retain())
  console.print("working")
}

export func main(args: List[String]) Void {
  let caps = Host.capabilities()
  let Capabilities(console: out, fileSystem: fs, network: net, clock: clock, random: rnd, environment: env, process: proc, supervisor: sup, secretAccess: sec, rawSql: sql) = move caps
  let console = Shared.create(move out)
  work(console)
  console.print("done")
}
```

Notes:

1. **Cleanup belongs to the type** — `cleanup` runs exactly once, when a `Resource` is destroyed. (lines 6–8)
2. **Counted, explicit sharing** — `Shared[Console]` is reference-counted. `retain()` takes another reference, and says so. (lines 5, 12–13)
3. **Destroyed in reverse order** — When `work` returns, `second` is destroyed before `first`, so the output reads `release 2` then `release 1`. No garbage collector decides when. (lines 12–13, 15)
4. **Authority unpacked once** — `main` takes the host's capabilities apart with `move`, and shares the console with the code it calls. (lines 18–20)
5. **Lent, not given away** — `work(console)` borrows the handle. `main` still owns it afterwards, and prints `done`. (lines 21–22)

### Patterns that take ownership (`parcel.ft`)

Source: `docs/guide/09-classes.md#24`. Expected output: `books: 2500 g
false`.

```fortis
import fortis.host { Host }

class Parcel {
  export label: String
  export grams: Int
}

pure func heavy(p: owned Parcel) Bool {
  return match move p {
    Parcel(label: _, grams: g) => g > 1000
  }
}

export func main(args: List[String]) Void {
  let caps = Host.capabilities()
  let parcel = Parcel(label: "books", grams: 2500)
  let Parcel(label: label, grams: grams) = move parcel
  caps.console.print("${label}: ${grams} g")
  caps.console.print("${heavy(Parcel(label: "feather", grams: 1))}")
}
```

Notes:

1. **Ownership in the signature** — `owned Parcel` means `heavy` takes the parcel. The caller gives it up. (lines 8)
2. **Pure, and checked** — `pure`: no effects at all. The checker verifies the claim. (lines 8)
3. **Consume and take apart** — `match move p` consumes the parcel. The pattern binds the field it needs, and `_` discards the label. (lines 9–10)
4. **Destructuring a move** — `let Parcel(…) = move parcel` takes the fields out. `parcel` can't be used after this line. (lines 17)
5. **Fresh values need no marker** — A constructor's result is a fresh value, so it goes straight into `heavy` without `move`. (lines 19)

### Recover, report or pass on (`half.ft`)

Source: `docs/guide/10-outcomes.md#3`. Expected output: `0 4
half of 6 is 3
3 has no half`.

```fortis
import fortis.host { Host }

export error NotEven {
  code: "demo.not_even"
  payload { value: Int }
}

pure try func half(n: Int) Int {
  if n % 2 != 0 {
    fail NotEven(value: n)
  }
  return n / 2
}

pure recovers func halfOrZero(n: Int) Int => half(n) or recover 0

recovers func describe(n: Int) String {
  return match half(n) {
    success(v) => "half of ${n} is ${v}"
    failure(f) => {
      report f
      give "${n} has no half"
    }
  }
}

export recovers func main(args: List[String]) Void {
  let caps = Host.capabilities()
  caps.console.print("${halfOrZero(7)} ${halfOrZero(8)}")
  caps.console.print(describe(6))
  caps.console.print(describe(3))
}
```

Notes:

1. **Errors are declared** — An error has a stable code and a typed payload. (lines 3–6)
2. **Failing is in the signature** — `try` says `half` can fail, and `fail` is where it does. (lines 8, 10)
3. **Recover in place** — `or recover 0` handles the failure on the spot. (lines 15)
4. **Or match on the outcome** — `match` sees success and failure as two explicit cases. (lines 18–20)
5. **Nothing is lost** — `report f` records the failure before carrying on with a value. (lines 21–22)
6. **Recovery is visible** — `recovers` is transitive: a function that absorbs a failure says so, and so does every function that reaches one, up to `main`. (lines 15, 17, 27)

## Try it

From a checkout of the repository, with Python 3 and a Rust toolchain:

```sh
cargo build --release --manifest-path compiler/Cargo.toml
bin/fortis check mean.ft
bin/fortis run mean.ft
```

The same program runs on the definitional interpreter (`bin/fortis run`), the development VM (`compiler/target/release/fortisc vm`) and native code (`bin/fortis build`), and all three must agree.

## Roadmap

- **v0.0.1 (now)**: write, check, run, build, format and test programs. Modules, functions, classes, enums, ownership and failures.
- **v0.0.2**: source conventions. Fewer markers, capabilities as parameters and built-in logging.
- **v0.1**: domain modelling. Interfaces, generics, refinements and contracts.
- **v0.2**: effects and testing. Checked effects, property tests and packages with dependencies.
- **v0.3**: concurrency. Async, tasks and structured concurrency.
- **v0.4**: standard library. Collections, text, Unicode and numerics.
- **v0.5–0.6**: production tooling. Observation, runtime, kits and an incremental compiler.
- **v1.0**: stability. Editions, migration and a stability promise. Performance judged against Rust.

## Licence

Developed by Pickering Technologies Ltd. Released under the MIT License.
