Skip to content

Commit 382de76

Browse files
committed
P1: fix Zig FFI to build and match the Idris2 ABI
The Zig FFI in src/interface/ffi/src/main.zig failed `zig test src/main.zig -lc` under Zig 0.14.0 and one test asserted behaviour the ABI contract does not provide. Errors found: 1. Compile error: `array_list.ArrayListAligned` no longer exposes `popOrNull`. `oblibeniser_undo_pop` called `h.undo_stack.popOrNull()`, which does not exist in Zig 0.14.0. 2. Test failure: the "compute and verify inverse" test finalised the operation with a null (0) post-snapshot pointer, so `post_snapshot` stayed null and `oblibeniser_compute_inverse` correctly returned `not_reversible` (per its contract: an inverse needs both pre- and post-state snapshots). The test asserted `ok`, so it failed. Fixes: 1. Replaced `popOrNull()` with `pop()`, which in Zig 0.14.0 already returns an optional (`?T`); the `orelse` empty-stack handling is unchanged. 2. Updated the test to record with a real pre-state snapshot and finalise with a real post-state snapshot, then assert `ok` for compute_inverse and additionally verify_inverse. This exercises the documented contract instead of weakening the FFI logic. The Idris2 ABI (src/interface/abi/Oblibeniser/ABI/Foreign.idr + Types.idr) remains the source of truth: every `C:<name>` symbol still has a matching `export fn`, and the Result enum integer values (Ok=0 .. InverseProofFailed=7) are unchanged and match resultToInt. Verification: - `zig test src/main.zig -lc` -> all 7 tests pass, zero errors/warnings. - `idris2 --build oblibeniser-abi.ipkg` -> exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019xMKB3T4Vo5FYC7Czx3JSH
1 parent 74d25e3 commit 382de76

1 file changed

Lines changed: 17 additions & 3 deletions

File tree

src/interface/ffi/src/main.zig

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ export fn oblibeniser_undo_pop(handle: ?*Handle) u64 {
444444
return 0;
445445
};
446446

447-
const op_id = h.undo_stack.popOrNull() orelse {
447+
const op_id = h.undo_stack.pop() orelse {
448448
setError("Undo stack empty");
449449
return 0;
450450
};
@@ -601,10 +601,24 @@ test "compute and verify inverse" {
601601
const handle = oblibeniser_init() orelse return error.InitFailed;
602602
defer oblibeniser_free(handle);
603603

604-
const op_id = oblibeniser_record_forward(handle, 0, 0);
605-
_ = oblibeniser_finalise_forward(handle, op_id, 0);
604+
// Record with a real pre-state snapshot, then finalise with a real
605+
// post-state snapshot: compute_inverse requires both to be present.
606+
var pre = std.mem.zeroes(StateSnapshot);
607+
pre.state_hash = 0x1111;
608+
var post = std.mem.zeroes(StateSnapshot);
609+
post.state_hash = 0x2222;
610+
611+
const op_id = oblibeniser_record_forward(handle, 0, @intFromPtr(&pre));
612+
try std.testing.expect(op_id != 0);
613+
614+
const finalise = oblibeniser_finalise_forward(handle, op_id, @intFromPtr(&post));
615+
try std.testing.expectEqual(Result.ok, finalise);
616+
606617
const compute = oblibeniser_compute_inverse(handle, op_id);
607618
try std.testing.expectEqual(Result.ok, compute);
619+
620+
const verify = oblibeniser_verify_inverse(handle, op_id);
621+
try std.testing.expectEqual(Result.ok, verify);
608622
}
609623

610624
test "undo stack push and pop" {

0 commit comments

Comments
 (0)