pas2js Generics
From Free Pascal wiki
Jump to navigationJump to searchOverview
Pas2js will support FPC and Delphi like generics.
The next goal is to support generic methods aka parametrized methods, e.g. procedure Fly<T>(p: T).
Working
- generic record
- specialize:
- ObjFPC: type TFoo = specialize TGen<word>;
- Delphi: type TFoo = TGen<word>;
- ObjFPC anonymous: var r: specialize TBird<word>;
- Delphi: anonymous var r: TBird<word>;
- generic class
- specialize in ancestor type
- forward generic class (FPC 3.3.1 does not support it yet)
- enumtype inside generic is not propagated
- generic external class
- generic array
- generic static array: Note: delphi wiki says "no static arrays", but 10.3 compiles it, see http://docwiki.embarcadero.com/RADStudio/Rio/en/Declaring_Generics
- generic interface
- generic procedural type
- specialized proc types can assign normal proc
- Delphi type overload, e.g. type TArr = array of word; TArr<T> = array of T; TArr<T,S> = record i:T; j:S end;
- anonymous type in specialize: TBird<array of word>
- nested specialize: TBird<TWing<byte>>
- record/class field
- property
- method (not confused with generic method)
- Delphi: implementation must repeat type params, must omit constraints
- FPC: implementation must not repeat type params
- for-loop, if-then-else, repeat-until, while-do, try-finally, try-except, case-of
- some assignments
- primitive expression like identifiers and constants
- operators: +, -
- constraints:
- keyword record, class, constructor checked at specialization
- class type checked at specialization
- constraints:
- "class":
- Delphi/FPC: T is TObject
- pas2js: test if T is a class, either TObject or an external class
- "constructor": test if T is TObject and Create resolves to TObject.create
- "record": test if T is a record type
- class type: test if param fits
- list of interface types: test if param fits
- forward class must repeat constraints
- Delphi does not allow TObject as constraint. pas2js allows it, because it has other root classes.
- constraint refers to prior template name: type TBird<X, Y: TAnt<X>> = record a: X; b: Y; end;
- "class":
- statements:
- specialize (cloning) all kinds of statements and expressions
- inline specialize expression, e.g. TList<word>.Create
- Delphi: TFoo<Integer>.Create
- FPC: specialize TFoo<Integer>.Create
- "obj is T": allowed with constraint "class" or class type
- typecast T(): allowed with constraint "class" or class type
- using implementation function in generic function:
- Delphi: Error: Method of parameterized type declared in interface section must not use local symbol '%s'
- FPC: Error: Global Generic template references static symtable
- Pas2js: allowed
- anInt:=GenericVar
- Delphi: always Error: Incompatible types: 'Integer' and 'T'
- FPC/pas2js: allowed for valid combinations -> operators are checked on specialization, Note: because of implementation cross uses, check is delayed until used unit implementation is complete
- for-in TWithConstraint
- typeinfo(T)
- T is TFoo<Integer>
- T as TFoo<Integer>
- TFoo<Integer>(expr)
- call
- pas2js: Later checked by specialization.
- Delphi: must fit the constraint. For example without constraint it only fits untyped args.
- FPC: if there is only one function in scope select it, overloads are selected by constraints alone. Later checked by specialization.
- generic function (aka parametrized method):
- ObjFPC: generic procedure Fly<T>(a: T)
- Delphi: procedure Fly<T>(a: T) Note: Delphi 10.3 only supports parametrized method, not global procedure, pas2js allows it
- forward
- unit interface/implementation
- overloads
- nested generic procedure is forbidden, same as FPC/Delphi
- calling self
- constraints, see above, same as type constraints
- ObjFPC explicitly spezialize: specialize Fly<word>(aWord)
- Delphi explicitly spezialize: Fly<word>(aWord)
- generic method (aka parametrized method):
- methods: virtual, message, constructor and destructors cannot have type parameters
- class interface methods cannot have type parameters
- proc types
- specialize method:
- automatic inferring types Fly(aWord), $modeswitch implicitfunctionspecialization MyProc(1) calls MyProc<T>(a: T)
ToDos
- nested generic type: allowed by Delphi, not allowed by FPC
- cascaded specialize: TBird<word>.TWing<byte>
- generic class:
- overloads A<T> and A<S,T>
- default classname "TTest<System.Longint>"
- pas2js classname "TTest$G1" and overloads
- Delphi: descendants cannot refer to type parameters of ancestors
- FPC: members can refer to itself without parameters
- class constructor
- generic method (aka parametrized method):
- overloads
- nicer error messages
- instead of TList$G1 write TList<word>
- write a hint where it was specialized
- type alias type
- filer
- optimization: reuse specialized functions
- constants as templates: Not planned