Skip to content

P1: implement missing FFI functions + fix result-code semantics#32

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/new-session-1fphit
Jun 26, 2026
Merged

P1: implement missing FFI functions + fix result-code semantics#32
hyperpolymath merged 1 commit into
mainfrom
claude/new-session-1fphit

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Fixes ABI↔FFI drift in the Zig FFI (src/interface/ffi/src/main.zig), which was generic scaffolding that had diverged from the Idris2 ABI. The Idris2 ABI is the source of truth (src/interface/abi/Typedqliser/ABI/Foreign.idr and .../Types.idr).

Two missing core domain functions implemented

Both were declared in Foreign.idr but absent from the Zig layer. They are now exported callconv(.C) functions whose arities/types match the %foreign declarations exactly (the handle is threaded as a Bits64 pointer value and reconstructed FFI-side):

  • typedqliser_check_query : Bits64 -> String -> Bits32 -> PrimIO Bits32
    (handle_ptr: u64, query: [*:0]const u8, level: u32) -> u32. Validates a query against the registered schema up to the requested safety level, and records the achieved certificate level on the handle.
  • typedqliser_certificate_level : Bits64 -> PrimIO Bits32
    (handle_ptr: u64) -> u32. Returns the highest of the ten cumulative type-safety levels the last checked query achieved (0 if none).

Result-code semantics corrected

The Result enum now matches Typedqliser.ABI.Types.resultToInt exactly:

Ok=0, Error=1, InvalidQuery=2, SchemaError=3, NullPointer=4

The generic scaffold had encoded codes 2 and 3 as invalid_param / out_of_memory — so across the FFI those codes meant the wrong thing versus the ABI. They are renamed to invalid_query (2) and schema_error (3) and all usages updated.

Kept

The pre-existing extra exports (build_info, free_string, get_string, is_initialized, last_error, process, process_array, register_callback) are retained as a harmless superset; init/free/version behaviour is unchanged. Only files under src/interface/ffi/ were touched.

Verification

  • zig test src/interface/ffi/src/main.zig -lcall 8 tests pass (zig 0.14.0). Added tests cover check_query + certificate_level, the malformed-query InvalidQuery path, the SchemaError path, null-handle rejection, and a guard pinning the result codes to resultToInt (2=invalid_query, 3=schema_error).
  • idris2 --build src/interface/abi/typedqliser-abi.ipkgexit 0 (idris2 0.7.0), then build/ removed.

Note: any rust-ci / Hypatia / governance red checks are pre-existing estate-infra issues unrelated to this Zig-only change.

🤖 Generated with Claude Code

https://claude.ai/code/session_019xMKB3T4Vo5FYC7Czx3JSH


Generated by Claude Code

The Zig FFI (src/interface/ffi/src/main.zig) was generic scaffolding that drifted
from the Idris2 ABI, which is the source of truth
(src/interface/abi/Typedqliser/ABI/Foreign.idr and .../Types.idr).

Two core domain functions declared in Foreign.idr were missing from the Zig:

  * typedqliser_check_query  : Bits64 -> String -> Bits32 -> PrimIO Bits32
      (handle pointer, query C-string, requested safety level) -> result code.
      Validates a query against the registered schema up to the requested level
      and records the achieved certificate level on the handle.

  * typedqliser_certificate_level : Bits64 -> PrimIO Bits32
      (handle pointer) -> highest safety level the last checked query achieved
      (0 if none), within the ten cumulative type-safety levels.

Both are now exported `callconv(.C)` functions with arities/types matching the
Idris %foreign declarations exactly (the handle is threaded as a Bits64 pointer
value, reconstructed FFI-side).

Result-code semantics corrected to match Typedqliser.ABI.Types.resultToInt:
  Ok=0, Error=1, InvalidQuery=2, SchemaError=3, NullPointer=4.
The generic scaffold encoded codes 2 and 3 as invalid_param / out_of_memory,
so cross-FFI those codes meant the WRONG thing. They are renamed to
invalid_query (2) and schema_error (3) and all usages updated.

The pre-existing extra exports (build_info, free_string, get_string,
is_initialized, last_error, process, process_array, register_callback) are kept
as a harmless superset; init/free/version are unchanged in behaviour.

Verification:
  * zig test src/interface/ffi/src/main.zig -lc  -> all 8 tests pass
    (added tests exercising check_query + certificate_level, the malformed-query
     InvalidQuery path, the SchemaError path, null-handle rejection, and a
     guard pinning the result codes to resultToInt).
  * idris2 --build src/interface/abi/typedqliser-abi.ipkg  -> exit 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xMKB3T4Vo5FYC7Czx3JSH
@hyperpolymath
hyperpolymath marked this pull request as ready for review June 26, 2026 22:08
@hyperpolymath
hyperpolymath merged commit 4b1839b into main Jun 26, 2026
25 of 27 checks passed
@hyperpolymath
hyperpolymath deleted the claude/new-session-1fphit branch June 26, 2026 22:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants