Difference between revisions of "pas2js Generics"
From Free Pascal wiki
Jump to navigationJump to searchLine 1: | Line 1: | ||
=Overview= | =Overview= | ||
+ | |||
+ | Pas2js will support FPC and Delphi like generics. | ||
==Working== | ==Working== | ||
Line 11: | Line 13: | ||
* generic class | * generic class | ||
** specialize in ancestor type | ** specialize in ancestor type | ||
− | ** forward generic class (FPC does not support it yet) | + | ** forward generic class (FPC 3.3.1 does not support it yet) |
** enumtype inside generic is not propagated | ** enumtype inside generic is not propagated | ||
* generic external class | * generic external class | ||
* generic array | * generic array | ||
+ | * generic interface | ||
+ | * generic procedural type | ||
+ | * 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>'' | ||
* record/class field | * record/class field | ||
* property | * property | ||
* method (not confused with generic method) | * 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 | * for-loop, if-then-else, repeat-until, while-do, try-finally, try-except, case-of | ||
* some assignments | * some assignments | ||
Line 25: | Line 33: | ||
** keyword ''record'', keyword ''class'' checked at specialization | ** keyword ''record'', keyword ''class'' checked at specialization | ||
** class type checked at specialization | ** class type checked at specialization | ||
+ | * constraints: | ||
+ | ** "class", "record": test if param fits | ||
+ | ** class type: test if param fits | ||
+ | ** list of interface types: test if param fits | ||
+ | ** forward class must repeat constraints | ||
+ | * 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 | ||
==ToDos== | ==ToDos== | ||
− | |||
* cascaded specialize: TBird<word>.TWing<byte> | * cascaded specialize: TBird<word>.TWing<byte> | ||
* nested specialize: TBird<TWing<byte>> | * nested specialize: TBird<TWing<byte>> | ||
− | |||
* generic class: | * generic class: | ||
** default classname "TTest<System.Longint>" | ** default classname "TTest<System.Longint>" | ||
Line 38: | Line 54: | ||
** members can refer to itself without parameters | ** members can refer to itself without parameters | ||
** nested generic: allowed by Delphi, not allowed by FPC | ** nested generic: allowed by Delphi, not allowed by FPC | ||
− | |||
− | |||
− | |||
* 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 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 function (aka parametrized method): | * generic function (aka parametrized method): | ||
** Delphi does not allow global generic functions, only generic methods | ** Delphi does not allow global generic functions, only generic methods | ||
** methods: virtual, message, constructor and destructors cannot have type parameters | ** methods: virtual, message, constructor and destructors cannot have type parameters | ||
* constraints: | * constraints: | ||
− | ** | + | ** "constructor" (class+default constructor, can be combined with class) |
− | |||
** one class type (Delphi: not TObject) | ** one class type (Delphi: not TObject) | ||
− | |||
* specialize method: | * specialize method: | ||
** explicitly specifying Fly<word>(aWord) | ** explicitly specifying Fly<word>(aWord) | ||
Line 57: | Line 67: | ||
* Statements: | * Statements: | ||
** for-in, enumerators | ** for-in, enumerators | ||
− | |||
** inline specialization | ** inline specialization | ||
− | |||
− | |||
** T is TFoo<Integer> | ** T is TFoo<Integer> | ||
** T as TFoo<Integer> | ** T as TFoo<Integer> |
Revision as of 15:34, 26 August 2019
Overview
Pas2js will support FPC and Delphi like generics.
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 interface
- generic procedural type
- 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>
- 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, keyword class checked at specialization
- class type checked at specialization
- constraints:
- "class", "record": test if param fits
- class type: test if param fits
- list of interface types: test if param fits
- forward class must repeat constraints
- 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
ToDos
- cascaded specialize: TBird<word>.TWing<byte>
- nested specialize: TBird<TWing<byte>>
- generic class:
- default classname "TTest<System.Longint>"
- pas2js classname "TTest$G1" and overloads
- descendants cannot refer to type parameters of ancestors
- members can refer to itself without parameters
- nested generic: allowed by Delphi, not allowed by FPC
- 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 function (aka parametrized method):
- Delphi does not allow global generic functions, only generic methods
- methods: virtual, message, constructor and destructors cannot have type parameters
- constraints:
- "constructor" (class+default constructor, can be combined with class)
- one class type (Delphi: not TObject)
- specialize method:
- explicitly specifying Fly<word>(aWord)
- automatic inferring types Fly(aWord), $modeswitch implicitfunctionspecialization MyProc(1) calls MyProc<T>(a: T)
- specialized proc types can assign normal proc
- Statements:
- for-in, enumerators
- inline specialization
- T is TFoo<Integer>
- T as TFoo<Integer>
- TFoo<Integer>(expr)
- "obj is T": allowed with constraint "class" or class type
- typecast T(): allowed with constraint "class" or class type
- typeinfo(T)
- 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
- anInt:=GenericVar
- Delphi: always Error: Incompatible types: 'Integer' and 'T'
- FPC: allowed for valid combinations -> operators are checked on specialization, Note: because of implementation cross uses, check must be delayed until used unit implementation is complete
- call
- Delphi: must fit the constraint. For example without constraint it only fits untyped args.
- FPC: if only one function in scope preselect it, overloads are selected by constraints alone. Later checked by specialization.