blaise/docs
Graeme Geldenhuys f256052a2b feat(types): bare procedural types (function/procedure pointers)
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.
2026-05-03 23:15:42 +01:00
..
design.adoc feat: multi-file compilation (v0.2.0) 2026-04-27 11:35:26 +01:00
future-improvements.adoc feat(types): bare procedural types (function/procedure pointers) 2026-05-03 23:15:42 +01:00
grammar.ebnf feat(types): bare procedural types (function/procedure pointers) 2026-05-03 23:15:42 +01:00
language-rationale.adoc feat(types): bare procedural types (function/procedure pointers) 2026-05-03 23:15:42 +01:00