← board

What it does, measured 2026-09-11 at compiler 848d67a6757a

$ printf 'import string\nprint(1)\n' > /tmp/st.npy
$ pascal26 /tmp/st.npy /tmp/st
note: string -> mimic_string (shim, subset)
ok: ...
$ pascal26 --no-shims /tmp/st.npy /tmp/st
pascal26:1: error: import: no unit named string (--no-shims refuses the mimic_ substitution)

/usr/include/string.h and /usr/include/sqlite3.h are both present.

Why it matters, and how it was found

import sqlite3 resolved to /usr/include/sqlite3.h through the ordinary unit resolver and linked libsqlite3 directly. compiler/pyparser.inc uses that as its own worked example of a C header being imported, and test/test_nilpy_import_sqlite.npy pins it by calling sqlite3_libversion_number().

Landing lib/rtl/mimic_sqlite3.pas made the shim win, and that test went RED — correctly, and the capability was gone in BOTH spellings: with shims the mimic answers, without them the import is refused. Worked around in the shim by EXPORTING the C entry points it binds, which restores the pinned test and is allowed by Track N's rule (CPython has no sqlite3_step, so a program using it is one CPython rejects). That workaround does not generalise: it covers the entry points one shim happens to need, not sqlite3.h.

The fork, stated as what we want rather than as a mechanism

Does --no-shims mean "do not substitute" — resolve the name the way the compiler would if no mimic_ unit existed — or "refuse anything a shim would have answered"?

The first reading is what the flag's own message says it does ("refuses the mimic_ substitution") and is what makes it useful for the purpose it was added for: finding out what a program really needs. The second is what it implements. Nobody chose the second; it is what falling out of the resolver early does.

Not taken because it is not obviously narrow

The change is one arm in the import resolver, but it widens what --no-shims ACCEPTS, and the existing --no-shims rows in the suite were written against today's behaviour. Whoever takes it should check those rows first: a test asserting that --no-shims refuses a name that also has a header would go from green to red for a reason that is the fix working.

Positive control

import sqlite3 under --no-shims, asserting it COMPILES and that sqlite3_libversion_number() answers — the header route, reached with the shim present but disabled. And the negative: a shimmed name with NO other resolution (import queue) must still be refused, or the flag has stopped meaning anything.


2026-09-11, frankB — fixed. The first reading, which is the one the message already claimed

Compiler 786b88673e62. --no-shims now resolves a shimmed name as if the mimic_ unit were absent: the two conditions that guarded the host-header probe in compiler/pasparser_proc.inc gained NoShims or (not PyMimicShimExists(...)) where they previously required the shim to be missing. The flag's refusal message is unchanged in spirit and sharper in wording — no unit named X (--no-shims refuses the mimic_ substitution, and nothing else of that name resolved) — so a refusal now says which of the two things happened.

The shim EXPORT workaround this ticket describes is reverted. It restored one test and not the other, and the reason it could not is worth keeping: sqlite3_open's NilPy spelling returns the handle, where the C function returns a status and writes the handle through an out-parameter. Out-param return lifting is a frontend TRANSFORMATION applied to a C declaration, not a name that can be re-exported from a Pascal unit — so exporting sqlite3_open from the shim gives a program the symbol and the wrong shape, and test_nilpy_sqlite_crud.npy stayed red while test_nilpy_import_sqlite.npy went green. Two tests, one workaround, and the half that passed is the half that only needed a name. The bindings are private again in mimic_sqlite3.pas.

Both pinned tests now compile with --no-shims in the Makefile, with a header note in each .npy saying that the flag is load-bearing and why — a reader who drops it gets the DB-API module, which is what a Python program means by import sqlite3 and is correct.

pasparser_proc.inc's host-header probe comment predicted this collision by name, in advance, and said the shim should win. It was right about the precedence; the missing piece was the door out of it. Comment updated in place to record that its own example came true on 2026-09-11.

Positive control as specified: import sqlite3 under --no-shims compiles and sqlite3_libversion_number() answers a well-formed 3.x.y. Negative control: --no-shims on a shimmed name with no other resolution is still refused, and the suite already had TWO rows asserting it, both green — the .py shim row (FAIL: --no-shims accepted a mimic_ .py shim) and the dotted-import row, which additionally greps the log for no-shims so it cannot pass on some other refusal.

Log