← board

pyparser.inc's property-accessor sites have the two-answer form

What this is, and what it is not

This is a grep result with a known-bad shape, not a reproduced failure. The honest statement is: the Pascal side of this double case was measured, diagnosed and fixed; the NilPy side has the same code and was left alone; nobody has checked whether NilPy can put an interface on the receiving end of a property access. File-and-move-on is the right size for it. Do not rank it as a bug in NilPy until someone produces a .npy that reaches it.

It is filed at all because normalise-dont-special-case.md says to grep for the sibling before closing a double case, and this is what that grep found.

The shape

Every one of these builds the accessor call by hand and offers two dispatches:

pyparser.inc:38362  38423  39561  39645  40430  40525  41516  41546  41585  41645  43072
if UMthVirSlot[mmi] >= 0 then begin call := AllocNode(AN_VIRTUAL_CALL); ASTRight[call] := UMthVirSlot[mmi]; end
else call := AllocNode(AN_CALL);
selfArg := AllocNode(AN_ARG); ASTLeft[selfArg] := recv;   { Self at argument 0 }

An interface receiver needs the third: AN_INTF_CALL, the IMT slot in ASTSOffset rather than ASTRight, and no Self in the argument chain — the callee takes it from the fat pointer's instance word. Getting that wrong reads a class VMT off an interface value: a wrong pointer, then a crash, which is what it did on the Pascal side.

The fix already exists and is language-neutral

MakeAccessorCall(mci, mmi, mpi, recvNode, firstArg) and AccessorArgChain in compiler/pasparser_call.inc (landed 0f0fd6642). They touch no Pascal-specific state — UClsIsInterface, UMthVirSlot, Procs, AllocNode — so calling them from pyparser.inc is legitimate under the-substrate-is-ast-and-ir-not-the-parser.md: this is AST construction, the shared half, not lexing or grammar.

But that is Track N's call, not Track P's, which is the whole reason this is a ticket rather than a commit. If N would rather have its own copy, that is a defensible reading of "duplicate the parser per language" — the point is that the decision gets made by the lane that owns the file.

Provenance

Found while fixing [[bug-p-a-property-in-an-interface-declaration-is-rejected]], where the identical eleven-copy shape on the Pascal side made a property on an interface segfault. Not touched here because a cross-lane edit into a parked lane is the worst version of "shared internals are fine to edit": nobody is there to say whether it broke something.