Skip to content

refactor(codegen): shared FFIType IR + single type parser for C/C++/Rust#104

Merged
gmelodie merged 2 commits into
masterfrom
chore/shared-codegen-utils
Jul 6, 2026
Merged

refactor(codegen): shared FFIType IR + single type parser for C/C++/Rust#104
gmelodie merged 2 commits into
masterfrom
chore/shared-codegen-utils

Conversation

@gmelodie

@gmelodie gmelodie commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

The three FFI codegen backends each carried their own ad-hoc parser for the Nim type strings in the metadata registry (FFIFieldMeta.typeName, e.g. "seq[Option[int]]"): C recursed via genericInnerType + startsWith("seq["), C++ via genericInnerType, and Rust via hand-rolled t[4 .. ^2] slicing. Three copies of the same leaf-scalar table, three places to fix any new shape — and they had already drifted: nimTypeToRust was missing the int8/int16/uint8/uint16/uint32/byte/float32 cases that C and C++ handle, so those types silently fell through to capitalizeFirstLetter(t) and emitted invalid Rust.

This introduces one structured type model and one parser that all three backends consume.

  • New ffi/codegen/types_ir.nim: a recursive FFIType descriptor (ScalarKind + FFITypeKind), the single parseFFIType parser, and a generic renderNative walker driven by a small per-language NativeTypeMap. genericInnerType moves here as a private parser helper (removed from c_cpp_common.nim).
  • cpp.nim / rust.nim: nimTypeToCpp / nimTypeToRust are now renderNative(map, parseFFIType(t)). Public signatures unchanged, so callers are untouched. This fixes the Rust scalar drift by construction (the scalar set now lives in exactly one place).
  • c.nim: ensureCType switches on FFIType.kind instead of string prefixes; the leaf scalar table is expressed once as scalarCInfoTable keyed by ScalarKind, and leafSuffix/cToken derive from it. Monomorphisation and codec-body emission (emitSeqType/emitOptType/emitStructType) are unchanged — only their input becomes the shared IR.

Codec-body emission and the high-level ctor/method/event wrappers are deliberately left per-backend (they genuinely diverge: Result<T> vs std::future vs flume, unique_ptr vs RAII vs Drop); a later phase could revisit them behind a backend vtable. ftHandle is parsed for completeness but no production caller passes a handleNames set (handles are pre-converted to pointer upstream), so that arm is currently exercised only by the unit tests.

Verification

  • New tests/unit/test_rust_codegen.nim pins the drift fix directly: nimTypeToRust over the full scalar set (including the previously-broken int8/int16/uint8/uint16/uint32/byte/float32), seq[byte]Vec<u8>, ptr T/pointer, nested generics, Maybe == Option, and struct capitalisation.
  • New tests/unit/test_types_ir.nim covers parseFFIType directly: the full scalar set, seq[byte]/seq[uint8]ftBytes, nested seq[Option[seq[int]]], Maybe[T] == Option[T], handle names → ftHandle, ptr T/pointerftPtr, unknown name → ftStruct, plus renderNative round-trips.
  • Golden regen + diff: regenerated the committed example bindings; the C and C++ outputs for examples/echo and examples/timer are byte-identical to what is on disk, and the Rust output is identical (the examples don't use any of the previously-broken scalar types, so the drift fix changes no checked-in output).
  • All codegen unit tests pass under both --mm:orc and --mm:refc (test_types_ir, test_rust_codegen, test_c_codegen, test_cddl_codegen, test_string_helpers, test_meta).

@gmelodie
gmelodie marked this pull request as ready for review June 29, 2026 20:09
Base automatically changed from feat/c-codegen to master July 1, 2026 15:00
@gmelodie
gmelodie requested review from Ivansete-status and removed request for Ivansete-status July 1, 2026 19:02
@gmelodie
gmelodie marked this pull request as draft July 1, 2026 19:03
@gmelodie
gmelodie force-pushed the chore/shared-codegen-utils branch 7 times, most recently from 47804a5 to 7f858c6 Compare July 3, 2026 19:11
@gmelodie
gmelodie marked this pull request as ready for review July 3, 2026 19:11
@gmelodie
gmelodie requested a review from Ivansete-status July 3, 2026 19:11

@Ivansete-status Ivansete-status left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Great simplification indeed! 🙌

Comment thread ffi/codegen/types_ir.nim Outdated
Comment thread ffi/codegen/types_ir.nim Outdated
Comment thread ffi/codegen/types_ir.nim Outdated
Comment thread ffi/codegen/types_ir.nim
Comment thread ffi/codegen/types_ir.nim Outdated
Comment thread ffi/codegen/c.nim
Comment thread ffi/codegen/c.nim Outdated
@gmelodie
gmelodie force-pushed the chore/shared-codegen-utils branch from 7f858c6 to 59e9f1f Compare July 6, 2026 13:58
@gmelodie
gmelodie merged commit 8c1343a into master Jul 6, 2026
109 checks passed
@gmelodie
gmelodie deleted the chore/shared-codegen-utils branch July 6, 2026 14:43
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