A functional language built on three pillars: safety, elegance and performance. It is algebraic with no panics, so failures are Result values you must handle; inferred types and algebraic effects express more program with less text; and it compiles through LLVM to native code. Write your application logic once; handlers connect it to storage, platform services and deterministic tests.
Osprey is actively evolving. Try it on your projects, validate it against your workload, and assess the risks before relying on it in production. It compiles through LLVM to native binaries, WebAssembly and C ABI libraries for iOS, macOS and Android.
This is the package manager's install, trimmed. install and writeLock ask for a logger and a file write with perform, but nothing passes them a disk or a logger:
effect Files { write: fn(string, string) -> Result<int, Error> }
effect Log { info: fn(string) -> Unit }
// Deep in the app: no disk or logger is passed in.
fn writeLock(lock) = match perform Files.write("osprey.lock", lock) {
Success _ => "installed"
Error { message } => "rolled back: ${message}"
}
fn install(name) = {
perform Log.info("resolving ${name}")
writeLock("${name} = 2")
}
// The app's edge picks the real disk and logger, once.
let shipped = {
handle Files { write path text => writeFile(path, text) }
handle Log { info text => print("log: ${text}") }
install("serde")
}
print(shipped)
// A test swaps in a full disk. The app code does not change.
test("a full disk rolls back", fn() => {
handle Files { write _ _ => Error { message: "disk full" } }
handle Log { info text => expect(text, "resolving serde") }
expect(install("serde"), "rolled back: disk full")
})
log: resolving serde
installed
ok 1 - a full disk rolls back
1..1
# tests=1 passed=1 failed=0 skipped=0
The program's edge installs the real disk and logger once, and every function below it uses them. The test installs a disk that is always full and a logger that checks what was logged; the app code is unchanged and no file is touched. Types are inferred, the match must cover both Success and Error, and removing a handler is a compile error.
Read the effects guide, including the ML version, or try Osprey online.
Install LLVM/clang, then install Osprey:
# macOS or Linux, with Homebrew
brew install nimblesite/tap/osprey
# Windows, with Scoop
scoop bucket add nimblesite https://github.com/Nimblesite/scoop-bucket
scoop install ospreyosprey program.osp --run
osprey program.osp --check
osprey program.osp --target=wasm32 --memory=none --compile -o program.wasmSee the installation guide for LLVM setup, supported platforms and verification.
| Start here | What you will find |
|---|---|
| src/osprey/examples/ | Runnable programs, Talon Bank, Issue Inbox and GPT-2 |
| src/toolchain/crates/ | Rust compiler, type checker, code generation, formatter, language server and debugger |
| src/osprey/packages/ | Package manager, registry server and Osprey libraries in every syntax flavor |
| src/toolchain/compiler/runtime/ | C runtime and GPU adapters |
| src/toolchain/tree-sitter-osprey/ | Default-flavor grammar |
| src/osprey/tests/ | Default and ML language suites with shared golden output |
| docs/ | Specifications, delivery plans and contributor architecture |
| src/toolchain/website/ | Language guides, reference pages and public website |
| src/toolchain/vscode-extension/, src/toolchain/webcompiler/ | Editor integration and online compiler |
| scripts/ | Build rules, validation, platform tooling and packaging support |
| docs/book/, src/toolchain/benchmarks/ | The Osprey book and measured comparisons |
The repository map explains the compilation pipeline, build entry points and where a change belongs. The contributing guide covers setup and coordination.
make setup
make build
make test
make ciRun these from the repository root. The compiler is written to target/release/osprey. The root Makefile defines every public target; their configuration and private steps live in scripts/make/.
Hunt explores symbolic inputs with KLEE: make -C src/osprey/tests/hunt hunt FILE=src/osprey/tests/hunt/crash.osp HUNT_ARGS="--input-bytes 1 --max-time 10" finds input "9" and reproduces the demo's deliberately planted C abort. Open the printed HTML report; exit status 1 is expected. The package guide covers the working folder registry, locked builds and planned package website; make -C src/osprey/packages registry-test runs its separate suites.
- Effects: typed requests, reusable value handlers, native single-shot control operations and static interpretation. Guide.
- Types: inference, algebraic data types, exhaustive matching and explicit
Resultfailures. - Any syntax, one language: every flavor's concrete syntax tree lowers into one canonical AST, so types, effects and project modules are shared. Default braces (
.osp), ML layout (.ospml) and the Python flavor (.py, Osprey that looks like Python) ship today and mix in one project. - Arithmetic: integer faults require an explicit
Arithpolicy. Contract. - Native concurrency and memory: isolated fibers; tracing GC by default, or reference counting with
--memory=arc. Unmanaged allocation requires explicit--memory=none.
GC is the native default to avoid ARC's per-ownership-change reference-count work, at the cost of deferred reclamation and collection pauses. Choose ARC for prompt reclamation, Windows or allocating fibers; neither backend is universally faster. See memory choices and limits.
Talon Bank shares web and mobile application logic; Issue Inbox shares iOS and Android state, UI descriptions and platform commands. Native hosts execute mobile SQL and HTTP commands and return completion events. GPT-2 uses two static tensor handlers for host lists and the GPU surface.
Dynamic control effects require native execution. WebAssembly and mobile support value handlers and static discharge; unsupported capabilities are rejected. Full scoped effect rows and reusable continuations remain unfinished. See feature status, specifications and active plans for the precise limits.
MIT licensed. See LICENSE and the release process.