Adds support for declaring named procedural types that hold pointers to
standalone functions and procedures:
type
TIntFn = function: Integer;
TStrFn = function(const S: string): Integer;
TLogProc = procedure(Level: Integer; const Msg: string);
var F: TIntFn;
begin F := @MyFn; X := F(); end;
A procedural variable is stored as a single QBE 'l' (8-byte code
pointer). @FuncName produces a value of the matching procedural type.
Indirect calls F(args) load the pointer and emit a QBE indirect call.
Compatibility requires return types to match (both nil or both same
TTypeDesc) and parameter lists to match pairwise on type and parameter
mode (var/const/value); names do not participate.
Compiler additions:
* tyProcedural TTypeKind + TProcParamInfo + TProceduralTypeDesc
(with IsCompatibleWith)
* TProceduralTypeDef AST node
* Parser: type T = function/procedure ... ; reuses ParseParamList
* Semantic: ResolveProceduralTypeDef in pass 2; AnalyseAddrOfExpr
short-circuits @FuncName to a procedural-typed value;
AnalyseFuncCallExpr accepts procedural-typed variables as
indirect-call targets; CheckTypesMatch allows compatible
procedural assignment
* Codegen: QbeTypeOf(tyProcedural) -> 'l'; EmitVarAllocs emits an
8-byte slot; EmitAddrOfExpr emits $FuncName for @FuncName;
EmitFuncCallExpr emits 'call %tmp(...)' for indirect calls,
placed before the ResolvedDecl=nil type-cast branch
Out of scope (deferred until a use case requires them):
* function ... of object (method pointers — fat pointer ABI)
* reference to function/procedure (anonymous methods / closures)
* cdecl/stdcall calling-convention markers on procedural types
Tests: cp.test.proctypes.pas — 14 tests covering parser (kinds,
return types, params, var/const flags), semantic (compat accept/
reject on return type and arg count), and codegen (var allocation,
@FuncName emission, indirect-call emission).
Grammar and rationale: docs/grammar.ebnf adds the ProceduralType
production; docs/language-rationale.adoc captures the decision and
deferred items.
Motivation: prerequisite for porting Michael Van Canneyt's punit test
framework into rtl/src/test/pascal/, where every test, every
Setup/TearDown, and every hook handler is stored as a function
pointer.
1155 tests pass (1141 pre-existing + 14 new), no regressions.