Osprey Flavors: Any Syntax, One Language
A flavor is a surface syntax, not a separate language. Each flavor parses its
own concrete syntax tree and lowers it into the canonical osprey_ast::Program;
type checking, effect checking and code generation only ever see that AST. A new
syntax is a new frontend, and every flavor gets the whole language. Osprey ships
these today:
- Default (
.osp) uses braces,fn, named arguments and familiar calls. - ML (
.ospml) uses layout, curry-by-default functions and whitespace application. - Python flavor (
.py) looks like typed Python, with decorators andwithfor effects. It is Osprey compiled byosprey; CPython never runs it.
fn add(x) = fn(y) => x + y
add x y = x + y
The compiler tests these explicit-curry forms for AST equivalence. A Default
multi-parameter function, such as fn add(x, y), is intentionally different:
it accepts two arguments at once rather than returning a function.
ML layout and matching are available in runnable examples:
classify n =
match n
0 => "zero"
1 => "one"
_ => "many"
Flavor selection works per file through .osp or .ospml, a leading source marker such as # osprey: flavor=python, or --flavor for a single-file build. A project can mix flavors and import across them.
Default and ML support effect, perform, handle and handler, and the Python flavor spells the same effects with @effect classes, perform(...), handler classes and with; see Effect Handlers You Can Call.
See the tested examples and language-flavor specification.