Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,8 @@ examples/c-consumer/out/
examples/zig-consumer/.zig-cache/
examples/zig-consumer/zig-out/
examples/zig-consumer/run-log.txt

# Local agent context (never submit)
dev/
dev.zip

5 changes: 4 additions & 1 deletion DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ Entries that only restate a diff will be deleted.
`parameters(n)` returning a many-pointer at `@offsetOf(TeExpr,"parameters")`.
Document that C's indexing past element zero is UB and that Zig never
indexes the `[1]` array past zero.
- Consequence: C ABI trees stay layout-identical without teaching Zig to
index past a declared field; all pointer arithmetic for children lives
behind documented escape hatches in `c_abi.zig`.
- Evidence: layout probe IDENTICAL; Dynamic/Closure suites green.

## D013 - Escape-hatch operational definition (Zero Unsafe)
Expand All @@ -187,7 +190,7 @@ Entries that only restate a diff will be deleted.
spirit: every hatch has an invariant comment.
- Consequence: CI fails if any hatch appears outside `c_abi.zig` or total
exceeds the threshold. Before parser/CAbiBuilder unification the measured
count was ~49-50; after consolidation it is 16 (797 audit-surface lines,
count was ~49-50; after consolidation it is 16 (799 audit-surface lines,
6 exported `te_*` functions). Per-kloc density is misleading on a tiny FFI
file; hatches-per-export and absolute audit surface are the honest denominators.
- Evidence: `docs/evidence/escape-hatches.json`.
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
**Pin:** `4a7456e2eab88b4c76053c1c4157639ccb930e2b`.
**Verify:** `docker compose up --build verify`
**Green CI (main):** https://github.com/aadi-joshi/tinyexpr.zig/actions/runs/30744156679
**Landing:** [`SUBMISSION.md`](SUBMISSION.md)

![Default suite 4930/4930 against the Zig library](docs/demo/02-suite-default.svg)

<!-- scorecard:begin -->
## Status
Expand Down
97 changes: 97 additions & 0 deletions SUBMISSION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Submission

Track **G** (C → Zig). Port of [codeplea/tinyexpr](https://github.com/codeplea/tinyexpr)
at pin `4a7456e2eab88b4c76053c1c4157639ccb930e2b` to **Zig 0.16.0**.

**One command:** `docker compose up --build verify`

**Repository:** https://github.com/aadi-joshi/tinyexpr.zig
**Tag:** `submission-v1` (annotated; four assertion counts in the message)

---

## Headline scorecard

| Config | Zig-linked | C-linked |
| --- | --- | --- |
| default | 4930/4930 | 4930/4930 |
| pow | 4924/4924 | 4924/4924 |
| natlog | 4934/4934 | 4934/4934 |
| pow_natlog | 4928/4928 | 4928/4928 |

Source: `docs/evidence/scorecard.json` (assembled by `tools/scorecard.py`).
Freeze-regen transcripts: `docs/evidence/freeze-regen/`.

Escape hatches: **16** in `src/c_abi.zig`, threshold **20**, outside count **0**.
Artifact: `docs/evidence/escape-hatches.json`.

---

## Bonus claims

| Bonus | Met? | Evidence |
| --- | --- | --- |
| Differential Fuzz Survivor (+5) | Yes | `fuzz/log.txt` (60s, 0 divergences); `docs/evidence/fragments/fuzz-certified.json` |
| Zero Unsafe (+5) | Yes (operational) | 16 hatches ≤ 20; confined; CI `escape-hatch-count` |
| Bug Catcher (+3) | Yes (filed; honest novelty) | `docs/findings.md`; upstream 136/105/141/142; PRs 143/144 |
| Decision Log (+3) | Yes | `DECISIONS.md` (33 entries) |

Allocator-misuse Track G exit criterion: **not satisfied** (honest negative).

---

## Divergences (short)

| Class | C | Port |
| --- | --- | --- |
| Deep nests | Stack overflow ([#136](https://github.com/codeplea/tinyexpr/issues/136)) | Bounded error / NULL |
| `-Dfix-fac-overflow` | Truncates | NaN for non-integers (optional) |
| Comma locales | `strtod` / `LC_NUMERIC` | Same |
| High-bit `char` | ctype UB ([#105](https://github.com/codeplea/tinyexpr/issues/105)) | No plain-`char` ctype |

Full table: `README.md`, `docs/evidence/divergences.md`.
Equivalence scope: C locale, below nest bound, no C UB.

---

## Upstream findings

| Item | Link |
| --- | --- |
| Nest overflow (confirmed) | https://github.com/codeplea/tinyexpr/issues/136 |
| Signed char ctype (confirmed) | https://github.com/codeplea/tinyexpr/issues/105 |
| `next_token` linkage (filed) | https://github.com/codeplea/tinyexpr/issues/141 |
| Locale / `strtod` (filed) | https://github.com/codeplea/tinyexpr/issues/142 |
| PR static `next_token` | https://github.com/codeplea/tinyexpr/pull/143 |
| PR unsigned char ctype | https://github.com/codeplea/tinyexpr/pull/144 |

---

## Benchmarks

Fair headline: C `-O2` vs Zig `ReleaseSafe` (Linux Docker aarch64; governor
unavailable). Safe interp arithmetic p99 about **1.03%** slower (8209 vs 8125 ns).
Protocol and full distributions: `bench/methodology.md`, `bench/results.json`,
`bench/plots/`.

---

## Limitations

- Repo must be **public** at submission (organizer rule). Confirm visibility
before the form.
- Demo **video** is a human recording from `docs/demo-script.md`; SVG segments
are committed under `docs/demo/`.
- Benches are container measurements, not bare-metal locked-CPU runs.
- Write-up side quest closes 2026-08-10 18:00 UTC (`docs/writeup.md` draft).

---

## Judge path

1. `docker compose up --build verify`
2. `docs/judge-quickstart.md`
3. `docs/evidence/self-audit.md`
4. Green CI on `main`

Self-audit and freeze notes: `docs/evidence/self-audit.md`.
20 changes: 10 additions & 10 deletions bench/logs/run-darwin.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
environment written to /Users/kavyabhand/Desktop/port/bench/out/environment.json (kind=darwin_host)
ld: warning: object file (/Users/kavyabhand/Desktop/port/bench/bin/zig-safe/lib/libtinyexpr.a[2](libtinyexpr_zcu.o)) was built for newer 'macOS' version (15.1.1) than being linked (15.0)
ld: warning: object file (/Users/kavyabhand/Desktop/port/bench/bin/zig-safe/lib/libtinyexpr.a[2](libtinyexpr_zcu.o)) was built for newer 'macOS' version (15.1.1) than being linked (15.0)
ld: warning: object file (/Users/kavyabhand/Desktop/port/bench/bin/zig-fast/lib/libtinyexpr.a[2](libtinyexpr_zcu.o)) was built for newer 'macOS' version (15.1.1) than being linked (15.0)
ld: warning: object file (/Users/kavyabhand/Desktop/port/bench/bin/zig-fast/lib/libtinyexpr.a[2](libtinyexpr_zcu.o)) was built for newer 'macOS' version (15.1.1) than being linked (15.0)
environment written to bench/out/environment.json (kind=darwin_host)
ld: warning: object file (bench/bin/zig-safe/lib/libtinyexpr.a[2](libtinyexpr_zcu.o)) was built for newer 'macOS' version (15.1.1) than being linked (15.0)
ld: warning: object file (bench/bin/zig-safe/lib/libtinyexpr.a[2](libtinyexpr_zcu.o)) was built for newer 'macOS' version (15.1.1) than being linked (15.0)
ld: warning: object file (bench/bin/zig-fast/lib/libtinyexpr.a[2](libtinyexpr_zcu.o)) was built for newer 'macOS' version (15.1.1) than being linked (15.0)
ld: warning: object file (bench/bin/zig-fast/lib/libtinyexpr.a[2](libtinyexpr_zcu.o)) was built for newer 'macOS' version (15.1.1) than being linked (15.0)
+ latency_c_o2 compile trivial 2000 20000
+ latency_c_o2 interp trivial 2000 20000
+ latency_c_o2 compile arithmetic 2000 20000
Expand Down Expand Up @@ -42,10 +42,10 @@ ld: warning: object file (/Users/kavyabhand/Desktop/port/bench/bin/zig-fast/lib/
+ latency_zig_fast eval 2000 20000
+ latency_zig_fast throughput 1.0
+ latency_zig_fast rss 1000
wrote /Users/kavyabhand/Desktop/port/bench/out/startup.json
wrote /Users/kavyabhand/Desktop/port/bench/out/artifacts.json
wrote /Users/kavyabhand/Desktop/port/bench/out/alloc_ledger.json
wrote /Users/kavyabhand/Desktop/port/bench/results.json
wrote bench/out/startup.json
wrote bench/out/artifacts.json
wrote bench/out/alloc_ledger.json
wrote bench/results.json
=== headline (p99 ns / throughput) ===
c_o2 {'compile_functions_p99_ns': 8000, 'interp_arithmetic_p99_ns': 10000, 'eval_variables_p99_ns': 1000, 'throughput_expr_per_s': 1279487.0, 'startup_warm_p50_ns': 5568500.0006633345}
zig_safe {'compile_functions_p99_ns': 8000, 'interp_arithmetic_p99_ns': 8000, 'eval_variables_p99_ns': 1000, 'throughput_expr_per_s': 1147563.0, 'startup_warm_p50_ns': 5799541.999294888}
Expand All @@ -72,4 +72,4 @@ comparison {
"pct_change_safe_vs_c": -10.310694833163604
}
}
DONE. Raw: /Users/kavyabhand/Desktop/port/bench/out/raw.jsonl Results: bench/results.json
DONE. Raw: bench/out/raw.jsonl Results: bench/results.json
2 changes: 1 addition & 1 deletion bench/methodology.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ binary existed in the image (util-linux); if absent, the run records
| `te_interp` arithmetic p99 (ns) | 8125 | 8209 | 2875 | +1.03% |
| `te_compile` functions p99 (ns) | 19750 | 10750 | 9458 | -45.57% |
| `te_eval` variables p99 (ns) | 42 | 42 | 42 | +0.00% |
| throughput shared4 (expr/s) | 949443 | 1209050 | 1148760 | +27.34% |
| throughput shared4 (expr/s) | 949442.683 | 1209049.9 | 1148760.127 | +27.34% |
| RSS ru_maxrss (KiB, 1000 trees) | 1464 | 1764 | 1468 | |
| startup warm p50 (ns) | 1335500 | 1913000 | 976708 | |

Expand Down
106 changes: 106 additions & 0 deletions docs/demo-script.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Demo script (under five minutes)

Required deliverable 07 is a live screen recording of the original suite
passing against the port. This file is the shot list and narration. SVG
terminal captures of each segment are already committed under `docs/demo/`
(generated by `docs/demo/render_svg.py` from real command transcripts in
`docs/demo/segments/`).

**Outstanding human action:** record the MP4 from this script and upload it
with the submission form **before 2026-08-03 18:00 UTC**.

## Assets already in the repo

| Segment | SVG | Transcript |
| --- | --- | --- |
| Hashes + live upstream | `docs/demo/01-hashes.svg` | `segments/01-hashes.txt` |
| Default suite 4930/4930 | `docs/demo/02-suite-default.svg` | `segments/02-suite-default.txt` |
| Four configs | `docs/demo/03-four-configs.svg` | `segments/03-four-configs.txt` |
| Nest crash vs port NULL | `docs/demo/04-nest-contrast.svg` | `segments/04-nest-contrast.txt` |
| Fuzz log 60s / 0 div | `docs/demo/05-fuzz-log.svg` | `segments/05-fuzz-log.txt` |
| Hatch gate fails then restores | `docs/demo/06-hatch-gate.svg` | `segments/06-hatch-gate.txt` |
| One-command / scorecard tip | `docs/demo/07-one-command.svg` | `segments/07-one-command.txt` |

Optional: re-record with `asciinema rec` (installed on the audit host) and
convert with `agg` if you want cast files; SVGs are enough for README inline.

## Timed shot list (total ~4:30)

### 0:00-0:25 Hashes first

Show `bash scripts/verify-original-hashes.sh` and
`bash scripts/fetch-upstream-and-diff.sh` both OK.
**Say:** "These are the upstream tests, unmodified, checked live against the
pin."

### 0:25-1:10 Default suite live

`bash scripts/run-original-suite.sh default`
Leave `ALL TESTS PASSED (4930/4930)` on screen for two seconds.
**Say:** "Same smoke.c, linked to the Zig static library."

### 1:10-1:50 Four configurations

Show the four OK lines: 4930, 4924, 4934, 4928.
**Say:** "All four compile-flag combinations. Counts are configuration
invariants, not host noise."

### 1:50-2:40 Nest contrast (the legible moment)

Split or sequential:
1. Quote C first-crash depths from the repro log (Darwin 23764 / Docker 17471).
2. Run or show `zig_abi te_compile depth=3000 -> NULL err=-1`.
**Say:** "Identical class of input. C exhausts the stack. The port returns a
bounded error."

### 2:40-3:20 Differential fuzz

Show `fuzz/log.txt` with `seconds: 60` and `divergences: 0`.
**Say:** "Sixty seconds is a duration claim. Enumeration and coverage are how
we argue reach. The log still clears the bonus bar."

### 3:20-4:00 Escape-hatch gate

Show planted hatch outside `c_abi.zig` failing (`pass: False`, ILLEGAL lines),
then restore (`pass: True`, total 16).
**Say:** "A gate that can fail is a gate that exists."

### 4:00-4:30 One command

Show README first screen and/or `docker compose up --build verify` ending in
`VERIFY OK`.
**Say:** "One command. Scorecard written from artifacts."

End black.

## Commands for the human recorder (copy in order)

```bash
cd /path/to/tinyexpr.zig
# optional clean terminal theme, large font

bash scripts/verify-original-hashes.sh
bash scripts/fetch-upstream-and-diff.sh

bash scripts/run-original-suite.sh default
bash scripts/run-original-suite.sh pow -Dpow-from-right=true
bash scripts/run-original-suite.sh natlog -Dnat-log=true
bash scripts/run-original-suite.sh pow_natlog -Dpow-from-right=true -Dnat-log=true

# nest contrast: show docs/demo/segments/04-nest-contrast.txt or re-run capture
head -20 docs/demo/segments/04-nest-contrast.txt

head -20 fuzz/log.txt

# hatch gate demo (destructive plant; script restores):
bash -c 'cp src/root.zig /tmp/root.zig.bak
python3 -c "from pathlib import Path;p=Path(\"src/root.zig\");t=p.read_text();n=\"pub const c_abi = @import(\\\"c_abi.zig\\\");\";p.write_text(t.replace(n,n+\"\\nfn _audit_plant() void { _ = @as(*const u8, @ptrCast(@as(*const u8, @ptrFromInt(1)))); }\\n\",1))"
python3 tools/count-escape-hatches.py; echo planted_exit=$?
mv /tmp/root.zig.bak src/root.zig
python3 tools/count-escape-hatches.py'

docker compose up --build verify
```

Upload the MP4 where the organizer form asks. Link it from the submission
form and, if allowed, from the README after freeze.
17 changes: 17 additions & 0 deletions docs/demo/01-hashes.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions docs/demo/02-suite-default.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions docs/demo/03-four-configs.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading