← board

array of const (TVarRec) parameter support

Done so far (2026-06-14)

Remaining: High() (not in lexer — test uses Length-1); other vt* tags; i386/cross verification; the array-of-const temp heap-leaks per call (FPC builds it on the stack) — fine for the asm emitter, revisit if it matters.

Known divergences from FPC (half-working, by design for now)

Motivation

The dialect has no variadic / mixed-type argument facility. writeln/read are compiler magic, not something a user routine can imitate. The Pascal answer is array of const (an open array of TVarRec, the machinery behind Format()), which lets a routine take a bracketed, mixed-type argument list:

emit(['mov eax, %', 2, 'add eax, %,%', 3, 4]);   { strings + ints interleaved }

This is the enabler for feature-asm-text-emitter (readable asm-as-data emission) and for any future Format-style routine. It is FPC-3.2.2 compatible (verified) so it does not threaten the make bootstrap path — unlike multiline strings (FPC 3.3.1 only) or bare varargs (compiler magic), both of which we explicitly ruled out for that reason.

What FPC does (verified 2026-06-14, ppcx64 3.2.2)

procedure emit(const items: array of const) — the callee walks items, switching on each element's VType tag:

for i := 0 to High(items) do
  case items[i].VType of
    vtInteger:    use items[i].VInteger;
    vtAnsiString: use AnsiString(items[i].VAnsiString);
  end;

Captured facts PXX must reproduce bit-for-bit (the same compiler source is read by both FPC during bootstrap and PXX during self-compile, so layout and constants must agree):

Scope

Minimum viable for the asm emitter (int + ansistring elements):

  1. Type recognition — accept array of const as a parameter type; expose TVarRec, the vt* constants, and the element fields (VType, VInteger, VAnsiString) to source. Match FPC's names/values so one source compiles under both.
  2. Call-site construction — for f([a, 1, 'x', expr]), lower each element to a stack/temp TVarRec: integer expr → {VType:=vtInteger; VInteger:=v}; ansistring expr/literal → {VType:=vtAnsiString; VAnsiString:=handle}. Build the contiguous array, pass it as an open array (ptr, High) like other open arrays. Target-correct element size (16 on 64-bit targets, 8 on i386).
  3. Callee readitems[i].VType / .VInteger / .VAnsiString and High(items)/Length(items) already fall out of open-array + record field access; just need the field offsets right per target.
  4. Refcounting: an array of const does not own its ansistring elements (FPC convention — VAnsiString is a borrowed pointer; the caller's string outlives the call). So no IncRef/DecRef on construction — simpler, and matches FPC so behaviour is identical.

Defer: the other vt* tags (vtChar, vtBoolean, vtExtended, vtPointer, vtVariant, …) until a consumer needs them. Two tags carry the asm-emit ticket.

Acceptance

Notes / landmines

Log