language: design record for foreign functions (step 1 of #84) #459
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Step 1 of #84 (language: the design of foreign functions; COMPUTE.md section 2, ROADMAP "Computation and machine learning", CONCEPT "Foreign Functions (Draft)").
foreignis parsed and its block shape is checked (checkForeignShape,compiler/src/semantics/checker/declaration.trb), the package summary already reports it as the capability "foreign functions" (compiler/src/package/archive.trb), and the sandbox never grants it (docs/language/configuration/the-sandbox.md, rule 8). But nothing links or calls a foreign function,Pointer<Value>andCStringare declared nowhere instd/, and no design record exists: CONCEPT is a draft with eight bullets,docs/language/extensibility/foreign-functions.mdrepeats them as "planned", andstd/gpu(COMPUTE.md section 2: "then the design of foreign functions; thenstd/gpu") waits for it. This step is documentation only.Goal
A design record
docs/design/FOREIGN.mdthat specifies foreign functions end to end (types, ABI mapping, how each back end calls, library resolution, ownership, callbacks, errors) and cuts the build into slices, each one PR. The one question the record cannot answer itself, whether a published package may declareforeignfunctions and carry C sources, is an owner decision tracked in #84; the record states the options and leaves that section marked open.Acceptance criteria
docs/design/FOREIGN.mdexists, headed and indexed like the other records (status line "designed, not built", an entry indocs/design/index.md); CONCEPT "Foreign Functions (Draft)",docs/language/extensibility/foreign-functions.md, COMPUTE.md (layer 0 and section 2), RELEASE.md section 2 and FIRST-PARTY.md row 7 link it;docs/regeneratesskills/(torb docs skill docs skills, a tier A gate).Bool,Pointer<Value>,CString,foreign type(C layout: field order, alignment, padding, no generics), and what is refused (String,Intwithout a size, closures other than the callback form, generics). Says in whichstdpackagePointerandCStringare declared, who may construct and dereference a pointer, how aStringbecomes aCString(copy, NUL check, lifetime of the call) and how aBuffer<Item>window is handed to C for the duration of one call. Each is a numbered decision with its reason.dlopen/LoadLibraryW, the patternruntime/os/windows.candruntime/platform.calready use) against link-time linking (CONCEPT's "the compiler links directly"), and, for the VM's "generic trampoline", an in-tree call stub per ABI (SysV x86-64, Win64, AAPCS64) against libffi against generating a C stub per signature. Decides one, with the number of supported tier 1 targets, the dependency and licence cost (RELEASE.md section 7.11: no large C files in every build), and what happens on a signature the stub cannot express. A back end that cannot call a signature reports a compile error that names it (BACKEND gap 22), never a link error.foreign "name"and of the per-platform file names (library "sqlite3", windows: ..., linux: ..., macos: ...), where the mapping lives and what happens when the library is missing at start or at first call. Resolves the conflict between CONCEPT ("a package that containsforeigndeclarations says so inproject.trb") and PROJECT.md section 1 ("nativeandforeign... a manifest switch would be a second source of truth"): decided here, with the working assumption that the capability is derived from source asarchive.trbdoes today andproject.trbcarries only the name-to-file mapping; the record may change that with a reason.torb addand the lock, never granted bySandbox, SCRIPTS.md table); fixes the stale rule number in OS.md section 8 ("the-sandbox.md, rule 7" is rule 8) if it is still wrong; says what--embed-vmbinaries andtorb testdo with a foreign library.shared typewithClose, DESTRUCTORS.md), what a pointer's lifetime means across aTaskboundary (CONCURRENCY.md), the capture-free closure as function pointer (how it is lowered and kept alive),errno/GetLastErrorand a null result asResult, and a panic or a signal inside C. Platform arms (match OperatingSystem.current, OS.md) and which declarations are emitted per target.std/gpuandstd/renderneed from the record (Layer 0 of COMPUTE.md): struct by value, out-parameters, function-pointer tables, pinned buffer windows, library loading at run time; stated as constraints, without designing those packages.Pointer/CStringinstd; thelibraryblock andforeign typein parser and checker; the call in the VM; the call in the C back end; conformance tests against a tiny C test library built in CI), each one PR of one or two Conventional Commits, each with its seed impact under the two-commit rule (new syntax: teach both forms, refresh the seed, then use it; the seed refresh itself stays with the owner). A slice is filed as its own issue only when it starts.torb/sqlite(FIRST-PARTY.md row 7), the registry andtorb publish, and is marked "open, owner decision (#84)". It carries no decision; a follow-up PR writes the answer into it, into RELEASE.md section 2 and into FIRST-PARTY.md.Design record point
CONCEPT "Foreign Functions (Draft)" and "Capabilities are visible"; COMPUTE.md sections 1 (layer 0) and 2; NATIVE-BODIES.md (the other half of the
native/foreignsplit); RELEASE.md sections 2, 7.8 and 7.11; PROJECT.md section 1 (what does not belong in a project file); SCRIPTS.md (capability table); VM.md section 6; BACKEND gap 22; DESTRUCTORS.md; JAVASCRIPT-AND-PHP.md (the JS boundary offoreign); OS.md (platform arms).Seed impact
None for this step (documentation only; no
std/,runtime/orcompiler/file changes). The later slices add syntax and names the compiler looks up, so each states its seed impact under the two-commit rule.Size
One PR, one Conventional Commit (
docs(language): design record for foreign functions).Out of scope
Any change to
std/,runtime/orcompiler/; the decision onforeignin published packages (#84);std/gpuitself (#85); the seed.Dependencies
None hard. Verified against
mainatc4a8443: no open or closed issue covers foreign functions besides #84;docs/design/NATIVE-BODIES.mdis already onmain(it is referenced, not a prerequisite). Part of #84; blocks #85.[loop:torbscript] claim implement by session:loop-torbscript-20261024 until 2026-10-24T04:24:35Z
[loop:torbscript] implement: checkpoint (context guard), no PR yet, nothing committed.
torbscript-language-459-foreign-design-recordon branchloop/459-foreign-design-record(from maind5227eec, not pushed). Research read so far: COMPUTE.md, NATIVE-BODIES.md, CONCEPT "Foreign Functions (Draft)", docs/language/extensibility/foreign-functions.md,checkForeignShapeandarchive.trb(capability "foreign functions" derived from source), VM.md section 6 (the VM reaches C only through the kernel natives and a table of thunks generated from the manifest, so a foreign call needs one more kernel operation) and 10, BACKEND 3.7 / gap 22, dlopen-style loaders inruntime/platform.candruntime/os/windows.c(onlyLoadLibraryW/GetProcAddressso far, no POSIXdlopenyet).docs/is excluded from pdisc (.pdisc.yaml), so docs/design/*.md carry no frontmatter and need no stamp (still runpdisc.py check); design records areskill: omit, so a link to FOREIGN.md fromdocs/language/extensibility/foreign-functions.mdkeeps only its text inskills/(hand-mirror the edit there, the copy differs only by one trailing blank line; add the record tosource:in both). Entry indocs/design/index.mdgoes in thedocuments:list and in the generated block. Precedent commit:798f20d9(NATIVE-BODIES).docs/design/FOREIGN.md.Closes, #84 stays open), comment, remove the worktree.[loop:torbscript] implement: checkpoint 2 (context guard), no PR yet.
docs/design/FOREIGN.mdwritten and committed locally (branchloop/459-foreign-design-record, worktreetorbscript-language-459-foreign-design-record, NOT pushed). 11 sections: decisions, what exists, types/ABI, declarations + run-time loading in both back ends, checker rules F1-F7, sandbox/registry (yes to declaring, no to carrying C), C back end vs VMForeignCallkernel op (stubs, spike gate vs libffi), memory/callbacks, non-goals, 8 slices, open points.docs/tooling/package-capabilities.md, section numbers of VM/OS/CONCURRENCY/DESTRUCTORS, "BACKEND 5.4"); (2) links to FOREIGN.md from CONCEPT.md (Foreign Functions section; also change "the compiler links directly" to the run-time loading of FOREIGN.md 4.2),docs/language/extensibility/foreign-functions.md(+ add tosource:) and itsskills/copy by hand (design records areskill: omit), COMPUTE.md (lines 20 and 49), RELEASE.md section 2 (row 108) + 7.2 line 942, FIRST-PARTY.md row 7 (line 171) and row 9 (line 324),docs/design/index.md(thedocuments:list and the generated block near line 120, precedent798f20d9); (3) OS.md line 1581 "rule 7" -> "rule 8"; (4)python pdisc.py check; (5) commit, push, open PR referencing #459 (no Closes, #84 stays open); (6) finalnext: reviewcomment on #459; (7) remove worktree.~/.secrets/torbdev-token(forgejo-token is for git.dmb.zone).[loop:torbscript] claim implement by session:loop-torbscript-20261024 until 2026-10-24T04:29:27Z
orion referenced this issue2026-10-24 02:31:11 +00:00
[loop:torbscript] implement: design record docs/design/FOREIGN.md plus cross-links (CONCEPT, language page + skills copy, COMPUTE, RELEASE, FIRST-PARTY, design index), OS.md rule 7->8 fix, pdisc clean; PR #460 (docs only, CI is the gate), next: review