feat(c): full-tier adapter implementation (M9 2/3)#402
Merged
Conversation
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
cd8ac2c to
1de7101
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack
Stack-Id:
m9-c-full-tier-20260704Base:
mainPosition: 2/3
feat/m9-c-fixtures-> test(c): grammar evaluation and fixture scaffold (M9 1/3) #401feat/m9-c-adapter-> this PRfeat/m9-c-full-tier-> nextDepends on: #401
Upstack: (next PR, not yet open)
Summary
M9 (DEVELOPMENT_PLAN.md Section D) PR 2/3:
src/archex/parse/adapters/c.pyimplementing the full
LanguageAdaptercontract, plus its test suite. Notier-flip or registry wiring yet -- that's PR 3/3.
extract_symbols: function definitions and bodyless prototypedeclarations (both ->
FUNCTION-- a.hfile's public API is almostentirely prototypes) and struct definitions -- bare, typedef-anonymous, and
typedef-named (->
TYPE, preferring the typedef alias over the bare tagname). Both recurse through preprocessor conditionals
(
#ifdef/#if/#elif/#else) andextern "C"linkage blocks, since Cnests declarations inside those wrapper nodes rather than flattening them
to top-level
translation_unitsiblings -- a naive one-level scan wouldmiss most real
.hfile content.parse_imports: both#includeforms (quoted, angle-bracket) through thesame recursive walk.
resolve_import: angle-bracket includes are always external; quotedincludes resolve relative to the including file first, falling back to a
basename match anywhere in the project (no build-system
-Isearch-pathvisibility).
detect_entry_points: amainfunction definition (not prototype) in a.cfile.classify_visibility: AST-derived from thestaticstorage 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 passeduv run pytest: 3141 passed, 4 deselected, 91.03% coverage (was 3102pre-M9)
uv run ruff check ./uv run ruff format --check .: cleanuv run pyright: 0 errors, 0 warnings, 0 informationsbehavioral change from this PR alone -- verified by the full-suite pass
above.