Indexed / element proc-value call: arr[i](args)
- Type: feature (Track A — parser + element proc-sig tracking)
- Track: A —
compiler/** - Status: done
- Owner: Track A
- Closed: 2026-06-25
- Opened: 2026-06-25
- Split-from: [[bug-proc-typed-call-const-record-arg]] (its array-element symptom; the scalar/const-record half is fixed).
- Found-by: [[feature-demo-chess]] —
Evaluatecalls eval terms through a procedural-typed tableEvalTerms[i](pos).
Symptom
Calling a proc-typed value held in an ARRAY ELEMENT is not parsed as an indirect call at all:
type TFn = function(x: Integer): Integer;
function Dbl(x: Integer): Integer; begin Dbl := x*2; end;
var arr: array[0..0] of TFn;
begin arr[0] := @Dbl; writeln(arr[0](21)); end. { error: unexpected token () }
A scalar proc var (fn(args)) and a record FIELD proc value (rec.fn(args),
via UFldProcSig) both work; only the array-element form is missing.
Why
ParseProcVarCallAST and its callers only special-case a simple identifier
callee (fires when ( immediately follows the name). For arr[i] the callee is
an AN_INDEX, and the array's element proc signature is not tracked (there is
SymProcSig for a var and UFldProcSig for a field, but no element equivalent),
so the postfix (args) after an indexed proc value has nowhere to bind. arr[0]
yields the pointer and the (...) is dropped / mis-parsed.
Fix sketch
- Record an element proc signature for
array of <proctype>— a newSymElemProcSig(mirroringUFldProcSig), captured fromLastTypeProcSigat the array declaration. NB: every symtabAlloc*must reset it to -1 (the parallel-array landmine), and that reseeds once. - In the ParseFactor postfix loop, after building an
AN_INDEXwhose base array has an element proc sig and(follows, buildAN_CALL_IND(mirror the field path at parser.inc ~1882), method-pointer flag when the element isof object.
Done when
arr[i](args)(andEvalTerms[i](pos)with aconst recordparam) compiles and calls correctly; the chess eval no longer saturates to ±INF.- Regression test under
make test; self-host fixedpoint byte-identical.
Resolution (2026-06-25)
- New
SymElemProcSigparallel array (defs.inc) tracks an array's ELEMENT proc signature; reset to -1 at all four symtabAlloc*sites (parallel-array landmine). Captured inParseVarSectionfromLastTypeProcSigafter the elementParseTypeKind(plain proc => tyPointer, method ptr => tyRecord). ParseFactorpostfix loop: after building anAN_INDEXwhose base is anAN_IDENTwith a non-negativeSymElemProcSigand(follows, splice anAN_CALL_IND(callee = the index node), mirroring the record-field path.- No reseed needed —
make bootstrapbyte-identical first pass.make testgreen. Chess compiles + runs: startposbestmove e2e4 score 10(sane, no ±INF saturation). Regression:test/test_indexed_proc_call.pas.