IC: keep the node bridge out of the nimKochBootstrap build

`koch boot` failed with `bodynav.nim(278) Error: undeclared identifier:
'program'`. `transf` imported `nodebridge` unconditionally, which pulls in
`bodynav`, which resolves names through `ast.program` — and `program` does not
EXIST under `-d:nimKochBootstrap`. That define disables the IC subsystem
wholesale: `ast.nim` guards `program` and the loader callbacks with it, and
`koch.bootic` records that it also disables `commandIc`. The bridge was being
compiled into a build with nothing for it to talk to.

Guarded the same way `ast.nim` already guards `program`. `handOffBody` goes
with it; its only caller is `cgen`, under `-d:newIcBackend`.

`koch temp` cannot catch this — it does not set the define — so the break
survived several rounds of verification that all used it. Predates this
branch's recent work: `transf`'s unconditional import and `bodynav`'s use of
`program` are both there at 8afd306b0.

Also moved `bnode`'s `std / assertions` import inside the `newIcBackend`
branch, the only one that asserts. At module scope it warned "imported and not
used" on every default build, which is how it showed up in the boot output.

Verified: `koch boot -d:release` reaches "executables are equal: SUCCESS!";
both non-bootstrap configurations build; `tests/ic` 40/40; the generated C is
unchanged — 67/67 identical to before this commit, and cursor still identical
to `PNode`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FMyRHByv7hhaQJ4Pa1bHbE
This commit is contained in:
araq
2026-08-30 21:10:49 +02:00
parent 2db27d4826
commit 727d70d2ba
2 changed files with 29 additions and 21 deletions

View File

@@ -243,9 +243,6 @@
import ast, lineinfos, idents
when defined(nimPreviewSlimSystem):
import std / assertions
# ---- opt-in profiling (-d:icBNodeProf) --------------------------------------
# Counts and coarse phase timings; the accessors are far too small to time
# individually. Each backend process appends one line to $NIM_IC_BNODE_PROF (or
@@ -305,6 +302,8 @@ else:
template timed*(s: untyped; body: untyped) = body
when defined(newIcBackend):
when defined(nimPreviewSlimSystem):
import std / assertions # only this branch asserts
import "../dist/nimony/src/lib/nifcore" except pool
import ic / enum2nif
import ast2nif, icnifcore, bodynav

View File

@@ -37,7 +37,15 @@ type
proc transformBody*(g: ModuleGraph; idgen: IdGenerator; prc: PSym; flags: TransformFlags): PNode
import closureiters, lambdalifting
import nodebridge
when not defined(nimKochBootstrap):
# The `PNode` -> `TokenBuf` bridge, and through it `bodynav`, which resolves
# names against `ast.program`. `program` does not EXIST under
# `-d:nimKochBootstrap` — that define disables the whole IC subsystem (see
# `ast.nim` and `koch.bootic`) — so the bridge has to be out of that build
# too, not merely unused by it. `handOffBody` below is guarded for the same
# reason; its only caller is `cgen`, under `-d:newIcBackend`.
import nodebridge
type
PTransCon = ref object # part of TContext; stackable
@@ -1437,23 +1445,24 @@ proc transformBody*(g: ModuleGraph; idgen: IdGenerator; prc: PSym; flags: Transf
#if prc.name.s == "main":
# echo "transformed into ", renderTree(result, {renderIds})
proc handOffBody*(body: PNode; conf: ConfigRef): BridgeBuf =
## THE HANDOFF from the rewriting stage to the reading stage: the transformed
## body, as a `TokenBuf` a reader can cursor over (`nodebridge`).
##
## It lives here because the invariant it carries is this module's: a bridged
## buffer is a SNAPSHOT, so it must be taken after the LAST rewrite the body
## will receive. Anything that mutates a node afterwards — `cgen.easyResultAsgn`
## setting `nfPreventCg` is the one that does — leaves the buffer describing a
## tree that no longer exists.
##
## The call site is in `cgen` rather than at the end of `transformBody` for
## exactly that reason: destructor injection runs *after* `transformBody`
## returns and is another rewrite, so transforming is not the last step and a
## buffer taken here would be stale before it was read. `transformBody` returns
## a `PNode` on purpose; this is the point where a caller that has finished
## rewriting says so.
result = toTokenBuf(body, conf)
when not defined(nimKochBootstrap):
proc handOffBody*(body: PNode; conf: ConfigRef): BridgeBuf =
## THE HANDOFF from the rewriting stage to the reading stage: the transformed
## body, as a `TokenBuf` a reader can cursor over (`nodebridge`).
##
## It lives here because the invariant it carries is this module's: a bridged
## buffer is a SNAPSHOT, so it must be taken after the LAST rewrite the body
## will receive. Anything that mutates a node afterwards — `cgen.easyResultAsgn`
## setting `nfPreventCg` is the one that does — leaves the buffer describing a
## tree that no longer exists.
##
## The call site is in `cgen` rather than at the end of `transformBody` for
## exactly that reason: destructor injection runs *after* `transformBody`
## returns and is another rewrite, so transforming is not the last step and a
## buffer taken here would be stale before it was read. `transformBody` returns
## a `PNode` on purpose; this is the point where a caller that has finished
## rewriting says so.
result = toTokenBuf(body, conf)
proc transformStmt*(g: ModuleGraph; idgen: IdGenerator; module: PSym, n: PNode; flags: TransformFlags = {}): PNode =
if nfTransf in n.flags: