Add examples/1223-ffi-extern-fn.sx — binds libc 'abs' via bare 'extern'
(sx name = C symbol, no rename). Hand-authored expected/ captures the
SUCCESS output (abs(-7)=7 / abs(42)=42, exit 0).
RED: 1223 is the sole corpus failure (634 ran, 1 failed) — it parses
then errors at sema ('body produces no value') because lowering does
not yet route extern fns through declareExtern. Phase 1.1 wires the
lowering and turns this green.
xfail commit per the cadence rule (no commit both adds a test and makes
it pass).
3.8 KiB
sx extern/export + #foreign retirement — Checkpoint (FFI-linkage stream)
Companion to current/PLAN-EXTERN-EXPORT.md — one merged plan: Part A adds
extern/export, Part B migrates #foreign and purges foreign. Update after
every commit, one step at a time per the cadence rule.
Last completed step
Phase 1.0b (xfail — example half of 1.0) — added examples/1223-ffi-extern-fn.sx
(extern-binds libc abs via bare extern; sx name = C symbol, no rename) +
hand-authored expected/ capturing the SUCCESS output (abs(-7) = 7 / abs(42) = 42, exit 0). RED: 1223 is the only corpus failure (634 ran, 1 failed) — it parses
then errors at sema (body produces no value) because lowering doesn't route extern
yet. Phase 1.1 turns it green. (Prior: 1.0a (lock, green) wired fn-path extern
parsing — parseFnDecl → parseOptionalExternExport() → FnDecl.extern_export,
; body = empty-block placeholder; both lookahead predicates accept
kw_extern/kw_export; per user feedback added FnDecl.extern_lib/extern_name +
VarDecl.extern_lib, decision 4 REVISED.)
Current state
Syntax: bare extern/export, postfix after callconv(.c), extern ⇒ callconv(.c).
Decision 4 revised (user 2026-06-14): extern carries an optional LIB+"csym"
axis (extern_lib/extern_name) like #foreign; the #library decl + build-flag
linking stays separate. Touch-points: token token.zig:45,282; parser
1950,3669,316,425,1305; lowering decl.zig:1123,387,2110,2382,2514; IR/emit already
capable (no codegen change). Part B foreign footprint to purge: 643 lines / ~57
identifiers in src/ + 28 doc lines. End-state invariant: zero foreign (Phase
9.4 gate). Done: tokens (0.0) + AST/parser plumbing (0.1) + fn-path extern parsing
- lib/name fields (1.0a), all unconsumed. Lowering not yet wired.
Next step
Phase 1.1 (green, turns 1223 green) — in decl.zig, when
fn_decl.extern_export == .extern_, route the fn through declareExtern (is_extern,
.external linkage, callconv(.c), no implicit ctx — anchors decl.zig:1123,387, 2110,2113) instead of lowering the empty-block placeholder body. Treat the bare
extern (no extern_lib/extern_name yet) like a lib-less #foreign import — the
sx name IS the C symbol, resolves against the default-linked libc. Run, then
-Dupdate-goldens to finalize 1223's snapshot byte-exact; review diff. Then 1.2
(green): consume extern LIB "csym" rename (extern_lib/extern_name) + extern-global
g : T extern; (parser.zig:425). Stop at end of Phase 1.
Open decisions
Part A ratified (bare / postfix / ⇒ callconv(.c) / lib-separate). Part B (confirm
before Phase 9): runtime-class rename target — Runtime*Class* (recommended);
historical carve-out — keep issues/*.md provenance, gate the live tree only.
Log
- (init) Plan written; FFI-linkage stream opened.
- (merge) Folded FOREIGN-MIGRATION in as Part B; deleted the split plan + checkpoint.
- (0.0) Added
kw_extern/kw_exporttokens + keyword-map entries + LSP keyword classification +lex linkage keywordstest. Suite green; no identifier collisions in the corpus.lockcommit. - (0.1) Added
ast.ExternExportModifier+FnDecl.extern_export+VarDecl.is_extern/extern_name+parseOptionalExternExport()(unconsumed) + 2 parser unit tests. Suite green (443/633).lockcommit. - (1.0a) Wired fn-path extern parsing (
parseFnDecl+ both lookahead predicates) + addedFnDecl.extern_lib/extern_name+VarDecl.extern_libper user feedback (decision 4 revised: extern carries an optional lib axis). Unconsumed by lowering. Suite green (443/633).lockcommit. - (1.0b) Added
examples/1223-ffi-extern-fn.sx+ hand-authored success snapshots. RED (634 ran, 1 failed — semabody produces no value).xfailcommit; 1.1 greens it.
Known issues
None yet.