Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
8b8bc2c
Add first round of parser changes for beta.
Jan 2, 2026
244805d
Fix parser for current usage.
Jan 2, 2026
5512bf0
Remove 1_234 notation for now.
Jan 3, 2026
eebc896
Made parser happy
Jan 5, 2026
2d305a5
Switch to atom/noun divide.
Jan 5, 2026
2f2031f
Compiles with new atom and jnoun types.
Jan 5, 2026
5fbf967
Post
Jan 5, 2026
7347728
Paths works correctly; Aliases stubbed in.
Jan 5, 2026
5627fb5
Post docs
sigilante Jan 22, 2026
edff856
Add comprehensive Jock language state assessment
claude Jan 22, 2026
7b6129b
Merge branch 'sigilante/freshwater-ray-finned-fish' into claude/asses…
claude Jan 22, 2026
43cf315
Add struct type system implementation
claude Jan 22, 2026
a2a2b2d
Post working struct type
sigilante Jan 29, 2026
00bb487
Add struct type system support with recursive type indirection
sigilante Jan 29, 2026
1e36fd2
Implement struct mint case with bunt value
sigilante Jan 29, 2026
978ec7d
Add struct field access support and fix build tooling
sigilante Jan 29, 2026
6362fbf
Add struct keyword
sigilante Jan 30, 2026
00e3e9c
Merge pull request #5 from sigilante/sigilante/jype-refactor
sigilante Jan 30, 2026
fc17c67
Post GH workflow.
sigilante Jan 30, 2026
a4e640f
Add timeout
sigilante Jan 30, 2026
65f0b7f
Merge pull request #6 from sigilante/sigilante/jype-refactor
sigilante Jan 30, 2026
a8b1832
Implement alias keyword for type synonyms
sigilante Jan 30, 2026
8536d4f
Add chained alias example.
sigilante Jan 30, 2026
4058ee3
Post
sigilante Jan 30, 2026
58fd740
Add nested struct
sigilante Jan 30, 2026
6d8574c
Merge pull request #7 from sigilante/sigilante/jype-refactor
sigilante Jan 30, 2026
058922d
Post traits.
sigilante Jan 31, 2026
fb32ba0
Check in
sigilante Jan 31, 2026
b271b54
Fix class method calls: resolve door axis correctly
sigilante Feb 1, 2026
fd136a2
Fix traits.
sigilante Feb 1, 2026
79789c9
Implement Self type in class methods
sigilante Feb 1, 2026
4465f90
Add operator overloading.
sigilante Feb 1, 2026
a184d2a
Add arbitrary Unicode operator support.
sigilante Feb 1, 2026
3b1dcc1
Add operator whitelist.
sigilante Feb 1, 2026
27a5752
Post unary operators
sigilante Feb 2, 2026
4706914
Post
sigilante Feb 2, 2026
74c4b8e
Post
sigilante Feb 2, 2026
86a7952
Add index notation.
sigilante Feb 2, 2026
e8c3bad
Fix tuple indexing.
sigilante Feb 3, 2026
0a3faad
Add as keyword support.
sigilante Feb 3, 2026
e796e11
Upgrade as? type material.
sigilante Feb 3, 2026
4be497c
Revise compose behavior.
sigilante Feb 3, 2026
c912e90
Post kernel material.
sigilante Feb 4, 2026
2bf65c4
Post trait-in-cell fix.
sigilante Feb 4, 2026
f91b0f9
Merge pull request #8 from sigilante/sigilante/jype-refactor
sigilante Feb 4, 2026
ef9201d
Add prettyprinting basic support.
sigilante Feb 4, 2026
cc6134f
Add prettyprint support from Hoon 136.
sigilante Feb 4, 2026
e83b002
post
sigilante Feb 4, 2026
eef5a70
Update
sigilante Feb 5, 2026
188654c
Fix binop support.
sigilante Feb 5, 2026
b982376
Post tests.
sigilante Feb 5, 2026
20d176e
Fix list indexing.
sigilante Feb 6, 2026
88b8c59
Add bracket syntax AST, parser, helpers, and partial map/set compilat…
sigilante Feb 17, 2026
c8cb749
Fix parser issues: metatype comma separator, mint stubs, type checks.
sigilante Feb 17, 2026
5c45f7b
Fix map/set bracket indexing for multi-node trees.
sigilante Feb 19, 2026
6d66e31
Implement %index-has bracket syntax for maps and sets.
sigilante Feb 19, 2026
94e9b11
Post examples
sigilante Feb 19, 2026
208691c
Post
sigilante Feb 19, 2026
b0e006f
Revert hoon to reference.
sigilante Feb 21, 2026
bfc4bbd
Post syntax updates
sigilante Feb 21, 2026
acdf2cf
Revise Jock project status and release information
sigilante Feb 21, 2026
d6307a5
Update README with jockt status for February 2026
sigilante Feb 21, 2026
3f6aa02
Post
sigilante Feb 22, 2026
2299631
Finish Map/Set support with Chars.
sigilante Mar 5, 2026
7807768
Revise CI
sigilante Mar 6, 2026
d3b3e75
Add string support
sigilante Mar 7, 2026
0e0488f
Fix CI
sigilante Mar 7, 2026
78968be
Revert hoon.hoon changes
sigilante Mar 7, 2026
a3bf326
Fix CI
sigilante Mar 7, 2026
7d89601
Fix CI
sigilante Mar 7, 2026
69fcacf
Post working strings (slow) and roadmap for jetting.
sigilante Mar 8, 2026
15e18a4
Turn off CI for docs
sigilante Mar 8, 2026
7430be1
Merge pull request #9 from sigilante/sigilante/jype-refactor
sigilante Mar 27, 2026
9f990f9
Post based atom check.
sigilante Mar 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: CI

on:
push:
branches: ['**']
paths-ignore:
- '**.md'
- 'docs/**'
pull_request:
branches: [master]
paths-ignore:
- '**.md'
- 'docs/**'

env:
RUST_BACKTRACE: full
RUST_LOG: info
MINIMAL_LOG_FORMAT: true
HOONC: ~/.nockup/bin/hoonc

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly-2025-02-14

- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-

- name: Cache jockc.jam
uses: actions/cache@v4
with:
path: |
assets/jockc.jam
~/.nockapp/hoonc
key: ${{ runner.os }}-jockc-jam-${{ hashFiles('crates/jockc/hoon/**', 'common/hoon/lib/**') }}
restore-keys: |
${{ runner.os }}-jockc-jam-

- name: Install hoonc via Nockup
run: |
curl -fsSL https://raw.githubusercontent.com/nockchain/nockchain/refs/heads/master/crates/nockup/install.sh | bash
echo "$HOME/.nockup/bin" >> $GITHUB_PATH
$HOME/.nockup/bin/nockup update

- name: Build jockc.jam
# Touch source files to ensure Make sees them as newer than any cache-restored jam.
# GitHub Actions cache restore sets restored file timestamps to "now", same as checkout,
# so Make may incorrectly consider the jam up-to-date when it is actually stale.
run: |
find crates/jockc/hoon common/hoon/lib -name '*.hoon' | xargs touch
make assets/jockc.jam

- name: Build jockc
run: cargo build --profile release --bin jockc

- name: Run Jock tests
run: bash common/tests/run-all-tests.sh
env:
PARALLEL: 4
TEST_TIMEOUT: 120
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ help:

PROFILE_DEV_DEBUG = --profile dev
PROFILE_RELEASE = --profile release
HOONC = hoonc
HOONC ?= ~/.cargo/bin/hoonc

.PHONY: build
build: build-dev-debug
Expand Down Expand Up @@ -66,6 +66,12 @@ release-test-all:
.PHONY: build
build: jockc jockt ## Build the Jock compiler and tester

.PHONY: clean-jam
clean-jam: ## Clean just the jam files to force Hoon recompilation
-find assets -name '*.jam' -delete 2>/dev/null; true
-command rm -rf .data.hoonc/ 2>/dev/null; true
-command rm -rf $(HOME)/.nockapp/hoonc/ 2>/dev/null; true

.PHONY: clean
clean: ## Clean all projects
@set -e; \
Expand All @@ -84,7 +90,7 @@ assets: ## Create the assets directory
@mkdir -p assets

assets/jockc.jam: assets $(JOCKC_HOON_SOURCES)
RUST_LOG=trace MINIMAL_LOG_FORMAT=true $(HOONC) crates/jockc/hoon/main.hoon crates/jockc/hoon
RUST_LOG=trace,gnort=off MINIMAL_LOG_FORMAT=true $(HOONC) crates/jockc/hoon/main.hoon crates/jockc/hoon
mv out.jam assets/jockc.jam

assets/jockt.jam: assets $(JOCKT_HOON_SOURCES)
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Jock, a friendly and practical programming language

This is a developer preview of Jock, a friendly programming language that compiles to the [Nock instruction set architecture](#nock).
**Status February 2026** Jock was originally developed under the auspices of [Zorp Corp](https://github.com/zorp-corp), the primary developers of Nockchain. They released a developer preview and sponsored Jock's development to an alpha release before dropping it from the NockApp roadmap. However, many more features were planned for the Jock beta release and these are now underway.

- [Jock language site](https://jock.org)
- [@JockNockISA on X](https://x.com/JockNockISA)
Expand Down Expand Up @@ -117,6 +117,8 @@ If you are developing Jock code, you should use the Jock compiler tool `jockc`.

### `jockt` Jock Test Framework

**Status February 2026** `jockt` is not working during beta development because it relies on the AST which is changing quickly.

If you are developing Jock itself, you should use the Jock testing tool `jockt` to verify behavior.

9. Build the Jock testing tool:
Expand Down Expand Up @@ -171,3 +173,4 @@ If you are developing Jock itself, you should use the Jock testing tool `jockt`

- [0.0.0-dp, Developer Preview](https://zorp.io/blog/jock), ~2024.10.24
- 0.1.0-alpha, ~2025.6.26
- 0.2.0-beta, ongoing by @sigilante
141 changes: 101 additions & 40 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Roadmap

## `BasedAtom` type

Add a first-class `BasedAtom` type representing a Goldilocks prime field element — distinct from `Atom` (arbitrary precision).

A `BasedAtom` is a value in `[0, p−1]` where `p = 2^64 − 2^32 + 1`. The distinction matters for zkVM contexts where field arithmetic is the native operation and overflow-reduction is semantically significant.

### Design sketch

- Add `%based` to `jatom-type` and to the `jatom` union; surface as `BasedAtom` in Jock source.
- Parser: `BasedAtom` maps to `[%atom %based %.n]`; literals that parse as `BasedAtom` are bounds-checked at parse time (error, not warning).
- Arithmetic operators (`+`, `-`, `*`, etc.) on two `BasedAtom` operands emit field-arithmetic Nock (reduction mod p) rather than arbitrary-precision arithmetic.
- A `BasedAtom` inferred from a literal `%number` that fits in the field may be silently promoted; one that does not fit is a compile error.
- Casting: `val as BasedAtom` performs runtime reduction mod p.
- Current status: `%number` literals that exceed the field maximum produce a compile-time `%warn-unbased-atom` warning (implemented); full type-system integration is deferred until jetting is complete.

## Cache noun builds

Cache large noun builds.
Expand Down Expand Up @@ -32,11 +47,11 @@ This involves converting the single `$map` in the compiler door sample to a `mip

- Current status: libraries can be supplied to the sample of the compiler door as a `(map term cord)`. (This should be changed to `(map path cord)` for flexibility, versioning, etc.) `jockc` supports preprocessed argument insertion, but this should be replaced with this better system.

## Jock imports
## Jock imports ✅ IMPLEMENTED

Support Jock library imports just like Hoon imports.

This probably requires changing the library map to use paths as the keys instead of terms.
- Current status: `import mylib;` where `mylib.jock` is in the import directory works via AST inlining. The library's parse tree (compose/func/let chains) is spliced into the importing file at parse time. No new module system needed — the Rust loader already reads `.jock` files into the `libs` map. Library files should contain definitions only (e.g. `func double(x: Atom) -> Atom { (x + x) }; ~`).

## Hoon return types

Expand All @@ -54,18 +69,18 @@ let mylist = [1 2 3 4 5];
)
```

- Current status: the Hoon FFI permits these operations but no syntax is available.
- Current status: Index notation (`expr[idx]`) is implemented for both lists (runtime via `hoon.snag`) and tuples (compile-time axis resolution). Slicing (`[1:4]`) is not yet implemented.

## `Map` and `Set` type and syntax ✅ IMPLEMENTED

## `Map` type and syntax
Implement native `Map` and `Set` types with syntax support.

Implement a native `Map` type with syntax support.
- Current status: Map and Set are fully implemented with bracket notation only. Literal syntax: `{'a' -> 1, 'b' -> 2}` (Map), `{1, 2, 3}` (Set), `{->}` / `{}` (empty). Operations: `m[k]` (get → option), `m[k?]` (has → bool), `m[k] = v;` (put), `m[!k]` (del). Key types supported include atoms, chars, and number pairs. 92 regression tests in `common/tests/` cover all operations.

```
{
'a' -> 'A'
'b' -> 'B'
'c' -> 'C'
}
let m = {'a' -> 100, 'b' -> 200};
m['c'] = 300;
(m['a'] m['b'?] m[!'a'])
```

## Operator associativity
Expand All @@ -78,49 +93,38 @@ Implement a `List(String)` type with syntax support.

This will facilitate paths and wires for JockApp interactions.

## `print` keyword
## `print` keyword ✅ IMPLEMENTED

Produce output as a side effect.

We can print literals fine, but references (variables) are not yet complete.

```
let a = 5;
print(a);
a
```

- Current status: PR #53 contains work towards wrapping the environment in a closure so that references can be resolved at runtime.
- Current status: Runtime prettyprinting works for all basic types. `print(x)` generates Nock hint formulas that evaluate at runtime — the type (jype) selects the formatter at compile time, and the value is computed at runtime. Supported types: `%number` (decimal via `hoon.scot-ud`), `%hex` (hex via `hoon.scot-ux`), `%chars` (passthrough), `%logical` (inline `%.y`/`%.n`), and `%fork` option types (runtime none/some check).
- Known issue: Number formatting is slow (~10s per value) because the hoon library's arithmetic functions (`div`, `mod`, `add`, etc.) are not jetted. The library is compiled with `(mint ut %noun)` which produces correct Nock but battery hashes don't match the kernel's jet registrations. Fixing this requires either (a) compiling hoon.hoon in a way that produces matching battery hashes, (b) registering jets for the standalone core's batteries in the Nock runtime, or (c) caching the compiled noun (see "Cache noun builds" above) so the cost is amortized.

## `protocol` traits interface
## `protocol` traits interface ✅ IMPLEMENTED

Define a list of methods and type relations to be validated at compile time.

A `protocol` is a definition of the allowed and type signatures that a class must implement. It may be `total` (only these methods are allowed) or partial (at least these methods are allowed, default). Eventually, `protocol` will form the basis of an operator overloading system.
- Current status: Traits are implemented via `trait Name { method1; method2; }` syntax. Classes can implement traits: `class C(S) impl Trait1, Trait2 { ... }`. Operator overloading is supported: `trait Add(+) { add; }` for binary operators and `trait Neg(unary -) { neg; }` for unary operators, including arbitrary Unicode operators. `Self` type resolves in method signatures.

```
compose trait Add(+) { add; };
compose trait Sub(-) { sub; };
compose struct PointState { x: Real, y: Real };
compose
protocol Arithmetic {
add(# #) -> #;
sub(# #) -> #;
bitwidth(#) -> ##;
};

class Number implements Arithmetic {
add(x:Number y:Number) -> Number {
x + y
}
sub(x:Number y:Number) -> Number {
if (y > x) {
crash;
} else {
x - y
}
}
bitwidth(x:Number) -> Uint {
// logic to get log2 + 1
}
}
class Point(PointState) impl Add, Sub {
add(self: Self, p: Self) -> Self { ( self.x + p.x self.y + p.y ) }
sub(self: Self, p: Self) -> Self { ( self.x - p.x self.y - p.y ) }
}
;
let p = Point { x: 101, y: 105 };
let q = Point { x: 42, y: 7 };
p + q
```

## REPL development
Expand All @@ -129,16 +133,73 @@ Produce a feature-complete, fast Jock REPL/CLI.

[Jojo](https://github.com/sigilante/jojo) is a proof of concept, and does not represent any serious thought towards the "best" solution.

## Strings
## Strings ✅ IMPLEMENTED (pending jet performance)

Implement true strings with operators.

Strings should be `cord` UTF-8 encodings, as `tape`s are several times larger in memory representation. Strings may or may not be agnostic to quote type (defer this decision).
Strings are `cord` (`@t`) UTF-8 encodings. `"foo"` = `String`; `'foo'` = `Chars` (symbol/key use). Both are the same underlying atom; different Jock types.

```
let forename:String = "Buckminster";
let surname:String = "Fuller";
forename + " " + surname
```

- Current status: Right now we can write strings but operations on them must be routed through the Hoon FFI. PR #59 contains work towards supporting and testing strings.
- Current status: String and Chars literals, `+` concatenation, `lent(s)` byte-length, `s[i]` byte-index, and `s[i:j]` byte-slice are all implemented and correct. String ops compile to Nock calls to `met`/`cat`/`cut` from hoon.hoon. **Performance is very slow** because these arms are unjetted — see "Jet Matching" below. String tests hang on CI until jetting is resolved.

## Jet Matching

Enable jet dispatch for hoon.hoon arms so that string operations and arithmetic run at native speed.

### Background

Jock's compiler (`jock.hoon`) calls standard Hoon library arms (`met`, `cat`, `cut`, `add`, `sub`, etc.) from `hoon.hoon` at runtime to implement string ops and arithmetic. NockApp's jet system could replace these with fast Rust implementations — but jets only fire when the called battery has matching hint labels registered.

The hint mechanism requires:
- A core-level hint `~% %k.136 ~ ~` on the Hoon core
- Per-arm hints `~/ %arm-name` on each arm to be jetted

`hoon.hoon` already has the `~% %k.136 ~ ~` core-level hint, but has **no** per-arm `~/` hints — and `hoon.hoon` cannot be modified. As a result, the hot state entries in `crates/jockc/main.rs` register the right paths but never fire.

### Proposed fix: `jruntime.hoon`

Create a new file `common/hoon/lib/jruntime.hoon` (freely modifiable) that:

1. Has `~% %k.136 ~ ~` and per-arm `~/ %name` hints
2. Contains wet-gate wrappers that delegate to the corresponding hoon.hoon arms in the subject
3. Is compiled into `jockc.jam` as part of the Jock kernel
4. Is callable from jock.hoon's codegen for the specific arms that need jetting

Example structure:
```hoon
~% %k.136 ~ ~
|%
~/ %met
++ met |*([a=bloq b=*] (met:hoon a b))
~/ %cat
++ cat |*([a=bloq b=* c=*] (cat:hoon a b c))
~/ %cut
++ cut |*([a=bloq b=[p=@ q=@] c=*] (cut:hoon a b c))
~/ %add
++ add |*([a=@ b=@] (add:hoon a b))
:: ... all other jetted arms ...
--
```

When jetted, the Rust implementation runs directly (bypassing the wrapper body). When not jetted (fallback), the wrapper delegates to hoon.hoon — correct but slow. Two cores having the same `%k.136` label don't conflict: each registers by its own battery hash.

### Implementation steps

1. **`common/hoon/lib/jruntime.hoon`** — create the wrapper file with all arms that should be jetted. Wet gates required (dry gates cause rest-loop during jock.hoon mint). Arms needed at minimum: `met`, `cat`, `cut`, `add`, `dec`, `sub`, `mul`, `div`, `mod`, `dvr`, `gte`, `gth`, `lte`, `lth`, `mug`, `dor`, `gor`, `mor`.

2. **`crates/jockc/hoon/lib/jruntime.hoon`** — symlink or copy into jockc's lib dir so `hoonc` compiles it into `jockc.jam`.

3. **`common/hoon/lib/jock.hoon`** — add a `jruntime-lib` arm alongside `hoon-lib` that resolves the jruntime core from the Jock compiler's subject. Update `make-hoon-binop` (and `make-hoon-call`) to route jetted arms through `jruntime-lib` instead of `hoon-lib`.

4. **`crates/jockc/main.rs`** — restore hot state entries for `met`, `cat`, `cut` (removed in cleanup); verify all other entries are present. The `jet_met`/`jet_cat`/`jet_cut` Rust implementations must handle the wet-gate sample axis correctly (`+<+<` not `+<`).

5. **Build and test** — `make clean-jam && make jockc`, then run string tests; they should complete within timeout. Run full test suite to confirm no regressions.

### Known complication

Wet gate sample extraction: for a wet gate `|*([a b] ...)`, the sample is at a different axis than for a dry gate. The Rust jet implementations in `nockvm` must extract arguments at the correct axis. Confirmed axis for wet gates: `+<+<.gate` (not `+<.gate`). Verify each jet implementation handles this.
1 change: 1 addition & 0 deletions common/hoon/jib/hoon-136.hoon
12 changes: 12 additions & 0 deletions common/hoon/jib/print-demo.jock
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import hoon;

let n: Atom = 42;
print(n);

let name = 'hello';
print(name);

let sum: Atom = n + 8;
print(sum);

~
3 changes: 3 additions & 0 deletions common/hoon/jib/scot.hoon
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
|%
++ scot scot
--
2 changes: 2 additions & 0 deletions common/hoon/jib/testlib.jock
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
func double(x: Atom) -> Atom { (x + x) };
~
Loading
Loading