Difference between revisions of "pas2js Generics"
From Free Pascal wiki
Jump to navigationJump to search (→ToDos) |
|||
(One intermediate revision by the same user not shown) | |||
Line 17: | Line 17: | ||
** enumtype inside generic is not propagated | ** enumtype inside generic is not propagated | ||
** ObjFPC: members can refer to parent type without type parameters, e.g. ''type generic TAnt<T> = class Parent: TAnt; end;'' | ** ObjFPC: members can refer to parent type without type parameters, e.g. ''type generic TAnt<T> = class Parent: TAnt; end;'' | ||
− | ** Delphi/FPC: descendants cannot refer to type parameters of ancestors, pas2js allows it. | + | ** Delphi/FPC: descendants cannot refer to type parameters of ancestors, pas2js allows it within same unit (strict private). |
** Delphi/FPC does not allow accessing local symbols. pas2js allows it. | ** Delphi/FPC does not allow accessing local symbols. pas2js allows it. | ||
** class constructor | ** class constructor | ||
Line 151: | Line 151: | ||
==ToDos== | ==ToDos== | ||
− | * anonymous record, e.g. ''type TAnt<T> = class a: record end; end;'' | + | * anonymous record, e.g. ''type TAnt<T> = class a: record end; end;'' |
− | * anonymous set, e.g. ''type TAnt<T> = class a: (red, blue); end;'' | + | * anonymous set, e.g. ''type TAnt<T> = class a: (red, blue); end;'' |
− | * type alias type as parameter: create separate specialization, at the moment ''TList<integer>'' and ''TList<TColor>'' are the same specialization in pas2js | + | * type alias type as parameter: create separate specialization, at the moment ''TList<integer>'' and ''TList<TColor>'' are the same specialization in pas2js |
* generic class: | * generic class: | ||
− | ** nested generic type: i.e. generic inside a generic. Allowed by Delphi, not allowed by FPC | + | ** nested generic type: i.e. generic inside a generic. Allowed by Delphi, not allowed by FPC |
− | ** cascaded specialize: TBird<word>.TWing<byte> | + | ** cascaded specialize: TBird<word>.TWing<byte> |
− | ** Delphi type overloads A, A<T> and A<S,T> | + | ** Delphi type overloads A, A<T> and A<S,T> |
− | ** generic ancestor, allowed in FPC, not allowed in Delphi: ''TExample<T: class> = class(T) end;'' | + | ** generic ancestor, allowed in FPC, not allowed in Delphi: ''TExample<T: class> = class(T) end;'' |
* nicer error messages | * nicer error messages | ||
** write a hint where it was specialized | ** write a hint where it was specialized | ||
− | * Redefinition. Example: ''type TBird<T> = class i: integer; end; integer = string; TEagle = TBird<word>;'' FPC+pas2js: create i as ''string'', Delphi: creates i as ''system.integer'' | + | * Redefinition. Example: ''type TBird<T> = class i: integer; end; integer = string; TEagle = TBird<word>;'' FPC+pas2js: create i as ''string'', Delphi: creates i as ''system.integer'' |
* filer | * filer | ||
− | * optimization: reuse specialized functions | + | * optimization: reuse specialized functions |
− | * constants as templates | + | * constants as templates |
[[Category:Pas2js]] | [[Category:Pas2js]] |
Revision as of 20:22, 17 February 2021
Overview
Pas2js 1.5 supports generic types and functions in either the ObjFPC or Delphi like way.
Next goal is to test and fix bugs.
Working
- generic class
- ClassName, TypeInfo Name
- Delphi, pas2js: full path with param names, e.g. 'TAnt<System.Word>' and 'TAnt<System.Word>.TLeg'
- 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'
- JS specialize code in unit of generic
- forward generic class, e.g. type TAnt<T>=class; TBird=class a: TAnt<word>; end; TAnt<T>=class a:T; end;
- Delphi/pas2js: supported
- FPC: 3.3.1 does not support it yet
- enumtype inside generic is not propagated
- ObjFPC: members can refer to parent type without type parameters, e.g. type generic TAnt<T> = class Parent: TAnt; end;
- Delphi/FPC: descendants cannot refer to type parameters of ancestors, pas2js allows it within same unit (strict private).
- Delphi/FPC does not allow accessing local symbols. pas2js allows it.
- class constructor
- ClassName, TypeInfo Name
- generic external class
- generic record
- generic dynamic 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
- Procedure local scope:
- pas2js: allowed, except for typeinfo
- FPC: allowed, including typeinfo
- Delphi: Error: parameterized type can not be declared in procedure local scope
- anonymous type in specialize: TBird<array of word>
- 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>;
- 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
- helper for generic type
- 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 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).
- "class":
- statements:
- specialize (cloning) all kinds of statements and expressions
- for-loop, if-then-else, repeat-until, while-do, try-finally, try-except, case-of
- assignments
- primitive expression like identifiers and constants
- operators: +, -, *, /
- 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 T do -> T must have constraints
- 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
- generic procedure inside a procedure is forbidden, same as FPC/Delphi
- local procedures inside a generic function: supported by FPC and pas2js, not supported by Delphi
- calling self
- constraints, see above, same as type constraints
- ObjFPC explicitly spezialize: specialize Fly<word>(aWord)
- Delphi explicitly spezialize: Fly<word>(aWord)
- parameter type inline specialization: procedure Run<T>(List: TList<T>);
- generic method (aka parametrized method):
- methods: virtual, message, constructor and destructors cannot have type parameters
- class interface methods cannot have type parameters
- proc types
- overloads
- automatically inferring types of generic method/function:
- MyProc(1) calls MyProc<T>(a: T)
- $modeswitch implicitfunctionspecialization: mode Delphi: default enabled, ObjFPC: disabled
- array of T: procedure Run<T>(a: array of T)
- any order: procedure Run<S,T>(a:T; b:S)
- 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
- typecast between specializations gives a warning, not an error
- typecast TGenType<jsvalue> from/to TGenType<SomeType> without warning
- allowing ATExtClass<jsvalue> := ATExtClass<SomeType>
- function GetTypeKind(aType): TTypeKind
- RTTI
- RTTI names use FPC/Delphi like TList<word> instead of the JS name TList$G1
RTL Units
- generics.defaults.pas
- generics.strings.pas
- generics.collections.pas
RTL Classes
- TArray<T>
- IComparer<T>
- TOnComparison<T>
- TComparer<T>
- TDefaultComparer<T>
- IEnumerator<T>
- IEnumerable<T>
- TCollectionNotifyEvent<T>
- TCustomArrayHelper<T>
- TArrayHelper<T>
- TEnumerator<T>
- TEnumerable<T>
- TCustomList<T>
- TCustomListEnumerator<T>
- TCustomInvertedListEnumerator<T>
- TList<T>
- TObjectList<T: class>
- TThreadList<T>
- TQueue<T>
- TObjectQueue<T: class>
- TStack<T>
- TObjectStack<T: class>
- TPair<TKey,TValue>
- TDictionary<TKey,TValue>
ToDos
- anonymous record, e.g. type TAnt<T> = class a: record end; end;
- anonymous set, e.g. type TAnt<T> = class a: (red, blue); end;
- type alias type as parameter: create separate specialization, at the moment TList<integer> and TList<TColor> are the same specialization in pas2js
- generic class:
- nested generic type: i.e. generic inside a generic. Allowed by Delphi, not allowed by FPC
- cascaded specialize: TBird<word>.TWing<byte>
- Delphi type overloads A, A<T> and A<S,T>
- generic ancestor, allowed in FPC, not allowed in Delphi: TExample<T: class> = class(T) end;
- nicer error messages
- write a hint where it was specialized
- Redefinition. Example: type TBird<T> = class i: integer; end; integer = string; TEagle = TBird<word>; FPC+pas2js: create i as string, Delphi: creates i as system.integer
- filer
- optimization: reuse specialized functions
- constants as templates