Summary
An embedded na function taking a str parameter falls back to Python cleanly when it is alone, but dies at run time with a ctypes error when it shares an na { } block with functions that take list[int]/dict parameters. The per-function native/fallback decision appears to be poisoned by block-mates.
Repro (crashes)
na {
def shout(s: str) -> str { return s.upper(); }
def total(xs: list[int]) -> int { s = 0; for x in xs { s += x; } return s; }
def pick(d: dict[str, int], k: str) -> int { return d[k]; }
}
with entry { print(shout("hi")); }
→ TypeError: 'str' object cannot be interpreted as ctypes.c_char_p at shout().
Contrast (works)
na def shout(s: str) -> str { return s.upper(); } standalone → falls back cleanly, prints HI.
Analysis
The native calling convention is attempted for shout (a function that should have fallen back to Python), producing a ctypes marshalling crash. The presence of container-taking siblings in the same block changes the per-function lowering/fallback decision. Found on 0.32.0 while verifying book listings.
Summary
An embedded
nafunction taking astrparameter falls back to Python cleanly when it is alone, but dies at run time with actypeserror when it shares anna { }block with functions that takelist[int]/dictparameters. The per-function native/fallback decision appears to be poisoned by block-mates.Repro (crashes)
→
TypeError: 'str' object cannot be interpreted as ctypes.c_char_patshout().Contrast (works)
na def shout(s: str) -> str { return s.upper(); }standalone → falls back cleanly, printsHI.Analysis
The native calling convention is attempted for
shout(a function that should have fallen back to Python), producing a ctypes marshalling crash. The presence of container-taking siblings in the same block changes the per-function lowering/fallback decision. Found on 0.32.0 while verifying book listings.