feat(ffi-linkage)!: Phase 8.1 — parser hard-rejects #foreign (cutover)

The prefix #foreign linkage directive is removed. All four parse sites
(const-with-type, data global, fn body, runtime-class prefix) now reject it with
a migration message ('#foreign has been removed; use the postfix extern (import) /
export (define) linkage keyword instead'); added a span-aware failAt for the
runtime-class case (the lookahead consumes the token before the reject decision).
Greens the Phase 8.0 xfail 1176.

- Deleted obsolete tests: 1174 (#foreign+postfix conflict — unreachable now that
  #foreign alone is rejected) and 1620 (#foreign nosuchunit lib-ref — superseded by
  the extern twin 1231). Their assertions tested #foreign-specific behavior.
- Removed the GATE A→B unit test + lowerSrcToIr helper (lower.test.zig): it locked
  #foreign ≡ extern through the migration; with #foreign gone there is nothing to
  compare. Converted the in-source 'parse void function with foreign body' parser
  test to the surviving postfix 'extern' spelling (identical resulting AST).
- specs.md + readme.md drop #foreign; document extern/export as the sole C-linkage
  surface.

extern_export in parseFnDecl is now const (the fn-body arm that mutated it is gone).
Suite green (646 corpus / 444 unit, 0 failed). NOTE: comment-only #foreign in
examples + issues/*.md prose + internal foreign_* identifiers remain for Phase 9
(now unblocked: Decision 6 = purge everything).
This commit is contained in:
agra
2026-06-15 08:06:05 +03:00
parent 8180faf839
commit 3811311e12
12 changed files with 69 additions and 340 deletions

View File

@@ -29,7 +29,7 @@ main :: () {
- First-class closures with value capture
- Protocol-based polymorphism (traits)
- Pattern matching on enums, optionals, and type categories
- C interop via `#foreign` and `#import c`
- C interop via `extern` / `export` and `#import c`
- Targets: macOS (ARM64, x86_64), Linux (x86_64, ARM64), Windows (x86_64), WebAssembly
## Building
@@ -402,20 +402,20 @@ FIBONACCI_10 :: #run fib(10);
### C Interop
Foreign functions:
C linkage:
```sx
libc :: #library "c";
printf :: (fmt: [:0]u8, args: ..Any) -> i32 #foreign libc;
write_fd :: (fd: i32, buf: [*]u8, count: u64) -> i64 #foreign libc "write";
printf :: (fmt: [:0]u8, args: ..Any) -> i32 extern libc;
write_fd :: (fd: i32, buf: [*]u8, count: u64) -> i64 extern libc "write";
```
`extern` / `export` are the keyword surface for C linkage. `extern` is the modern
spelling of `#foreign` (import); `export` is its dual — define a function in sx and
`extern` / `export` are the keyword surface for C linkage. `extern` imports a
symbol defined elsewhere; `export` is its dual — define a function in sx and
expose it under the C ABI so C can call back in. Both imply `callconv(.c)` and take
the same optional `[LIB] ["csym"]` rename tail; they also apply to data globals and
to Obj-C / JNI runtime-class aggregates (postfix after the `#objc_class(…)` directive).
```sx
abs :: (x: i32) -> i32 extern; // import (== `#foreign`)
abs :: (x: i32) -> i32 extern; // import an external C symbol
sx_square :: (x: i32) -> i32 export { x * x } // define + expose to C
__stdinp : *void extern; // extern data global
NSObject :: #objc_class("NSObject") extern { alloc :: () -> *NSObject; } // reference a runtime class