Sign in Join
Wiki copytemporary

pas2js Generics: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: pas2js Generics

OldNewLine
1+# Overview
2+
3+Pas2js 1.5 supports generic types and functions in either the ObjFPC or Delphi like way.
4+
5+Next goal is to test and fix bugs.
6+
7+## Working
8+
9+- generic class
10+ - ClassName, TypeInfo Name
11+ - Delphi, pas2js: full path with param names, e.g. 'TAnt\<System.Word\>' and 'TAnt\<System.Word\>.TLeg'
12+ - FPC: instead of param names uses crc, e.g. 'TAnt\$1\$crcHexNumber', full paths for classnames, e.g. 'TAnt\$1\$crcHexNumber.TLeg', last name for TypeInfo: e.g. 'TLeg'
13+ - JS specialize code in unit of generic
14+ - forward generic class, e.g. *type TAnt\<T\>=class; TBird=class a: TAnt\<word\>; end; TAnt\<T\>=class a:T; end;*
15+ - Delphi/pas2js: supported
16+ - FPC: 3.3.1 does not support it yet
17+ - enumtype inside generic is not propagated
18+ - ObjFPC: members can refer to parent type without type parameters, e.g. *type generic TAnt\<T\> = class Parent: TAnt; end;*
19+ - Delphi/FPC: descendants cannot refer to type parameters of ancestors, pas2js allows it within same unit (strict private).
20+ - Delphi/FPC does not allow accessing local symbols. pas2js allows it.
21+ - class constructor
22+- generic external class
23+- generic record
24+- generic dynamic array
25+- 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>
26+- generic interface
27+- generic procedural type
28+ - specialized proc types can assign normal proc
29+ - Procedure local scope:
30+ - pas2js: allowed, except for typeinfo
31+ - FPC: allowed, including typeinfo
32+ - Delphi: Error: parameterized type can not be declared in procedure local scope
33+- anonymous type in specialize: *TBird\<array of word\>*
34+- Delphi type overloads A, A\<T\> and A\<S,T\>
35+- specialize:
36+ - ObjFPC: *type TFoo = specialize TGen\<word\>;*
37+ - Delphi: *type TFoo = TGen\<word\>;*
38+ - ObjFPC anonymous: *var r: specialize TBird\<word\>;*
39+ - Delphi: anonymous *var r: TBird\<word\>;*
40+- nested specialize: TBird\<TWing\<byte\>\>
41+- record/class field
42+- property
43+- method (not confused with generic method)
44+ - Delphi: implementation must repeat type params, must omit constraints
45+ - FPC: implementation must not repeat type params
46+- helper for generic type
47+- constraints:
48+ - keyword *record*, *class*, *constructor* checked at specialization
49+ - class type checked at specialization
50+- constraints:
51+ - "class":
52+ - Delphi/FPC: T is TObject
53+ - pas2js: test if T is a class, either TObject or an external class
54+ - "constructor": test if T is TObject and Create resolves to TObject.create
55+ - "record": test if T is a record type
56+ - class type: test if param fits
57+ - list of interface types: test if param fits
58+ - forward class must repeat constraints
59+ - Delphi does not allow *TObject* as constraint. pas2js allows it, because it has other root classes.
60+ - constraint can refer prior templates: *type TBird\<X, Y: TAnt\<X\>\> = record a: X; b: Y; end;*. This is Delphi compatible. FPC 3.3.1 does not support this (23th Aug 2020).
61+- statements:
62+ - specialize (cloning) all kinds of statements and expressions
63+ - for-loop, if-then-else, repeat-until, while-do, try-finally, try-except, case-of
64+ - assignments
65+ - primitive expression like identifiers and constants
66+ - operators: +, -, *, /
67+ - inline specialize expression, e.g. *TList\<word\>.Create*
68+ - Delphi: TFoo\<Integer\>.Create
69+ - FPC: specialize TFoo\<Integer\>.Create
70+ - "obj is T": allowed with constraint "class" or class type
71+ - typecast T(): allowed with constraint "class" or class type
72+ - using implementation function in generic function:
73+ - Delphi: Error: Method of parameterized type declared in interface section must not use local symbol '%s'
74+ - FPC: Error: Global Generic template references static symtable
75+ - Pas2js: allowed
76+ - anInt:=GenericVar
77+ - Delphi: always Error: Incompatible types: 'Integer' and 'T'
78+ - 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
79+ - for-in T do -\> T must have constraints
80+ - typeinfo(T)
81+ - T is TFoo\<Integer\>
82+ - T as TFoo\<Integer\>
83+ - TFoo\<Integer\>(expr)
84+ - call
85+ - pas2js: Later checked by specialization.
86+ - Delphi: must fit the constraint. For example without constraint it only fits untyped args.
87+ - FPC: if there is only one function in scope select it, overloads are selected by constraints alone. Later checked by specialization.
88+- generic function (aka parametrized method):
89+ - ObjFPC: *generic procedure Fly\<T\>(a: T)*
90+ - Delphi: *procedure Fly\<T\>(a: T)* Note: Delphi 10.3 only supports parametrized method, not global procedure, pas2js allows it
91+ - forward
92+ - unit interface/implementation
93+ - overloads
94+ - generic procedure inside a procedure is forbidden, same as FPC/Delphi
95+ - local procedures inside a generic function: supported by FPC and pas2js, not supported by Delphi
96+ - calling self
97+ - constraints, see above, same as type constraints
98+ - ObjFPC explicitly spezialize: *specialize Fly\<word\>(aWord)*
99+ - Delphi explicitly spezialize: *Fly\<word\>(aWord)*
100+ - parameter type inline specialization: *procedure Run\<T\>(List: TList\<T\>);*
101+- generic method (aka parametrized method):
102+ - methods: virtual, message, constructor and destructors cannot have type parameters
103+ - class interface methods cannot have type parameters
104+ - proc types
105+ - overloads
106+- automatically inferring types of generic method/function:
107+ - *MyProc(1)* calls *MyProc\<T\>(a: T)*
108+ - **\$modeswitch implicitfunctionspecialization**: mode Delphi: default enabled, ObjFPC: disabled
109+ - array of T: *procedure Run\<T\>(a: array of T)*
110+ - any order: *procedure Run\<S,T\>(a:T; b:S)*
111+ - infer types: widen types, e.g. *Run(1,1000000)* specializes *Run\<T\>(a,b:T)* with *T* as *longint*. Not supported by Delphi/FPC, supported by pas2js to reduce number of specializations
112+- typecast between specializations gives a warning, not an error
113+- typecast TGenType\<jsvalue\> from/to TGenType\<SomeType\> without warning
114+- allowing ATExtClass\<jsvalue\> := ATExtClass\<SomeType\>
115+- function GetTypeKind(aType): TTypeKind
116+- RTTI
117+ - RTTI names use FPC/Delphi like *TList\<word\>* instead of the JS name *TList\$G1*
118+
119+# RTL Units
120+
121+- generics.defaults.pas
122+- generics.strings.pas
123+- generics.collections.pas
124+
125+# RTL Classes
126+
127+- TArray\<T\>
128+- IComparer\<T\>
129+- TOnComparison\<T\>
130+- TComparer\<T\>
131+- TDefaultComparer\<T\>
132+- IEnumerator\<T\>
133+- IEnumerable\<T\>
134+- TCollectionNotifyEvent\<T\>
135+- TCustomArrayHelper\<T\>
136+- TArrayHelper\<T\>
137+- TEnumerator\<T\>
138+- TEnumerable\<T\>
139+- TCustomList\<T\>
140+- TCustomListEnumerator\<T\>
141+- TCustomInvertedListEnumerator\<T\>
142+- TList\<T\>
143+- TObjectList\<T: class\>
144+- TThreadList\<T\>
145+- TQueue\<T\>
146+- TObjectQueue\<T: class\>
147+- TStack\<T\>
148+- TObjectStack\<T: class\>
149+- TPair\<TKey,TValue\>
150+- TDictionary\<TKey,TValue\>
151+
152+## ToDos
153+
154+- anonymous record, e.g. *type TAnt\<T\> = class a: record end; end;*
155+- anonymous set, e.g. *type TAnt\<T\> = class a: (red, blue); end;*
156+- type alias type as parameter: create separate specialization, at the moment *TList\<integer\>* and *TList\<TColor\>* are the same specialization in pas2js
157+- generic class:
158+ - nested generic type: i.e. generic inside a generic. Allowed by Delphi, not allowed by FPC
159+ - cascaded specialize: TBird\<word\>.TWing\<byte\>
160+ - generic ancestor, allowed in FPC, not allowed in Delphi: *TExample\<T: class\> = class(T) end;*
161+- nicer error messages
162+ - write a hint where it was specialized
163+- Redefinition. Example: *type TBird\<T\> = class i: integer; end; integer = string; TEagle = TBird\<integer\>;* FPC+pas2js: create i as *string*, Delphi: creates i as *system.integer*
164+- optimization: reuse specialized functions
165+- constants as templates
166+- precompiled js files. At the moment all specializations are added to the unit where the generic is defined. That means using a new specialization require to recompile the js file.
167+
168+---
169+*From the Free Pascal wiki, page "pas2js Generics", as it stood on 2022-12-19 after a change by Mattias2, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
170+Category: Pas2js

Back to history