Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / pas2js / 2019-10

Testing generics

37 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Michael Van Canneyt
to Mattias Gaertner

Hm. I am amazed and pleasantly surprised.

Do you ever sleep ?

You're much farther than I expected. The todo list is actually quite short.

3 questions:
1. Should we notify Bruno or do you think it is better to wait ? He asked about progress on the phone yesterday, I said I'd investigate but I think the answer is now quite clear, so not much investigation is needed.
2. Do you think the fgl unit can be ported ?
3. I saw you created simple version of some generics routines. Do you think it is already possible to port the rtl-generics units ? TMS Software and wagner Landgraf in particular use these units.

In each case, congratulations on the huge progress you made !

Michael.

Mattias Gaertner wrote 20 lines
Hi, pas2js trunk now supports generics. Here is a list of features, what should work and what not: https://wiki.lazarus.freepascal.org/pas2js_Generics As demonstration I added the generic TList<T> in the rtl units: generics.collections.pas generics.defaults.pas generics.strings.pas Now I'm searching some brave adventurers to test this alpha feature and report bugs. Mattias _______________________________________________ Pas2js maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/pas2js

Reply by email

Ben Grasset
to Michael Van Canneyt
PM Michael Van Canneyt wrote 47 lines
Hm. I am amazed and pleasantly surprised. Do you ever sleep ? You're much farther than I expected. The todo list is actually quite short. 3 questions: 1. Should we notify Bruno or do you think it is better to wait ? He asked about progress on the phone yesterday, I said I'd investigate but I think the answer is now quite clear, so not much investigation is needed. 2. Do you think the fgl unit can be ported ? 3. I saw you created simple version of some generics routines. Do you think it is already possible to port the rtl-generics units ? TMS Software and wagner Landgraf in particular use these units. In each case, congratulations on the huge progress you made ! Michael. On Thu, 17 Oct 2019, Mattias Gaertner via Pas2js wrote: > Hi, > > pas2js trunk now supports generics. > Here is a list of features, what should work and what not: > > https://wiki.lazarus.freepascal.org/pas2js_Generics > > As demonstration I added the generic TList<T> in the rtl units: > generics.collections.pas > generics.defaults.pas > generics.strings.pas > > Now I'm searching some brave adventurers to test this alpha feature and > report bugs. > > > Mattias > _______________________________________________ > Pas2js maillist - > https://lists.freepascal.org/cgi-bin/mailman/listinfo/pas2js _______________________________________________ Pas2js maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/pas2js

Nice work! I'm not much of a web person myself, but I find Pas2JS interesting, so I've been following the development pretty closely.

FYI: I've done a lot of experimentation with generics, and have found that basically all the classes that directly represent ones from Javascript (like TJSArray and so on) can be re-defined as generic (so that all the instances of "JSValue" become "T") and it works just as well as what you might expect from TypeScript (where everything has pretty much always been defined as generic.)

Personally, I don't see too much of a need for anything like generic classes ported over from Pascal, as for example the generic version of TJSArray does everything TList<T> does (more, actually!)

I'm sure there are people out there who'd like a more complete version of rtl-generics in Pas2JS though, so it's probably worth doing. -------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/pas2js/attachments/20191018/d6d69b55/attachment.html>

Reply by email

warleyalex
to Ben Grasset

Test I: test OK
====

type
  { TFakeClass }
  generic TFakeClass<_GT> = class
    class function gmax(a,b: _GT):_GT;
  end;
  TFakeClassInt = specialize TFakeClass<integer>;
  TFakeClassDouble = specialize TFakeClass<double>;
{ An example of how to use generics to write a function gmax() that takes
the
  maximum of two not-yet-typed variables. Note that while the functions here
  are namespaced by the classname, FPC versions from 3.1.1 onwards also
support
  fully free-standing generic methods.
}
procedure Fake_Class;
begin
  // show max of two integers
  console.log( 'Integer GMax:', TFakeClassInt.gmax( 23, 56 ) );
  // show max of two doubles
  console.log( 'Double GMax:', TFakeClassDouble.gmax( 23.89, 56.5) );
end;

// console output:
Integer GMax: 56
Double GMax: 56.5
--------------------------------------------------------- Test II --> this test fail :(
=====

  {$mode delphi}

uses
JS, Classes, SysUtils, Web, Types, Math,

  generics.collections, generics.defaults, generics.strings;
type
  TDoubleIntegerArray = array of TIntegerDynArray;
procedure PrintMatrix(A: TDoubleIntegerArray);
var
  i, j: Integer;
begin
  for i := Low(A) to High(A) do
  begin
    for j := Low(A[0]) to High(A[0]) do
      Write(A[i, j]: 3, ' ');
    Writeln;
  end;
  Writeln; Writeln;
end;
function CustomCompare_1(constref Left, Right: TIntegerDynArray): Integer;
begin
  Result := TCompare.Integer(Right[0], Left[0]);
end;
function CustomCompare_2(constref Left, Right: TIntegerDynArray): Integer;
var
  i: Integer;
begin
  i := 0;
  repeat
    Result := TCompare.Integer(Right[i], Left[i]);
    Inc(i);
  until ((Result  0) or (i = Length(Left)));
end;
function CustomCompare1(const Left, Right: TIntegerDynArray): Integer;
begin
  Result := Right[0] - Left[0];
end;
function CustomCompare2(const Left, Right: TIntegerDynArray): Integer;
var
  i: Integer;
begin
  i := 0;
  repeat
    Result := Right[i] - Left[i];
    Inc(i);
  until ((Result  0) or (i = Length(Left)));
end;
var
  A: TDoubleIntegerArray;
  FoundIndex: Integer;
  i, j: Integer;
begin
  WriteLn('Working with TArray - a two-dimensional integer array');
  WriteLn;
  // Fill integer array with random numbers [1 .. 50]
  SetLength(A, 4, 7);
  Random;
//  Randomize;
  for i := Low(A) to High(A) do
    for j := Low(A[0]) to High(A[0]) do
      A[i, j] := Math.RandomRange(1, 50);
  // Equate some of the elements for further "cascade" sorting
  A[1, 0] := A[0, 0];
  A[2, 0] := A[0, 0];
  A[1, 1] := A[0, 1];
  // Print out what happened
  Writeln('The original array:');
  PrintMatrix(A);
  // ! pas2js don't support anonymous methods yet
  // Sort descending 1st column, with cutom comparer_1
  TArrayHelper<TIntegerDynArray>.Sort(A,
TComparer<TIntegerDynArray>.Construct(@CustomCompare1));
  Writeln('Descending in column 1:');
  PrintMatrix(A);
  // Sort descending 1st column "cascade" -
  // If the line items are equal, compare neighboring
  TArrayHelper<TIntegerDynArray>.Sort(A,
TComparer<TIntegerDynArray>.Construct(@CustomCompare2));
  Writeln('Cascade sorting, starting from the 1st column:');
  PrintMatrix(A);
//--------------------------------------------------------------------
// This pas2js project compiles but we have this output error:

rtl.js:688
Uncaught TypeError: Cannot read property '_Release' of null at Object.free (rtl.js:688)
at Object.$mod.$main (projGenerics.lpr:493)
at doRun (rtl.js:141)
at run (rtl.js:156)

// example expected results:
==================
Working with TArray - a two-dimensional integer array

The original array:
9 43 14 1 48 40 33
9 43 30 21 10 36 45
9 32 45 45 42 33 42
39 35 26 38 45 48 15

Descending in column 1:
39 35 26 38 45 48 15
9 32 45 45 42 33 42
9 43 14 1 48 40 33
9 43 30 21 10 36 45

Cascade sorting, starting from the 1st column:
39 35 26 38 45 48 15
9 43 30 21 10 36 45
9 43 14 1 48 40 33
9 32 45 45 42 33 42

-------------------------------------------------------- Working with TArray - a two-dimensional integer array

The original array:
6 31 7 17 47 21 16
6 31 20 12 9 28 4
6 44 27 40 29 45 44
39 12 18 37 10 3 29

Descending in column 1:
39 12 18 37 10 3 29
6 44 27 40 29 45 44
6 31 7 17 47 21 16
6 31 20 12 9 28 4

Cascade sorting, starting from the 1st column:
39 12 18 37 10 3 29
6 44 27 40 29 45 44
6 31 20 12 9 28 4
6 31 7 17 47 21 16

Reply by email

Michael Van Canneyt
to Ben Grasset: On Thu, Oct 17, 2019 at 5:48 PM Michael Van Canneyt Nice work! I'm not much of a web…
Ben Grasset wrote
Nice work! I'm not much of a web person myself, but I find Pas2JS interesting, so I've been following the development pretty closely.

I've meanwhile done 2 commercial web projects with it, and development goes amazingly fast.

The start of webwidgets which I committed earlier have been enhanced very much meanwhile, and I will publish the enhancements in the near future, together with a demo application.

The template loader/component is in fact the workhorse doing the bulk of the work and in combination with bootstrap CSS you can have an application up and running in no time.

But the biggest help have been the dataset classes, combined with a REST or Remobjects Data Abstract backend..

Show quoted text 6 lines
FYI: I've done a lot of experimentation with generics, and have found that basically all the classes that directly represent ones from Javascript (like TJSArray and so on) can be re-defined as generic (so that all the instances of "JSValue" become "T") and it works just as well as what you might expect from TypeScript (where everything has pretty much always been defined as generic.)

At least TJSArray and TJSPromise are on my list for replacement with generic types, as well as TTypedArray and friends. For backwards compatibility I'll keep the current classes as specializations with JSValue.

Do you have other classes in mind that could be usefully replaced/enhanced with a generic variant?

Michael.

Reply by email

Mattias Gaertner
to warleyalex: Test I: test OK ==== type { TFakeClass } generic TFakeClass<_GT> = class class function…
Show quoted text 101 lines
Test I: test OK [...] Test II --> this test fail :( ===== {$mode delphi} uses JS, Classes, SysUtils, Web, Types, Math, generics.collections, generics.defaults, generics.strings; type TDoubleIntegerArray = array of TIntegerDynArray; procedure PrintMatrix(A: TDoubleIntegerArray); var i, j: Integer; begin for i := Low(A) to High(A) do begin for j := Low(A[0]) to High(A[0]) do Write(A[i, j]: 3, ' '); Writeln; end; Writeln; Writeln; end; function CustomCompare_1(constref Left, Right: TIntegerDynArray): Integer; begin Result := TCompare.Integer(Right[0], Left[0]); end; function CustomCompare_2(constref Left, Right: TIntegerDynArray): Integer; var i: Integer; begin i := 0; repeat Result := TCompare.Integer(Right[i], Left[i]); Inc(i); until ((Result 0) or (i = Length(Left))); end; function CustomCompare1(const Left, Right: TIntegerDynArray): Integer; begin Result := Right[0] - Left[0]; end; function CustomCompare2(const Left, Right: TIntegerDynArray): Integer; var i: Integer; begin i := 0; repeat Result := Right[i] - Left[i]; Inc(i); until ((Result 0) or (i = Length(Left))); end; var A: TDoubleIntegerArray; FoundIndex: Integer; i, j: Integer; begin WriteLn('Working with TArray - a two-dimensional integer array'); WriteLn; // Fill integer array with random numbers [1 .. 50] SetLength(A, 4, 7); Random; // Randomize; for i := Low(A) to High(A) do for j := Low(A[0]) to High(A[0]) do A[i, j] := Math.RandomRange(1, 50); // Equate some of the elements for further "cascade" sorting A[1, 0] := A[0, 0]; A[2, 0] := A[0, 0]; A[1, 1] := A[0, 1]; // Print out what happened Writeln('The original array:'); PrintMatrix(A); // ! pas2js don't support anonymous methods yet // Sort descending 1st column, with cutom comparer_1 TArrayHelper<TIntegerDynArray>.Sort(A, TComparer<TIntegerDynArray>.Construct(@CustomCompare1)); Writeln('Descending in column 1:'); PrintMatrix(A); // Sort descending 1st column "cascade" - // If the line items are equal, compare neighboring TArrayHelper<TIntegerDynArray>.Sort(A, TComparer<TIntegerDynArray>.Construct(@CustomCompare2)); Writeln('Cascade sorting, starting from the 1st column:'); PrintMatrix(A); //-------------------------------------------------------------------- // This pas2js project compiles but we have this output error:
After changing constref to const I get:
test1.pas(32,13) Error: identifier not found "TCompare"

Mattias

Reply by email

warleyalex
to Mattias Gaertner
// ! pas2js don't support anonymous methods yet

I mean like in this situation:

  TArrayHelper.Sort<TIntegerDynArray>(A,
TComparer<TIntegerDynArray>.Construct(
    function (const Left, Right: TIntegerDynArray): Integer
    begin
      Result := Right[0] - Left[0];
    end));

(...) I've still got Uncaught TypeError: Cannot read property '_Release' of null

live preview:
https://pas2js.github.io/master/tarrayprojectdouble/tarrayprojectdouble.html download project: https://pas2js.github.io/master/tarrayprojectdouble.rar

Reply by email

warleyalex
to warleyalex
{$mode delphi}
{$modeswitch AdvancedRecords}
type
  TCustomer = record
  private
    FName: string;
    FMoney: Currency;
  public
    constructor Create(const Name: string; Money: Currency);
    property Name: string read FName write FName;
    property Money: Currency read FMoney write FMoney;
    function ToString: string;
  end;

{ TCustomer }

constructor TCustomer.Create(const Name: string; Money: Currency);
begin
  FName := Name;
  FMoney := Money;
end;
function TCustomer.ToString: string;
begin
  Result := Format('Name: %s >>> Money: %m', [Name, Money]);
end;
(...)  Hum, it's not possible yet to compile this piece of code:
var
  CustomersArray: TArray<TCustomer>;

begin

  CustomersArray := TArray<TCustomer>.Create(
    TCustomer.Create('AAA', 10),
    TCustomer.Create('BBB', 20),
    TCustomer.Create('CCC', 30),
    TCustomer.Create('DDD', 40)
  );

Reply by email

Mattias Gaertner
to warleyalex: I mean like in this situation: TArrayHelper.Sort<TIntegerDynArray>(A,…
Show quoted text 18 lines
> // ! pas2js don't support anonymous methods yet I mean like in this situation: TArrayHelper.Sort<TIntegerDynArray>(A, TComparer<TIntegerDynArray>.Construct( function (const Left, Right: TIntegerDynArray): Integer begin Result := Right[0] - Left[0]; end)); (...) I've still got Uncaught TypeError: Cannot read property '_Release' of null live preview: https://pas2js.github.io/master/tarrayprojectdouble/tarrayprojectdouble.html download project: https://pas2js.github.io/master/tarrayprojectdouble.rar
I get:
tarrayprojectdouble.lpr(29,13) Error: identifier not found "TCompare"

Can you create a complete example, or even better: a bug report with an example?

Mattias

Reply by email

Mattias Gaertner
to warleyalex: {$mode delphi} {$modeswitch AdvancedRecords} type TCustomer = record private FName:…
Show quoted text 39 lines
{$mode delphi} {$modeswitch AdvancedRecords} type TCustomer = record private FName: string; FMoney: Currency; public constructor Create(const Name: string; Money: Currency); property Name: string read FName write FName; property Money: Currency read FMoney write FMoney; function ToString: string; end; { TCustomer } constructor TCustomer.Create(const Name: string; Money: Currency); begin FName := Name; FMoney := Money; end; function TCustomer.ToString: string; begin Result := Format('Name: %s >>> Money: %m', [Name, Money]); end; (...) Hum, it's not possible yet to compile this piece of code: var CustomersArray: TArray<TCustomer>; begin CustomersArray := TArray<TCustomer>.Create( TCustomer.Create('AAA', 10), TCustomer.Create('BBB', 20), TCustomer.Create('CCC', 30), TCustomer.Create('DDD', 40) );

I get:
Error: illegal qualifier "." after "array of TCustomer"

Do you have a type helper for TArray<TCustomer>?

Mattias

Reply by email

warleyalex
to Mattias Gaertner
generic function Min<T>(const A, B: T): T;
begin
  if A < B then
    Result := A else
    Result := B;
end;
begin
// it compiles/worked as expected
  specialize Min<Integer>(1, 0);     // Min (1, 0):  0
  specialize Min<Single>(3.14, 5);  //Min (3.14, 5):  3.14
  specialize Min<string>('a', 'b');     //Min ("a", "b"):  a
(* but we can not compile the following: *)
  WriteLn('Min (1, 0): ', specialize Min<Integer>(1, 0));
  WriteLn('Min (3.14, 5): ', specialize Min<Single>(3.14, 5));
  WriteLn('Min (''a'', ''b''): ', specialize Min<string>('a', 'b'));
end;
projGenericsA.lpr(29,41) Error: not yet implemented:
TInlineSpecializeExpr:TInlineSpecializeExpr [20170306102158]

Reply by email

Mattias Gaertner
to warleyalex
Show quoted text 22 lines
generic function Min<T>(const A, B: T): T; begin if A < B then Result := A else Result := B; end; begin // it compiles/worked as expected specialize Min<Integer>(1, 0); // Min (1, 0): 0 specialize Min<Single>(3.14, 5); //Min (3.14, 5): 3.14 specialize Min<string>('a', 'b'); //Min ("a", "b"): a (* but we can not compile the following: *) WriteLn('Min (1, 0): ', specialize Min<Integer>(1, 0)); WriteLn('Min (3.14, 5): ', specialize Min<Single>(3.14, 5)); WriteLn('Min (''a'', ''b''): ', specialize Min<string>('a', 'b')); end; projGenericsA.lpr(29,41) Error: not yet implemented: TInlineSpecializeExpr:TInlineSpecializeExpr [20170306102158]

Fixed.

Mattias

Reply by email

Pedro Pablo Oviedo Vera
to warleyalex: generic function Min<T>(const A, B: T): T; begin if A < B then Result := A else Result :=…

excuse me....but I'm no sure ...is it true pas2js already has anonymous method support ?

Thank a lot!

El lun., 21 oct. 2019 a las 22:22, warleyalex via Pas2js (<

Show quoted text 33 lines
) escribió: generic function Min<T>(const A, B: T): T; begin if A < B then Result := A else Result := B; end; begin // it compiles/worked as expected specialize Min<Integer>(1, 0); // Min (1, 0): 0 specialize Min<Single>(3.14, 5); //Min (3.14, 5): 3.14 specialize Min<string>('a', 'b'); //Min ("a", "b"): a (* but we can not compile the following: *) WriteLn('Min (1, 0): ', specialize Min<Integer>(1, 0)); WriteLn('Min (3.14, 5): ', specialize Min<Single>(3.14, 5)); WriteLn('Min (''a'', ''b''): ', specialize Min<string>('a', 'b')); end; projGenericsA.lpr(29,41) Error: not yet implemented: TInlineSpecializeExpr:TInlineSpecializeExpr [20170306102158] -- Sent from: http://pas2js.38893.n8.nabble.com/ _______________________________________________ Pas2js maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/pas2js
MSc. Ing. Pedro Pablo Oviedo Vera Dirección Técnica y Desarrollo Empresa de Proyectos e Ingeniería del Ministerio de la Agricultura.ENPA. Boyeros y Conill, Piso 10 Edif MINAG Telef. 884 7197 SIP:23000116 -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.freepascal.org/pipermail/pas2js/attachments/20191022/28d3a14e/attachment.html>

Reply by email

Pedro Pablo Oviedo Vera
to Mattias Gaertner

Iam sorry...Iam not on the ball....it is nice...Thanks

El mar., 22 oct. 2019 a las 8:29, Mattias Gaertner via Pas2js (<

Show quoted text 16 lines
) escribió: On Tue, 22 Oct 2019 08:20:20 -0400 Pedro Pablo Oviedo Vera wrote: > excuse me....but I'm no sure ...is it true pas2js already has > anonymous method support ? Yes, since 1.2: https://wiki.lazarus.freepascal.org/Pas2JS_Version_Changes#Version_1.2.0RC1 Mattias _______________________________________________ Pas2js maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/pas2js
MSc. Ing. Pedro Pablo Oviedo Vera Dirección Técnica y Desarrollo Empresa de Proyectos e Ingeniería del Ministerio de la Agricultura.ENPA. Boyeros y Conill, Piso 10 Edif MINAG Telef. 884 7197 SIP:23000116 -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.freepascal.org/pipermail/pas2js/attachments/20191022/a618f354/attachment.html>

Reply by email

Ben Grasset
to Michael Van Canneyt: I've meanwhile done 2 commercial web projects with it, and development goes amazingly…
PM Michael Van Canneyt wrote 9 lines
At least TJSArray and TJSPromise are on my list for replacement with generic types, as well as TTypedArray and friends. For backwards compatibility I'll keep the current classes as specializations with JSValue. Do you have other classes in mind that could be usefully replaced/enhanced with a generic variant?

There's a fair number overall. I actually have a "JSGenerics" unit I made for the purposes of playing around with generics in Pas2JS that I could submit as a patch for you to look at, if you want.

It currently has full generic translations of the following class definitions from JS.pas (prefixed like "TGJS" instead of "TJS" to avoid any name conflicts):

- TJSIteratorValue
- TJSIterator
- TJSSet
- TJSMap
- TJSFunction
- TJSArray
- TJSArrayBuffer
- TJSBufferSource
- TJSTypedArray
- TJSPromise
- TJSFunctionArguments

The various callback type aliases are included as well (under "public type" in the relevant class instead of globally, to avoid the forward-declaration problem with generics.)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/pas2js/attachments/20191022/4cf4705c/attachment.html>

Reply by email

Mattias Gaertner
to Ben Grasset
[...] The various callback type aliases are included as well (under "public type" in the relevant class instead of globally, to avoid the forward-declaration problem with generics.)

What do you mean with the "forward-declaration problem with generics"?

Mattias

Reply by email

Michael Van Canneyt
to Ben Grasset: On Fri, Oct 18, 2019 at 5:23 PM Michael Van Canneyt There's a fair number overall. I…
Ben Grasset wrote 16 lines
On Fri, Oct 18, 2019 at 5:23 PM Michael Van Canneyt wrote: > At least TJSArray and TJSPromise are on my list for replacement with > generic > types, as well as TTypedArray and friends. For backwards compatibility I'll > keep the current classes as specializations with JSValue. > > Do you have other classes in mind that could be usefully replaced/enhanced > with > a generic variant? > There's a fair number overall. I actually have a "JSGenerics" unit I made for the purposes of playing around with generics in Pas2JS that I could submit as a patch for you to look at, if you want.

Please send it to me, I'll use it as inspiration for changing the existing classes.

Michael.

Reply by email

Ben Grasset
to Mattias Gaertner: On Tue, 22 Oct 2019 17:14:01 -0400 What do you mean with the "forward-declaration problem…

On Tue, Oct 22, 2019 at 5:21 PM Mattias Gaertner via Pas2js <

wrote: What do you mean with the "forward-declaration problem with generics"?

It's not an issue with Pas2JS. I just meant the way they work in Pascal in general with regards to callbacks and such.

PM Michael Van Canneyt wrote
Please send it to me, I'll use it as inspiration for changing the existing classes.

Just sent you an email with it, along with a little example applicaton I just made.

To be clear, it *is* the existing classes, with the proper "class external" definitions, but just generic (with a few additions I made here and there.) -------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/pas2js/attachments/20191022/f2933de8/attachment.html>

Reply by email

Michael Van Canneyt
to Ben Grasset
Ben Grasset wrote 18 lines
On Tue, Oct 22, 2019 at 5:21 PM Mattias Gaertner via Pas2js < > wrote: > What do you mean with the "forward-declaration problem with generics"? > It's not an issue with Pas2JS. I just meant the way they work in Pascal in general with regards to callbacks and such. On Tue, Oct 22, 2019 at 5:41 PM Michael Van Canneyt wrote: > Please send it to me, I'll use it as inspiration for changing the existing > classes. Just sent you an email with it, along with a little example applicaton I just made.

Great, thank you !

To be clear, it *is* the existing classes, with the proper "class external" definitions, but just generic (with a few additions I made here and there.)

I had a quick look, it's just what I had in mind. I can insert it almost verbatim, and redefine the existing classes as a specialization with JSValue as a type.

Thank you, this will save me a lot of typing :-)

This weekend I will do the refactoring.
This, together with the support for linking resources, is reason enough to make a new release, even without the fgl and system.generics.* units...

Exciting times :-)

Michael.

Reply by email

warleyalex
to Ben Grasset: On Tue, Oct 22, 2019 at 5:21 PM Mattias Gaertner via Pas2js < It's not an issue with…

class procedure issue in fpc mode.

I would like this code:
---------------------------------------------
type
  generic TGen<T> = record
    class procedure Proc(item: T); static;
  end;
generic class procedure TGen<T>.Proc(item: T);
begin
  //console.log(SizeOf(T));
  if item > 0 then
    WriteLn('Positive')
  else if item < 0 then
    WriteLn('Negative')
  else
    WriteLn('Zero');
end;
---------------------------------------------
begin
  specialize TGen<LongInt>.Proc(0);       // Zero
  specialize TGen<Int64>.Proc(123);       // Positive
  specialize TGen<Extended>.Proc(-11);  // negative
end;

The compiler says: Error: class procedure expected, but procedure found

I think when we inform the "generic" keyword behind the class procedure.

Reply by email

Mattias Gaertner
to warleyalex
Show quoted text 25 lines
class procedure issue in fpc mode. I would like this code: --------------------------------------------- type generic TGen<T> = record class procedure Proc(item: T); static; end; generic class procedure TGen<T>.Proc(item: T); begin //console.log(SizeOf(T)); if item > 0 then WriteLn('Positive') else if item < 0 then WriteLn('Negative') else WriteLn('Zero'); end; --------------------------------------------- begin specialize TGen<LongInt>.Proc(0); // Zero specialize TGen<Int64>.Proc(123); // Positive specialize TGen<Extended>.Proc(-11); // negative end;

This is not ObjFPC syntax. It must be:

type
  generic TGen<T> = record
    class procedure Proc(item: T); static;
  end;
class procedure TGen.Proc(item: T);
begin
 ...
end;

Mattias

Reply by email

Ben Grasset
to Michael Van Canneyt: Great, thank you ! I had a quick look, it's just what I had in mind. I can insert it…
AM Michael Van Canneyt wrote 7 lines
I had a quick look, it's just what I had in mind. I can insert it almost verbatim, and redefine the existing classes as a specialization with JSValue as a type. Thank you, this will save me a lot of typing :-)

No problem!

I did notice one small typo I made, after I had already sent the file. Right now, line 79 (in the definition of TGJSMap) starts like this:

procedure GorEach

but obviously it should start like this:

procedure ForEach
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/pas2js/attachments/20191023/53f46abb/attachment.html>

Reply by email

warleyalex
to Ben Grasset
//--------
type
  generic TKeyValue<T> = class
  private
    FKey: string;
    FValue: T;
    procedure SetKey(const Value: string);
    procedure SetValue(const Value: T);
  //published // // target win64// Error: This kind of property cannot be
published
  public
    property Key : string read FKey write SetKey;
    property Value : T read FValue write SetValue;
  end;
  { TKeyValue<t> }
  generic procedure TKeyValue<T>.SetKey(const Value: string);
  begin
    FKey := Value;
  end;
  generic procedure TKeyValue<T>.SetValue(const Value: T);
  begin
    FValue := Value;
  end;
(...)
var
  KV : specialize TKeyValue<Integer>;
begin
  KV:= specialize TKeyValue<Integer>.Create;
  KV.Key := 'FPC';
  KV.Value := 2;
  writeln('key=', KV.key, ' value=', KV.value);
end;
//---------------------------------------------------------
This code compiler, but when I run, it outputs this:

Uncaught TypeError: o.AfterConstruction is not a function ---> rtl.js:295

If I edit rtl.js and comment 295 line code: // o.AfterConstruction(); and re-compile the project, we have this expected console output: --> key=FPC value=2

Reply by email

Mattias Gaertner
to warleyalex: //-------- type generic TKeyValue<T> = class private FKey: string; FValue: T; procedure…
Show quoted text 39 lines
//-------- type generic TKeyValue<T> = class private FKey: string; FValue: T; procedure SetKey(const Value: string); procedure SetValue(const Value: T); public property Key : string read FKey write SetKey; property Value : T read FValue write SetValue; end; { TKeyValue<t> } generic procedure TKeyValue<T>.SetKey(const Value: string); begin FKey := Value; end; generic procedure TKeyValue<T>.SetValue(const Value: T); begin FValue := Value; end; (...) var KV : specialize TKeyValue<Integer>; begin KV:= specialize TKeyValue<Integer>.Create; KV.Key := 'FPC'; KV.Value := 2; writeln('key=', KV.key, ' value=', KV.value); end; //--------------------------------------------------------- This code compiler, but when I run, it outputs this: Uncaught TypeError: o.AfterConstruction is not a function ---> rtl.js:295

It works here. Are you sure this is the complete example? AfterConstruction is a method of TObject.

Mattias

Reply by email

warleyalex
to Mattias Gaertner

I had a new TOject definition class in somewhere that was causing this "Uncaught TypeError: o.AfterConstruction is not a function ---> rtl.js:295". I deleted this TObject definition and the run as expected.

(*
type
TObject = class

  public
    constructor Create;
  end;

*)
------------------
Another thing is:
I would like to create a procedure, e.g. a list of people, without the use of generics; and another with the use of generics.

---// CODE -----------------
uses
JS, Classes, SysUtils, Web, Types, Math, TypInfo,

  generics.collections, generics.defaults, generics.strings;
  {$mode objfpc}
type
  TPerson = class
  private
    FNome: String;
    procedure SetNome(const Value: String);
  public
    property Nome: String read FNome write SetNome;
  end;
{ TPerson }
procedure TPerson.SetNome(const Value: String);
begin
  FNome := Value;
end;
procedure PersonWithoutGenerics;
var
  LListaPessoa: TList; //--> Error: Generics without specialization cannot
be used as a type for a variable
begin
end;
procedure PersonWithGenerics;
var
  LListaPessoas: specialize TList<TPerson>;
begin
//-----------------
The problem is that the compiler shows:

Error: Generics without specialization cannot be used as a type for a variable

hum, the Generics.Collections unit, we have this definiton: TList<T> = class(TCustomList<T>)
and the classes unit this one: TList = class(TObject)

if I move the "Classes" unit after the "Generics.Collections" at the uses clauses the code compile without errors.

Reply by email

Mattias Gaertner
to warleyalex
Show quoted text 12 lines
I had a new TOject definition class in somewhere that was causing this "Uncaught TypeError: o.AfterConstruction is not a function ---> rtl.js:295". I deleted this TObject definition and the run as expected. (* type TObject = class public constructor Create; end; *)

Yes, and I wrote it works here, please give a complete example.

Mattias

Reply by email

warleyalex
to Mattias Gaertner
// ---- code ---
uses
  JS, {Classes,} SysUtils, Web, Types, Math, TypInfo,
  generics.collections, generics.defaults, generics.strings, Classes;
  {$mode objfpc}
type
  TPerson = class
  private
    FNome: String;
    procedure SetNome(const Value: String);
  public
    property Nome: String read FNome write SetNome;
  end;
{ TPerson }
procedure TPerson.SetNome(const Value: String);
begin
  FNome := Value;
end;
procedure PersonWithoutGenerics;
var
  LListaPessoa: TList; //--> Error: Generics without specialization cannot
be used as a type for a variable
  LPessoa : TPerson;
  LNomePessoa : String;
begin
  LListaPessoa := TList.Create;
  LPessoa      := TPerson.Create;
  try
    LPessoa.Nome := 'Fabio Rubim';
    LListaPessoa.Add(LPessoa);
    LNomePessoa:=  TPerson(LListaPessoa[0]).Nome;
    WriteLn(LNomePessoa);
  finally
    LPessoa.Free;
    LListaPessoa.Free;
  end;
end;
procedure PersonWithGenerics;
var
  LListaPessoas: specialize TList<TPerson>;
  LPessoa : TPerson;
  LNomePessoa : String;
begin
  LListaPessoas := specialize TList<TPerson>.Create;
  LPessoa := TPerson.Create;
  try
    LPessoa.Nome := 'Fabio Rubim';
    LListaPessoas.Add(LPessoa);
    WriteLn(LListaPessoas[0].Nome);
  finally
    LListaPessoas.Free;
  end;
end;
begin
// Your code here
 PersonWithoutGenerics;
 PersonWithGenerics;
end.
----

When I run the project I have the
generics.collections.pas:612 Uncaught TypeError: Cannot set property 'undefined' of undefined

Reply by email

warleyalex
to warleyalex
//---- CODE -----
type
  generic TJSGenArray<T> = Class external name 'Array'
  private
    function GetElements(Index: NativeInt): T; external name '[]';
    procedure SetElements(Index: NativeInt; const AValue: T); external name
'[]';
  public
  type
    TSelfArray = specialize TJSGenArray<T>;
    TSelfTypeEvent = reference to function (element: T; index: NativeInt;
anArray: TSelfArray): Boolean;
    TSelfTypeEventProc = reference to procedure(element: T; index:
NativeInt; anArray: TSelfArray);
    TSelfTypeMapEvent = reference to function (element: T; index: NativeInt;
anArray: TSelfArray): T;
    TSelfTypeReduceEvent = reference to function (accumulator, currentValue:
T; currentIndex: NativeInt; anArray: TSelfArray): T;
    TSelfTypeCompareEvent = reference to function (a,b: T): NativeInt;
    TSelfTypeCallback = TSelfTypeEvent;
    TSelfTypeMapCallback = TSelfTypeMapEvent;
    TSelfTypeReduceCallBack = TSelfTypeReduceEvent;
    TSelfTypeCompareCallBack = TSelfTypeCompareEvent;
  public
    FLength: T; external name 'length';
    constructor new; overload;
    constructor new(aLength: NativeInt); overload;
    constructor new(aElement1: T); varargs; overload;
    class function &of(): TSelfArray; varargs; external name 'of';
    class function isArray(a: T): Boolean;
  {$IFDEF JAVASCRIPT2015}
    class function from(a: T): TSelfType;
    class function from(arrayLike: T; mapFunction: TJSMapFunctionCallBack):
TSelfType; overload;
    class function from(arrayLike: T; mapFunction: TJSMapFunctionCallBack;
thisArg: T): TSelfType; overload;
  {$ENDIF}
    function concat(el: T): TSelfArray; varargs;
    function copyWithin(aTarget: NativeInt): TSelfArray;overload; // not in
IE
    function copyWithin(aTarget, aStart: NativeInt): TSelfArray;overload; //
not in IE
    function copyWithin(aTarget, aStart, aEnd: NativeInt):
TSelfArray;overload; // not in IE
    function entries: TJSIterator;
    Function every(const aCallback: TSelfTypeCallBack): boolean;overload;
    Function every(const aCallback: TSelfTypeEvent; aThis: TObject):
boolean;overload;
    Function filter(const aCallBack: TSelfTypeCallBack): TSelfArray;
overload;
    Function filter(const aCallBack: TSelfTypeEvent; aThis: TObject):
TSelfArray;overload;
    Function fill(aValue: T): TSelfArray; overload;
    Function fill(aValue: T; aStartIndex: NativeInt): TSelfArray; overload;
    Function fill(aValue: T; aStartIndex,aEndIndex: NativeInt): TSelfArray;
overload;
    Function find(const aCallBack: TSelfTypeCallBack): T; overload;
    Function find(const aCallBack: TSelfTypeEvent; aThis: TObject): T;
overload;
    Function findIndex(const aCallBack: TSelfTypeCallBack): NativeInt;
overload;
    Function findIndex(const aCallBack: TSelfTypeEvent; aThis: TObject):
NativeInt; overload;
    procedure forEach(const aCallBack: TSelfTypeEventProc); overload;
    procedure forEach(const aCallBack: TSelfTypeEvent); overload;
    procedure forEach(const aCallBack: TSelfTypeEvent; aThis: TObject);
overload;
    function includes(aElement: T): Boolean; overload;
    function includes(aElement: T; FromIndex: NativeInt): Boolean; overload;
    function indexOf(aElement: T): NativeInt; overload;
    function indexOf(aElement: T; FromIndex: NativeInt): NativeInt;
overload;
    function join: String; overload;
    function join (aSeparator: string): String; overload;
    function keys: TJSIterator;
    function lastIndexOf(aElement: T): NativeInt; overload;
    function lastIndexOf(aElement: T; FromIndex: NativeInt): NativeInt;
overload;
  //    Function map(const aCallBack: TSelfTypeMapEventArray): T; overload;
    Function map(const aCallBack: TSelfTypeMapCallBack): TSelfArray;
overload;
    Function map(const aCallBack: TSelfTypeMapEvent; aThis: TObject):
TSelfArray; overload;
    function pop: T;
    function push(aElement: T): NativeInt; varargs;
    function reduce(const aCallBack: TSelfTypeReduceCallBack): T; overload;
    function reduce(const aCallBack: TSelfTypeReduceCallBack; initialValue:
T): T; overload;
    function reduceRight(const aCallBack: TSelfTypeReduceCallBack): T;
overload;
    function reduceRight(const aCallBack: TSelfTypeReduceCallBack;
initialValue: T): T; overload;
    Function reverse: TSelfArray;
    Function shift: T;
    Function slice: TSelfArray; overload;
    function slice(aBegin: NativeInt): TSelfArray; overload;
    function slice(aBegin,aEnd: NativeInt): TSelfArray; overload;
    Function some(const aCallback: TSelfTypeCallBack): boolean; overload;
    Function some(const aCallback: TSelfTypeEvent; aThis: TObject): boolean;
overload;
    Function sort(const aCallback: TSelfTypeCompareCallBack): TSelfArray;
overload;
    Function sort(): TSelfArray; overload;
    function splice(aStart: NativeInt): TSelfArray; overload;
    function splice(aStart,aDeleteCount: NativeInt): TSelfArray; varargs;
overload;
    function toLocaleString: String; overload;
    function toLocaleString(locales: string): String; overload;
    function toLocaleString(locales: string; const Options:
TLocaleCompareOptions): String; overload;
    function toString: String;
    function unshift: NativeInt; varargs;
    function values: TJSIterator;
    Property Length: T Read FLength Write FLength;
    property Elements[Index: NativeInt]: T read GetElements write
SetElements; default;
  end;
  { forward declarations }
  type
     generic TJSGenTypedArray<T> = Class;
     generic TJSGenArrayBuffer<T> = Class;
     generic TJSGenInt8Array<T> = Class;
  { TJSGenArrayBuffer<T> }
  generic TJSGenArrayBuffer<T> = Class external name 'ArrayBuffer'
  private
    fLength: NativeInt; external name 'byteLength';
  public
    constructor new(aByteLength: NativeInt);
    class function isView(aValue: T): Boolean;
    function slice(aBegin: NativeInt): TJSGenArrayBuffer; overload;
    function slice(aBegin,aEnd: NativeInt): TJSGenArrayBuffer; overload;
    Property byteLength: NativeInt Read fLength;
  end;
  { TJSGenBufferSource<T> }
  generic TJSGenBufferSource<T> = Class external name 'BufferSource'
  type
     TSelfArrayBuffer = specialize TJSGenArrayBuffer<T>;
     TSelfTypedArray = specialize TJSGenTypedArray<T>;
     TSelfInt8Array = specialize TJSGenInt8Array<T>;
  end;
  { TJSGenTypedArray<T> }
  generic TJSGenTypedArray<T> = Class external name 'TypedArray'
(TJSGenBufferSource)
  Private
    FBuffer: TSelfTypedArray; external name 'buffer';
    FByteLength: NativeInt; external name 'byteLength';
    FLength: NativeInt; external name 'length';
    FByteOffset: NativeInt; external name 'byteOffset';
    FBytesPerElement: NativeInt; external name 'BYTES_PER_ELEMENT';
    function getValue(Index: NativeInt): T; external name '[]';
    procedure setValue(Index: NativeInt;AValue: T); external name '[]';
  Public
  type
    TJSGenTypedArrayCallBack = function (element: T; index: NativeInt;
anArray: TSelfTypedArray): Boolean;
    TJSGenTypedArrayEvent = function (element: T; index: NativeInt; anArray:
TSelfTypedArray): Boolean of object;
    TJSGenTypedArrayMapCallBack = function (element: T; index: NativeInt;
anArray: TSelfTypedArray): T;
    TJSGenTypedArrayMapEvent = function (element: T; index: NativeInt;
anArray: TSelfTypedArray): T of object;
    TJSGenTypedArrayReduceCallBack = function (accumulator, currentValue: T;
currentIndex: NativeInt; anArray: TSelfTypedArray): T;
    TJSGenTypedArrayCompareCallBack = function (a,b: T): NativeInt;
    property BYTES_PER_ELEMENT: NativeInt Read FBytesPerElement;
    class var name: string;
//    class function from(aValue: T): TJSGenTypedArray;
//    class function from(aValue: T; Map: TJSGenTypedArrayMapCallBack):
TJSGenTypedArray;
//    class function from(aValue: T; aMap: TJSGenTypedArrayMapEvent):
TJSGenTypedArray;
    class function _of(aValue: T): TJSGenTypedArray; varargs; external name
'of';
    function copyWithin(aTarget: NativeInt): TJSGenTypedArray;overload;
    function copyWithin(aTarget, aStart: NativeInt):
TJSGenTypedArray;overload;
    function copyWithin(aTarget, aStart, aEnd: NativeInt):
TJSGenTypedArray;overload;
    Function every(const aCallback: TJSGenTypedArrayCallBack):
boolean;overload;
    Function every(const aCallback: TJSGenTypedArrayEvent; aThis: TObject):
boolean;overload;
    Function fill(aValue: T): TJSGenTypedArray; overload;
    Function fill(aValue: T; aStartIndex: NativeInt): TJSGenTypedArray;
overload;
    Function fill(aValue: T; aStartIndex,aEndIndex: NativeInt):
TJSGenTypedArray; overload;
    Function filter(const aCallBack: TJSGenTypedArrayCallBack):
TJSGenTypedArray; overload;
    Function filter(const aCallBack: TJSGenTypedArrayEvent; aThis: TObject):
TJSGenTypedArray;overload;
    Function find(const aCallBack: TJSGenTypedArrayCallBack): T; overload;
    Function find(const aCallBack: TJSGenTypedArrayEvent; aThis: TObject):
T; overload;
    Function findIndex(const aCallBack: TJSGenTypedArrayCallBack):
NativeInt; overload;
    Function findIndex(const aCallBack: TJSGenTypedArrayEvent; aThis:
TObject): NativeInt; overload;
    procedure forEach(const aCallBack: TJSGenTypedArrayCallBack); overload;
    procedure forEach(const aCallBack: TJSGenTypedArrayEvent; aThis:
TObject); overload;
    function includes(aElement: T): Boolean; overload;
    function includes(aElement: T; FromIndex: NativeInt): Boolean; overload;
    function indexOf(aElement: T): NativeInt; overload;
    function indexOf(aElement: T; FromIndex: NativeInt): NativeInt;
overload;
    function join: String; overload;
    function join (aSeparator: string): String; overload;
    function lastIndexOf(aElement: T): NativeInt; overload;
    function lastIndexOf(aElement: T; FromIndex: NativeInt): NativeInt;
overload;
    Function map(const aCallBack: TJSGenTypedArrayCallBack):
TJSGenTypedArray; overload;
    Function map(const aCallBack: TJSGenTypedArrayEvent; aThis: TObject):
TJSGenTypedArray; overload;
    function reduce(const aCallBack: TJSGenTypedArrayReduceCallBack): T;
overload;
    function reduce(const aCallBack: TJSGenTypedArrayReduceCallBack;
initialValue: T): T; overload;
    function reduceRight(const aCallBack: TJSGenTypedArrayReduceCallBack):
T; overload;
    function reduceRight(const aCallBack: TJSGenTypedArrayReduceCallBack;
initialValue: T): T; overload;
    Function reverse: TJSGenTypedArray;
    procedure _set(anArray: TJSArray); external name 'set';
    procedure _set(anArray: TJSArray; anOffset: NativeInt); external name
'set';
    procedure _set(anArray: TJSGenTypedArray); external name 'set';
    procedure _set(anArray: TJSGenTypedArray; anOffset: NativeInt); external
name 'set';
    Function slice: TJSGenTypedArray; overload;
    function slice(aBegin: NativeInt): TJSGenTypedArray; overload;
    function slice(aBegin,aEnd: NativeInt): TJSGenTypedArray; overload;
    Function some(const aCallback: TJSGenTypedArrayCallBack): boolean;
overload;
    Function some(const aCallback: TJSGenTypedArrayEvent; aThis: TObject):
boolean; overload;
    Function sort(const aCallback: TJSGenTypedArrayCompareCallBack):
TJSGenTypedArray; overload;
    Function sort(): TJSGenTypedArray; overload;
    function splice(aStart: NativeInt): TJSGenTypedArray; overload;
    function splice(aStart,aDeleteCount: NativeInt): TJSGenTypedArray;
varargs; overload;
    function toLocaleString: String; overload;
    function toLocaleString(locales: string): String; overload;
    function toLocaleString(locales: string; const Options:
TLocaleCompareOptions): String; overload;
    function toString: String;
    function unshift: NativeInt; varargs;
    property buffer: TSelfTypedArray read FBuffer;
    property byteLength: NativeInt Read FByteLength;
    property byteOffset: NativeInt Read FByteOffset;
    property length: NativeInt Read FLength;
    property values[Index: NativeInt]: T Read getValue Write SetValue;
default;
  end;
  { TJSGenInt8Array<T> }
  generic TJSGenInt8Array<T> = Class external name 'Int8Array'
(TJSGenTypedArray)
  private
    function getTypedValue(Index: NativeInt): Shortint; external name '[]';
    procedure setTypedValue(Index: NativeInt; AValue: Shortint);external
name '[]';
  public
{$IFDEF JAVASCRIPT2017}
    constructor new; // new in ES2017
{$ENDIF}
    constructor new (length: NativeInt);
    constructor new (atypedArray: TSelfTypedArray);
    constructor new (aObject: TJSObject);
    constructor new (buffer: TSelfArrayBuffer);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset: NativeInt);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset, aLength:
NativeInt);
    class function from(aValue: T): TSelfInt8Array; reintroduce;
    class function from(aValue: T; Map: TJSGenTypedArrayMapCallBack):
TSelfInt8Array; reintroduce;
    class function from(aValue: T; aMap: TJSGenTypedArrayMapEvent):
TSelfInt8Array; reintroduce;
    class function _of(aValue: T): TSelfInt8Array; varargs; external name
'of'; reintroduce;overload;
    class function _of(aValue: TJSValueDynArray): TSelfInt8Array; varargs;
external name 'of'; reintroduce; overload;
    function subarray(aBegin, aEnd: Integer): TSelfInt8Array;  overload;
    function subarray(aBegin: Integer): TSelfInt8Array; overload;
    procedure _set(anArray: Array of ShortInt); external name 'set';
reintroduce; overload;
    procedure _set(anArray: Array of ShortInt; anOffset: NativeInt);
external name 'set';
    property values[Index: NativeInt]: Shortint Read getTypedValue Write
setTypedValue; default;
  end;
  { TJSGenUint8Array<T> }
  generic TJSGenUint8Array <T> = Class external name 'Uint8Array'
(TJSGenTypedArray)
  private
    function getTypedValue(Index: NativeInt): Byte; external name '[]';
    procedure setTypedValue(Index: NativeInt; AValue: Byte);external name
'[]';
  public
    constructor new (length: NativeInt);
    constructor new (atypedArray: TSelfTypedArray);
    constructor new (aObject: TJSObject);
    constructor new (buffer: TSelfArrayBuffer);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset: NativeInt);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset, aLength:
NativeInt);
    class function from(aValue: T): TJSGenUint8Array; reintroduce; overload;
    class function from(aValue: T; Map: TJSGenTypedArrayMapCallBack):
TJSGenUint8Array; reintroduce;overload;
    class function from(aValue: T; aMap: TJSGenTypedArrayMapEvent):
TJSGenUint8Array; reintroduce;overload;
    class function _of(aValue: T): TJSGenUint8Array; varargs; external name
'of'; reintroduce; overload;
    function subarray(aBegin, aEnd: Integer): TJSGenUint8Array;  overload;
    function subarray(aBegin: Integer): TJSGenUint8Array; overload;
    procedure _set(anArray: Array of Byte); external name 'set';
reintroduce; overload;
    procedure _set(anArray: Array of Byte; anOffset: NativeInt); external
name 'set'; overload;
    Property values[Index: NativeInt]: Byte Read getTypedValue Write
setTypedValue; default;
  end;
  { TJSGenUint8ClampedArray<T> }
  generic TJSGenUint8ClampedArray <T> = Class external name
'Uint8ClampedArray' (TJSGenTypedArray)
  private
    function getTypedValue(Index: NativeInt): Byte; external name '[]';
    procedure setTypedValue(Index: NativeInt; AValue: Byte);external name
'[]';
  public
    constructor new (length: NativeInt);
    constructor new (atypedArray: TSelfTypedArray);
    constructor new (aObject: TJSObject);
    constructor new (buffer: TSelfArrayBuffer);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset: NativeInt);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset, aLength:
NativeInt);
    class function from(aValue: T): TJSGenUint8ClampedArray; reintroduce;
    class function from(aValue: T; Map: TJSGenTypedArrayMapCallBack):
TJSGenUint8ClampedArray; reintroduce;overload;
    class function from(aValue: T; aMap: TJSGenTypedArrayMapEvent):
TJSGenUint8ClampedArray; reintroduce;overload;
    class function _of(aValue: T): TJSGenUint8ClampedArray; varargs;
external name 'of'; reintroduce;overload;
    procedure _set(anArray: Array of Byte); external name 'set';
reintroduce;overload;
    procedure _set(anArray: Array of Byte; anOffset: NativeInt); external
name 'set';overload;
    function subarray(aBegin, aEnd: Integer): TJSGenUint8ClampedArray;
overload;
    function subarray(aBegin: Integer): TJSGenUint8ClampedArray; overload;
    Property values[Index: NativeInt]: Byte Read getTypedValue Write
setTypedValue; default;
  end;
  { TJGenSInt16Array<T> }
  generic TJGenSInt16Array<T> = Class external name 'Int16Array'
(TJSGenTypedArray)
  private
    function getTypedValue(Index: NativeInt): smallint; external name '[]';
    procedure setTypedValue(Index: NativeInt; AValue: Smallint);external
name '[]';
  public
    constructor new (length: NativeInt);
    constructor new (atypedArray: TSelfTypedArray);
    constructor new (aObject: TJSObject);
    constructor new (buffer: TSelfArrayBuffer);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset: NativeInt);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset, aLength:
NativeInt);
    class function from(aValue: T): TJGenSInt16Array; reintroduce;
    class function from(aValue: T; Map: TJSGenTypedArrayMapCallBack):
TJGenSInt16Array; reintroduce;overload;
    class function from(aValue: T; aMap: TJSGenTypedArrayMapEvent):
TJGenSInt16Array; reintroduce;overload;
    class function _of(aValue: T): TJGenSInt16Array; varargs; external name
'of'; reintroduce;overload;
    procedure _set(anArray: Array of SmallInt); external name 'set';
reintroduce;overload;
    procedure _set(anArray: Array of SmallInt; anOffset: NativeInt);
external name 'set';overload;
    function subarray(aBegin, aEnd: Integer): TJGenSInt16Array;  overload;
    function subarray(aBegin: Integer): TJGenSInt16Array; overload;
    Property values[Index: NativeInt]: SmallInt Read getTypedValue Write
setTypedValue; default;
  end;
  { TJSGenUint16Array<T> }
  generic TJSGenUint16Array<T> = Class external name 'Uint16Array'
(TJSGenTypedArray)
  private
    function getTypedValue(Index: NativeInt): Word; external name '[]';
    procedure setTypedValue(Index: NativeInt; AValue: Word);external name
'[]';
  public
    constructor new (length: NativeInt);
    constructor new (atypedArray: TSelfTypedArray);
    constructor new (aObject: TJSObject);
    constructor new (buffer: TSelfArrayBuffer);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset: NativeInt);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset, aLength:
NativeInt);
    class function from(aValue: T): TJSGenUint16Array; reintroduce;
    class function from(aValue: T; Map: TJSGenTypedArrayMapCallBack):
TJSGenUint16Array; reintroduce;
    class function from(aValue: T; aMap: TJSGenTypedArrayMapEvent):
TJSGenUint16Array; reintroduce;
    class function _of(aValue: T): TJSGenUint16Array; varargs; external name
'of'; reintroduce;
    procedure _set(anArray: Array of Word); external name 'set';
reintroduce;
    procedure _set(anArray: Array of Word; anOffset: NativeInt); external
name 'set';
    function subarray(aBegin, aEnd: Integer): TJSGenUint16Array;  overload;
    function subarray(aBegin: Integer): TJSGenUint16Array; overload;
    Property values[Index: NativeInt]: Word Read getTypedValue Write
setTypedValue; default;
  end;
  { TJSGenInt32Array<T> }
  generic TJSGenInt32Array<T> = Class external name 'Int32Array'
(TJSGenTypedArray)
  private
    function getTypedValue(Index: NativeInt): longint; external name '[]';
    procedure setTypedValue(Index: NativeInt; AValue: longint);external name
'[]';
  public
    constructor new (length: NativeInt);
    constructor new (atypedArray: TSelfTypedArray);
    constructor new (aObject: TJSObject);
    constructor new (buffer: TSelfArrayBuffer);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset: NativeInt);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset, aLength:
NativeInt);
    class function from(aValue: T): TJSGenInt32Array; reintroduce;
    class function from(aValue: T; Map: TJSGenTypedArrayMapCallBack):
TJSGenInt32Array; reintroduce;
    class function from(aValue: T; aMap: TJSGenTypedArrayMapEvent):
TJSGenInt32Array; reintroduce;
    class function _of(aValue: T): TJSGenInt32Array; varargs;external name
'of'; reintroduce;
    procedure _set(anArray: Array of LongInt); external name 'set';
reintroduce;
    procedure _set(anArray: Array of LongInt; anOffset: NativeInt); external
name 'set';
    function subarray(aBegin, aEnd: Integer): TJSGenInt32Array;  overload;
    function subarray(aBegin: Integer): TJSGenInt32Array; overload;
    Property values[Index: NativeInt]: longint Read getTypedValue Write
setTypedValue; default;
  end;
  { TJSGenUint32Array<T> }
  generic TJSGenUint32Array<T> = Class external name 'Uint32Array'
(TJSGenTypedArray)
  private
    function getTypedValue(Index: NativeInt): LongWord; external name '[]';
    procedure setTypedValue(Index: NativeInt; AValue: LongWord);external
name '[]';
  public
    constructor new (length: NativeInt);
    constructor new (atypedArray: TSelfTypedArray);
    constructor new (aObject: TJSObject);
    constructor new (buffer: TSelfArrayBuffer);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset: NativeInt);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset, aLength:
NativeInt);
    class function from(aValue: T): TJSGenUint32Array; reintroduce;
    class function from(aValue: T; Map: TJSGenTypedArrayMapCallBack):
TJSGenUint32Array; reintroduce;
    class function from(aValue: T; aMap: TJSGenTypedArrayMapEvent):
TJSGenUint32Array; reintroduce;
    class function _of(aValue: T): TJSGenUint32Array; varargs; external name
'of'; reintroduce;
    procedure _set(anArray: Array of Cardinal); external name 'set';
reintroduce;
    procedure _set(anArray: Array of Cardinal; anOffset: NativeInt);
external name 'set';
    function subarray(aBegin, aEnd: Integer): TJSGenUint32Array;  overload;
    function subarray(aBegin: Integer): TJSGenUint32Array; overload;
    Property values[Index: NativeInt]: LongWord Read getTypedValue Write
setTypedValue; default;
  end;
  { TJSGenFloat32Array<T> }
  generic TJSGenFloat32Array<T> = Class external name 'Float32Array'
(TJSGenTypedArray)
  private
    function getTypedValue(Index: NativeInt): Float32; external name '[]';
    procedure setTypedValue(Index: NativeInt; AValue: Float32);external name
'[]';
  public
    constructor new (length: NativeInt);
    constructor new (atypedArray: TSelfTypedArray);
    constructor new (aObject: TJSObject);
    constructor new (buffer: TSelfArrayBuffer);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset: NativeInt);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset, aLength:
NativeInt);
    class function from(aValue: T): TJSGenFloat32Array; reintroduce;
    class function from(aValue: T; Map: TJSGenTypedArrayMapCallBack):
TJSGenFloat32Array; reintroduce;
    class function from(aValue: T; aMap: TJSGenTypedArrayMapEvent):
TJSGenFloat32Array; reintroduce;
    class function _of(aValue: T): TJSGenFloat32Array; varargs; reintroduce;
    procedure _set(anArray: Array of Double); external name 'set';
reintroduce;
    procedure _set(anArray: Array of Double; anOffset: NativeInt); external
name 'set'; reintroduce;
    function subarray(aBegin, aEnd: Integer): TJSGenFloat32Array;  overload;
    function subarray(aBegin: Integer): TJSGenFloat32Array; overload;
    Property values[Index: NativeInt]: Float32 Read getTypedValue Write
setTypedValue; default;
  end;
  { TJSGenFloat64Array<T> }
  generic TJSGenFloat64Array<T> = Class external name 'Float64Array'
(TJSGenTypedArray)
  private
    function getTypedValue(Index: NativeInt): Float64; external name '[]';
    procedure setTypedValue(Index: NativeInt; AValue: Float64);external name
'[]';
  public
    constructor new (length: NativeInt);
    constructor new (atypedArray: TSelfTypedArray);
    constructor new (aObject: TJSObject);
    constructor new (buffer: TSelfArrayBuffer);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset: NativeInt);
    constructor new (buffer: TSelfArrayBuffer; aByteOffset, aLength:
NativeInt);
    class function from(aValue: T): TJSGenFloat64Array; reintroduce;
    class function from(aValue: T; Map: TJSGenTypedArrayMapCallBack):
TJSGenFloat64Array; reintroduce;
    class function from(aValue: T; aMap: TJSGenTypedArrayMapEvent):
TJSGenFloat64Array; reintroduce;
    class function _of(aValue: T): TJSGenFloat64Array; varargs; reintroduce;
    procedure _set(anArray: Array of Double); external name 'set';
reintroduce;
    procedure _set(anArray: Array of Double; anOffset: NativeInt); external
name 'set'; reintroduce;
    function subarray(aBegin, aEnd: Integer): TJSGenFloat64Array;  overload;
    function subarray(aBegin: Integer): TJSGenFloat64Array; overload;
    Property values[Index: NativeInt]: Float64 Read getTypedValue Write
setTypedValue; default;
  end;
  { TJSGenDataView<T> }
  generic TJSGenDataView<T> = Class external name 'DataView'
(TJSGenBufferSource)
  private
    fBuffer: TSelfArrayBuffer; external name 'buffer';
    fLength: NativeInt; external name 'byteLength';
    fOffset: NativeInt; external name 'byteOffset';
  public
    constructor new(aBuffer: TSelfArrayBuffer); overload;
    constructor new(aBuffer: TSelfArrayBuffer; aOffset: NativeInt);
overload;
    constructor new(aBuffer: TSelfArrayBuffer; aOffset,aByteLength:
NativeInt); overload;
    function getFloat32(aByteOffset: NativeInt): double; overload;
    function getFloat32(aByteOffset: NativeInt; aLittleEndian: Boolean):
double; overload;
    function getFloat64(aByteOffset: NativeInt): double; overload;
    function getFloat64(aByteOffset: NativeInt; aLittleEndian: Boolean):
double; overload;
    function getInt8(aByteOffset: NativeInt): ShortInt;
    function getInt16(aByteOffset: NativeInt): SmallInt; overload;
    function getInt16(aByteOffset: NativeInt; aLittleEndian: Boolean):
SmallInt; overload;
    function getInt32(aByteOffset: NativeInt): Longint; overload;
    function getInt32(aByteOffset: NativeInt; aLittleEndian: Boolean):
Longint; overload;
    function getUint8(aByteOffset: NativeInt): Byte; overload;
    function getUint16(aByteOffset: NativeInt): Word; overload;
    function getUint16(aByteOffset: NativeInt; aLittleEndian: Boolean):
Word; overload;
    function getUint32(aByteOffset: NativeInt): LongWord; overload;
    function getUint32(aByteOffset: NativeInt; aLittleEndian: Boolean):
LongWord; overload;
    procedure setFloat32(aByteOffset: NativeInt; aValue: double); overload;
    procedure setFloat32(aByteOffset: NativeInt; aValue: double;
aLittleEndian: Boolean); overload;
    procedure setFloat64(aByteOffset: NativeInt; aValue: double); overload;
    procedure setFloat64(aByteOffset: NativeInt; aValue: double;
aLittleEndian: Boolean); overload;
    procedure setInt8(aByteOffset: NativeInt; aValue: ShortInt);
    procedure setInt16(aByteOffset: NativeInt; aValue: SmallInt); overload;
    procedure setInt16(aByteOffset: NativeInt; aValue: SmallInt;
aLittleEndian: Boolean); overload;
    procedure setInt32(aByteOffset: NativeInt; aValue: Longint); overload;
    procedure setInt32(aByteOffset: NativeInt; aValue: Longint;
aLittleEndian: Boolean); overload;
    procedure setUint8(aByteOffset: NativeInt; aValue: Byte); overload;
    procedure setUint16(aByteOffset: NativeInt; aValue: Word); overload;
    procedure setUint16(aByteOffset: NativeInt; aValue: Word; aLittleEndian:
Boolean); overload;
    procedure setUint32(aByteOffset: NativeInt; aValue: LongWord); overload;
    procedure setUint32(aByteOffset: NativeInt; aValue: LongWord;
aLittleEndian: Boolean); overload;
    Property byteLength: NativeInt Read fLength;
    Property byteOffset: NativeInt read fOffset;
    property buffer: TSelfArrayBuffer Read fBuffer;
  end;
//---- END ------

I sincerely don't see the pros, if it's worthy to implement generic external classes like this one.

Reply by email

Mattias Gaertner
to warleyalex: class procedure issue in fpc mode. I would like this code:…
warleyalex wrote 27 lines
class procedure issue in fpc mode. I would like this code: --------------------------------------------- type generic TGen<T> = record class procedure Proc(item: T); static; end; generic class procedure TGen<T>.Proc(item: T); begin //console.log(SizeOf(T)); if item > 0 then WriteLn('Positive') else if item < 0 then WriteLn('Negative') else WriteLn('Zero'); end; --------------------------------------------- begin specialize TGen<LongInt>.Proc(0); // Zero specialize TGen<Int64>.Proc(123); // Positive specialize TGen<Extended>.Proc(-11); // negative end; The compiler says: Error: class procedure expected, but procedure found

Fixed in trunk.

Mattias

Reply by email

Mattias Gaertner
to warleyalex: I had a new TOject definition class in somewhere that was causing this "Uncaught…
warleyalex wrote 44 lines
Another thing is: I would like to create a procedure, e.g. a list of people, without the use of generics; and another with the use of generics. ---// CODE ----------------- uses JS, Classes, SysUtils, Web, Types, Math, TypInfo, generics.collections, generics.defaults, generics.strings; {$mode objfpc} type TPerson = class private FNome: String; procedure SetNome(const Value: String); public property Nome: String read FNome write SetNome; end; { TPerson } procedure TPerson.SetNome(const Value: String); begin FNome := Value; end; procedure PersonWithoutGenerics; var LListaPessoa: TList; //--> Error: Generics without specialization cannot be used as a type for a variable begin end; procedure PersonWithGenerics; var LListaPessoas: specialize TList<TPerson>; begin //----------------- The problem is that the compiler shows: Error: Generics without specialization cannot be used as a type for a variable

Fixed.

Mattias

Reply by email

Mattias Gaertner
to warleyalex: // ---- code --- uses JS, {Classes,} SysUtils, Web, Types, Math, TypInfo,…
warleyalex wrote 71 lines
// ---- code --- uses JS, {Classes,} SysUtils, Web, Types, Math, TypInfo, generics.collections, generics.defaults, generics.strings, Classes; {$mode objfpc} type TPerson = class private FNome: String; procedure SetNome(const Value: String); public property Nome: String read FNome write SetNome; end; { TPerson } procedure TPerson.SetNome(const Value: String); begin FNome := Value; end; procedure PersonWithoutGenerics; var LListaPessoa: TList; //--> Error: Generics without specialization cannot be used as a type for a variable LPessoa : TPerson; LNomePessoa : String; begin LListaPessoa := TList.Create; LPessoa := TPerson.Create; try LPessoa.Nome := 'Fabio Rubim'; LListaPessoa.Add(LPessoa); LNomePessoa:= TPerson(LListaPessoa[0]).Nome; WriteLn(LNomePessoa); finally LPessoa.Free; LListaPessoa.Free; end; end; procedure PersonWithGenerics; var LListaPessoas: specialize TList<TPerson>; LPessoa : TPerson; LNomePessoa : String; begin LListaPessoas := specialize TList<TPerson>.Create; LPessoa := TPerson.Create; try LPessoa.Nome := 'Fabio Rubim'; LListaPessoas.Add(LPessoa); WriteLn(LListaPessoas[0].Nome); finally LListaPessoas.Free; end; end; begin // Your code here PersonWithoutGenerics; PersonWithGenerics; end. ---- When I run the project I have the generics.collections.pas:612 Uncaught TypeError: Cannot set property 'undefined' of undefined

Fixed

Mattias

Reply by email