pas2js Generics

From Free Pascal wiki
Jump to navigationJump to search

Overview

Pas2js will support FPC and Delphi like generics.

The next goal is to support more statements, see below

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.
  • 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

ToDos

  • nested generic type: allowed by Delphi, not allowed by FPC
  • cascaded specialize: TBird<word>.TWing<byte>
  • constraint refers to prior template name: type TBird<X, Y: TAnt<X>> = record a: X; b: Y; end;
  • generic class:
    • default classname "TTest<System.Longint>"
    • pas2js classname "TTest$G1" and overloads
    • Delphi: descendants cannot refer to type parameters of ancestors
    • members can refer to itself without parameters
  • 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
  • specialize method:
    • explicitly specifying Fly<word>(aWord)
    • automatic inferring types Fly(aWord), $modeswitch implicitfunctionspecialization MyProc(1) calls MyProc<T>(a: T)
  • Statements:
    • for-in T
    • T is TFoo<Integer>
    • T as TFoo<Integer>
    • TFoo<Integer>(expr)
    • typeinfo(T)
    • 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.
  • nicer error messages
    • instead of TList$G1 write TList<word>
    • write a hint where it was specialized
  • filer
  • optimization: reuse specialized functions