A small toy
language. 
toy is a general purpose language which is statically typed, compiled, and garbage collected.
It aims to be ergonomic and performant but the main goal is for me to learn about language design and compiler development.
Features
A modern type system over value types, with the ergonomics you expect and none of the ceremony.
Type inference
Bind a value with := and its type is inferred. Annotate the boundaries and let the body follow.
fn main() -> int { price := 20 # inferred int quantity := 3 return price * quantity}Pattern matching
Enums hold one of several variants. match destructures them, checked for exhaustiveness at compile time.
pub enum Shape { Circle(int), Square(int) }pub fn area(shape: Shape) -> int { match shape { .Circle(r) -> 3 * r * r, .Square(side) -> side * side, }}Generics
Generic structs and functions are monomorphized. Pair[int, int] reifies to an ordinary struct — no boxing.
struct Pair[A, B] { left: A, right: B }fn main() -> int { point := Pair[int, int] { left: 3, right: 39 } return point.left + point.right}Protocols
A protocol is a set of method signatures. Conform a type with impl Square has Area and call its methods directly.
protocol Area { fn area(self) -> int}struct Square { side: int }impl Square has Area { fn area(self) -> int { self.side * self.side }}Pipes
x |> f(a) is f(x, a): the value on the left becomes the first argument, so a chain of calls reads in the order it runs.
fn double(x: int) -> int { x * 2 }fn add(a: int, b: int) -> int { a + b }fn main() -> int { score := 3 |> double |> add(36) # add(double(3), 36) return score}Closures
A lambda fn(x) { .. } captures the variables it names by reference. add(10, _) is short for a lambda, |> .m() pipes into a method, and a mut parameter writes to the caller's variable.
import std/vecfn add(a: int, b: int) -> int { a + b }fn bump(mut n: int) { n = n + 1 }fn main() -> int { count := 0 total := [5, 1, 4, 2, 3] |> .filter(fn(x) { x > 2 }) |> .map(add(10, _)) # fn(x) { add(10, x) } |> .fold(0, fn(sum, x) { count = count + 1 # shared with main, not a copy sum + x }) bump(count) # count is now 4 return total + count}No null
Option[T] and Result[T, E] are ordinary enums. The postfix ? unwraps a value or returns early on the empty case.
pub fn total(a: Option[int], b: Option[int]) -> Option[int] { x := a? y := b? Option.some(x + y)}Learn
Ready to go deeper? Walk the language tour, browse the reference, or read the source.