Skip to content

feat(c): full-tier adapter implementation (M9 2/3)#402

Merged
Mathews-Tom merged 3 commits into
mainfrom
feat/m9-c-adapter
Jul 4, 2026
Merged

feat(c): full-tier adapter implementation (M9 2/3)#402
Mathews-Tom merged 3 commits into
mainfrom
feat/m9-c-adapter

Conversation

@Mathews-Tom

@Mathews-Tom Mathews-Tom commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Stack

Stack-Id: m9-c-full-tier-20260704
Base: main
Position: 2/3

  1. feat/m9-c-fixtures -> test(c): grammar evaluation and fixture scaffold (M9 1/3) #401
  2. feat/m9-c-adapter -> this PR
  3. feat/m9-c-full-tier -> next

Depends on: #401
Upstack: (next PR, not yet open)

Summary

M9 (DEVELOPMENT_PLAN.md Section D) PR 2/3: src/archex/parse/adapters/c.py
implementing the full LanguageAdapter contract, plus its test suite. No
tier-flip or registry wiring yet -- that's PR 3/3.

  • extract_symbols: function definitions and bodyless prototype
    declarations (both -> FUNCTION -- a .h file's public API is almost
    entirely prototypes) and struct definitions -- bare, typedef-anonymous, and
    typedef-named (-> TYPE, preferring the typedef alias over the bare tag
    name). Both recurse through preprocessor conditionals
    (#ifdef/#if/#elif/#else) and extern "C" linkage blocks, since C
    nests declarations inside those wrapper nodes rather than flattening them
    to top-level translation_unit siblings -- a naive one-level scan would
    miss most real .h file content.
  • parse_imports: both #include forms (quoted, angle-bracket) through the
    same recursive walk.
  • resolve_import: angle-bracket includes are always external; quoted
    includes resolve relative to the including file first, falling back to a
    basename match anywhere in the project (no build-system -I search-path
    visibility).
  • detect_entry_points: a main function definition (not prototype) in a
    .c file.
  • classify_visibility: AST-derived from the static storage class
    (internal vs. external linkage) -- a real C semantic, not name-derived
    like Go's uppercase convention, so the value set during extraction is
    trusted rather than recomputed.

Validation

  • uv run pytest tests/parse/adapters/test_c.py -v: 39 passed
  • uv run pytest: 3141 passed, 4 deselected, 91.03% coverage (was 3102
    pre-M9)
  • uv run ruff check . / uv run ruff format --check .: clean
  • uv run pyright: 0 errors, 0 warnings, 0 informations
  • Adapter is not yet registered/wired (tier flip lands in PR 3/3), so no
    behavioral change from this PR alone -- verified by the full-suite pass
    above.

Adds src/archex/parse/adapters/c.py implementing the full LanguageAdapter
contract (extract_symbols, parse_imports, resolve_import,
detect_entry_points, classify_visibility -- the class must satisfy the
full protocol to be instantiable, no stub methods).

extract_symbols walks both function definitions and bodyless function
prototype declarations (-> SymbolKind.FUNCTION, sharing one
declarator-unwrapping helper so a header's prototype-only API surface
is not silently skipped) and struct definitions -- bare, typedef
anonymous, and typedef named (-> SymbolKind.TYPE, preferring the
typedef alias over the bare tag name; forward declarations and bare
type references are excluded since they carry no member information).
Both extractions recurse through preprocessor conditionals
(#ifdef/#if/#elif/#else) and extern "C" linkage blocks, since C nests
declarations inside those wrapper nodes rather than flattening them to
top-level siblings -- a naive one-level scan would miss most real .h
file content. Visibility is AST-derived from the static storage class
(internal vs external linkage), not name-derived like Go's uppercase
convention.

parse_imports extracts both #include forms (quoted and angle-bracket)
through the same recursive walk. resolve_import treats angle-bracket
includes as always-external and resolves quoted includes relative to
the including file first, falling back to a basename match anywhere in
the project (the adapter has no build-system -I search-path
visibility). detect_entry_points looks for a main() function
*definition* (not a prototype) in .c files only.

Tests land in the next two commits, following the same split the M8
Scala stack used: symbol/import extraction first, then the remaining
three contract methods.

Stack-Id: m9-c-full-tier-20260704
Stack-Position: 2/3
Covers extract_symbols (function definitions and prototypes, static
visibility, pointer-returning functions, signature slicing that
excludes the body/semicolon; bare/typedef-anonymous/typedef-named
structs, forward-declaration and self-referential-field exclusion,
the K&R combined struct-plus-variable form; recursion through
preprocessor conditionals and extern "C" blocks with independently
correct sibling boundaries) and parse_imports (quoted vs. angle-bracket
forms, recursion through extern "C", ordering) against the
c_simple fixtures plus targeted inline-source edge cases.

resolve_import/detect_entry_points/classify_visibility tests land in
the next commit.

Stack-Id: m9-c-full-tier-20260704
Stack-Position: 2/3
Completes test coverage for the three remaining CAdapter contract
methods (already implemented in the first commit, since the class must
satisfy the full LanguageAdapter contract to be instantiable).

resolve_import: same-directory and cross-directory relative resolution
for quoted includes, the basename-anywhere-in-project fallback (proven
load-bearing when a header lives on a compiler -I search path rather
than beside the includer), the unresolvable case, and angle-bracket
includes always returning None even against a coincidentally matching
file_map entry.

detect_entry_points: a real main() definition in a .c file, a main()
-shaped definition in a .h file (excluded -- headers are never entry
points), a bodyless main() prototype (excluded -- not a definition),
and a non-main file.

classify_visibility: both Visibility values pass through unchanged.

Test count: 28 -> 39.

Stack-Id: m9-c-full-tier-20260704
Stack-Position: 2/3
@Mathews-Tom Mathews-Tom changed the base branch from feat/m9-c-fixtures to main July 4, 2026 19:43
@Mathews-Tom Mathews-Tom merged commit c16e290 into main Jul 4, 2026
6 checks passed
@Mathews-Tom Mathews-Tom deleted the feat/m9-c-adapter branch July 4, 2026 19:50
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.

1 participant