A class or record method may now declare its own type parameters,
independent of the enclosing type, and is monomorphised per call site:
type TUtil = class
function Pick<T>(cond: Boolean; a, b: T): T;
begin if cond then Result := a else Result := b end;
end;
...
u.Pick<Integer>(True, 7, 9); // -> 7
u.Pick<string>(False, 'a', 'b'); // -> 'b'
Each distinct set of explicit type arguments produces one concrete body
named <Owner>_<Method>_<Args> (e.g. TUtil_Pick_Integer); the implicit
Self is preserved, so a generic method can read the receiver's fields and
call its other methods. This is distinct from (and composes with) methods
of a generic CLASS.
Implementation mirrors the existing generic free-function machinery:
- Parser: a method-call folds an explicit <...> type-arg list into the
method name (Pick<Integer>), using the same two-token '<' lookahead as
generic free-function calls.
- Semantic: generic-method templates (TypeParams <> nil) are registered
by Owner.Method and skipped from signature/vtable/body analysis;
InstantiateGenericMethod clones the template, substitutes the type
params, keeps OwnerTypeName + Self, analyses via AnalyseMethodDecl, and
records a TGenericMethodInstance (deduplicated per owner+args). The
call site resolves obj.M<T>(...) to the instance.
- Codegen (both backends): GenericMethodInstances are emitted as ordinary
methods (Self param + mangled ResolvedQbeName).
Verified pick/echo, two distinct instantiations (Integer + string), use
of a Self field, and two type parameters on both backends. Adds IR tests
(TGenericFuncTests.TestCodegen_GenericMethod_{Body,Call}Emitted) and
dual-backend e2e tests (TE2EGenericsTests.TestRun_GenericMethod_*).
Grammar and language-rationale updated.
Limitation (logged in bugs.txt): only the inline-body declaration form is
supported; the out-of-line function TOwner.Method<T>(...) form is not
yet parsed.