Jock
Jock compiles a high-level syntax to Nock, the twelve-opcode combinator calculus underneath Nockchain and Urbit, among other platforms. Jock models its syntax on Swift and Rust, aiming to be more approachable than Hoon while still permitting direct expression of Nock concepts: classes, generics, pattern matching and operator traits, all the way down to raw nouns.
01 » Compiles to Nock
Every Jock program erases to a noun and a formula. Structs become right-nested tuples, unions become tagged cells, and the whole language bottoms out in twelve instructions.
var a: Bool = true; a = false; a
[8 [1 0] 7 [10 [2 1 1] 0 1] 0 2]
02 » Examples
A few programs from the examples folder — each one a complete, executable program.
p + q dispatches through class conformancestruct PointState { x: Real, y: Real };
class Point(PointState) impl Add, Sub {
add(self: Self, p: Self) -> Self {
Point{ x: self.x + p.x, y: self.y + p.y }
};
sub(self: Self, p: Self) -> Self {
Point{ x: self.x - p.x, y: self.y - p.y }
};
};
let p = Point{ x: 101.0, y: 105.0 };
let q = Point{ x: 42.0, y: 7.0 };
(p + q).x
T: Lt, operators as bounds — the same < becomes a trait callfunc(T: Lt) insert(x: T, xs: List(T)) -> List(T) {
match xs {
(h, t) => if x < h { (x, xs) } else { (h, insert(x, t)) };
_ => [x];
}
};
func(T: Lt) isort(xs: List(T)) -> List(T) {
match xs {
(h, t) => insert(h, isort(t));
_ => ~;
}
};
isort([5, 3, 8, 1, 9, 2])
Kernel protocolunion Color { red, green, yellow };
struct LightState { c: Color };
func advance(c: Color) -> Color {
match c {
red => Color.green;
green => Color.yellow;
yellow => Color.red;
}
};
class Light(LightState) impl Kernel {
load(self: Light, old: *) -> Light { old as! Light };
peek(self: Light, p: *) -> * { self.c };
poke(self: Light, e: *) -> (List(Effect), Light) {
let n = advance(self.c);
(~, Light{ c: n })
};
};
Light{ c: Color.red }
impl Kernel, state threading — no driver, no import: this kernel builds and runs unchanged under jojo, the generic NockApp hoststruct KS { n: @ };
class Counter(KS) impl Kernel {
load(self: Counter, old: *) -> Counter { old as! Counter };
peek(self: Counter, p: *) -> * { self.n };
poke(self: Counter, e: *) -> (List(Effect), Counter) { (~, Counter{ n: self.n + 1 }) };
};
Counter{ n: 0 }
load's as! carries counter's exported state into totalstruct KS2 { n: @, total: @ };
class CounterV2(KS2) impl Kernel {
load(self: CounterV2, old: *) -> CounterV2 { CounterV2{ n: old as! @, total: 100 } };
peek(self: CounterV2, p: *) -> * { (self.n, self.total) };
poke(self: CounterV2, e: *) -> (List(Effect), CounterV2) { (~, CounterV2{ n: self.n + 1, total: self.total + 1 }) };
};
CounterV2{ n: 0, total: 100 }
03 » Repositories
| Track | Repository | Status |
|---|---|---|
| Alpha | zorp-corp/jock-lang | public (original release) |
| Recommenced | sigilante/jock | private (ongoing development) |
Jock is a one-man rewrite in active development. The public alpha remains the reference for the original language release by Zorp in June 2025; new feature work is happening in the recommenced repository as of August 2026.
04 » Keywords
Every keyword in the frozen 1.0 grammar — kernel forms lower to one Nockasm production apiece, sugar rewrites to an AST already covered here — each with a minimal example.
| Keyword | Syntax |
|---|---|
| let | let x: @ = 5; |
| var | var b: @ = 0; b = b + 1; |
| func | func inc(n: @) -> @ { n + 1 }; |
| lambda | let f = lambda(x: @) -> @ { x + 1 }; |
| if / else | if a == 3 { 42 } else { 17 } |
| match | match a { %1 => 0; _ => 84; } |
| switch | switch a { 1 => 0; _ => 84; } |
| loop / recur | loop { if a == b { b } else { b = b + 1; recur } } |
| eval | eval(subj, form) |
| crash | _ => crash; |
| import | import urbit; |
| as / as? / as! | (n as? Char) ?? 'x' |
| assert | assert n > 0; |
| print("count = {n}"); | |
| and / or / xor / not | if a and not b { 1 } else { 0 } |
| struct | struct PointState { x: Real, y: Real }; |
| class / impl | class Point(PointState) impl Arithmetic { … }; |
| trait | trait Arithmetic { add(self: Self, other: Self) -> Self; }; |
| alias | alias Number Real; |
| union | union Shape { point, circle(Real) }; |
| in | x in s |
defer is reserved (%defer) but its runtime semantics aren't pinned
yet, so it's left off the table above rather than shown with an invented example.