[Pas2js] My 1st type helper

warleyalex warleyalex at yahoo.com.br
Mon Mar 4 00:51:53 CET 2019


Ref: Pas2JS Compiler version 1.4.0RC4 [2019/03/03] for Win32 i386
==================================================
Test I:
==================================================
type
 float = double;

type
 TFloatHelper  =  type helper for Float
   const NPI = 3.141592;
   function ToStr: String;
 end;    

function  TFloatHelper.ToStr: String;
begin
  Result:=  FloatToStr(Self);
end;

(...)
var
  ReturnValue : Float;
begin
  ReturnValue := 2.71;
  ReturnValue:= (ReturnValue * Float.NPI);                
  console.log(ReturnValue.ToStr);   //8.51371432 it works for me.

a) but we can't use it straightforward like 
//  console.log((ReturnValue * ReturnValue.NPI).ToStr);    //8.51371432 


==================================================
Test II:
==================================================
type 
  TMyClass = class 
    procedure MyProc; 
    function MyFunc: Integer; 
  end; 

type 
  TMyClassHelper = class helper for TMyClass 
    procedure HelloWorld; 
    function MyFunc: Integer; 
  end; 

implementation 

procedure TMyClass.MyProc; 
var 
 X: Integer; 
begin 
  X := MyFunc; 
end; 

function TMyClass.MyFunc: Integer; 
begin 
  WriteLn('TMyClass.MyFunc called'); 
end; 

procedure TMyClassHelper.HelloWorld; 
begin 
  Writeln(Self.ClassName); // Self refers to TMyClass type, not 
TMyClassHelper 
end; 

function TMyClassHelper.MyFunc: Integer;
begin
//  inherited;
  WriteLn('TMyClassHelper.MyFunc called');
end;  

(...) 

var 
  X: TMyClass; 
begin 
  X := TMyClass.Create; 
  X.MyProc;     // Calls TMyClass.MyProc 
  X.HelloWorld; // Calls TMyClassHelper.HelloWorld 
  X.MyFunc;     // Calls TMyClassHelper.MyFunc 
---------------------------------- 
the console output is: 
(* 
  TMyClassHelper.MyFunc called
  TMyClass 
  TMyClassHelper.MyFunc called 
*) 

a) if I declare the method "MyFunc" with the keyword "inherited"

function TMyClassHelper.MyFunc: Integer;
begin
  inherited;
  WriteLn('TMyClassHelper.MyFunc called');
end;  

the console is: 
(* 
  TMyClass.MyFunc called
  TMyClassHelper.MyFunc called
  TMyClass
  TMyClass.MyFunc called
  TMyClassHelper.MyFunc called
*)

b) I would like to call TMyClass.MyProc method, but there's an active helper
with the method MyProc.

  X := TMyClass.Create; 
  X.MyProc;     // Calls TMyClass.MyProc

Hum, this is correct! it will show the console "TMyClassHelper.MyFunc
called" instead of  "TMyClass.MyProc called" just because the class helper
takes precedence over the actual class type.

==================================================
Test III: class helper how old are you?
==================================================
  { TPessoa class }
  type
    TPessoa = class
    private
      FDataNasc: TDateTime;
    public
      property DataNasc: TDateTime read FDataNasc write FDataNasc;
    end;

    TPessoaHelper = class helper for TPessoa
      private
        function GetIdade: integer;
      public
      property Idade: integer read GetIdade;
    end;

    TIntHelper = type helper for Integer
    public
      function ToStr: String;
    end;

implementation

{YearsBetween function}
function SpanOfNowAndThen(const ANow, AThen: Float): Float;
begin
  if ANow < AThen then
    Result := AThen - ANow
  else
    Result := ANow - AThen;
end;

function DaySpan(const ANow, AThen: Float): Float;
begin
  Result := SpanOfNowAndThen(ANow, AThen);
end;

function YearSpan(const ANow, AThen: Float): Float;
begin
  Result := DaySpan(ANow, AThen) / 365.25;
end;

function YearsBetween(const ANow, AThen: Float): Integer;
begin
  Result := Trunc(YearSpan(ANow, AThen));
end;

{ TPessoaHelper }
function TPessoaHelper.GetIdade: integer;
begin
  Result := YearsBetween(Self.DataNasc, Now);
end;

{ TIntHelper }
function TIntHelper.ToStr: String;
begin
  Result := IntToStr(Self);
end;


(...)
  oPessoa := TPessoa.Create;
  try
    oPessoa.DataNasc := EncodeDate(1986, 11, 26);
    console.log(
      (oPessoa.Idade).ToStr + ' years'
    );
  finally
    oPessoa.Free;
  end;   

a) that we are using ToStr function instead of IntToStr. I see the console
"32 years", which is the expected! Today - BirthDate = 32

==================================================
Test IV: Multiple class helper (multihelpers) are supported
==================================================
We add 2 more helpers in the Test III:

  TPessoaFisicaHelper = class helper (TPessoaHelper) for TPessoa
    public
      function isValidCPF():Boolean;
  end;

  TPessoaJuridicaHelper = class helper (TPessoaFisicaHelper) for TPessoa
    public
      function isValidCNPJ():Boolean;
  end;

implementation

{ TPessoaFisicaHelper }
function TPessoaFisicaHelper.isValidCPF(): Boolean;
begin
 WriteLn('CPF is valid');
end;

{ TPessoaJuridicaHelper }
function TPessoaJuridicaHelper.isValidCNPJ(): Boolean;
begin
 WriteLn('CNPJ is valid');
end;

(...)
  oPessoa := TPessoa.Create;
  try
    oPessoa.DataNasc := EncodeDate(1986, 11, 26);
    console.log(
      (oPessoa.Idade).ToStr + ' years'
    );
    txt :=  (oPessoa.Idade).ToStr;
    console.log(txt);
    oPessoa.isValidCPF;
    oPessoa.isValidCNPJ;

  finally
    oPessoa.Free;
  end;  

we have the expected console:
(*
  32 years
  32
  CPF is valid
  CNPJ is valid
*)

We can not use the following syntax, when defining TPessoaFisicaHelper
helper, for instance:
  TPessoaFisicaHelper = class helper for TPessoa

I'm getting this msg: 
  Error: identifier not found "Idade"

to disappear this error, we have to define this way:
  TPessoaFisicaHelper = class helper (TPessoaHelper) for TPessoa
       and
  TPessoaJuridicaHelper = class helper (TPessoaFisicaHelper) for TPessoa

That is, MORE THAN ONE class helper for a given class may be in scope at any
time. For instance, if you have two helpers in scope, ALL OF THEM will be
recognised by the compiler. 

==================================================
Test V: Helpers on functions pointers are not supported.
==================================================
type
   TFunc = function: Integer;

   { TIntegerHelper }
    TIntegerHelper = type helper (TIntHelper) for Integer
       function ToString : String;
    end;

implementation

{ TIntegerHelper }
function TIntegerHelper.ToString: String;
begin
  Result := IntToStr(Self);
end;

(*
  { TFuncHelper }
  function TFuncHelper.ToString: String;
  begin
    Result := IntToStr(Self);
  end;  
*)

We can not define a helper like this:

   { TFuncHelper }
   (*
   TFuncHelper = type helper for TFunc // this is not allowed
       function ToString : String;
    end;
    *)

You've got this msg:
Error: Type "TFunc" cannot be extended by a type helper. 
so Helper on function pointer are not supported.

(...)

function twenty: Integer;
begin
  Result := 20;
end;

var
  f: TFunc;
begin
  f:= @twenty;

  console.log(
    f.ToString   
  );

the console is "20". Correct!

if we comment this line f:= @twenty;
Uncaught TypeError: $mod.f is not a function // this is correct.

==================================================
Test VI
==================================================
type
   Vec2  =  array  [0..1]  of  Float;

type
   TVec2Helper  =  type helper  for  Vec2
     function  Add(const  v:  Vec2):  Vec2;  overload;
     function  Add(const  f:  Float):  Vec2;  overload;
   end;

implementation

{ TVec2Helper }
function  TVec2Helper.Add(const  v  :  Vec2):  Vec2;
begin
  Result:=[Self[0]+v[0],  Self[1]+v[1]];
end;

function  TVec2Helper.Add(const  f  :  Float):  Vec2;
begin
  Result:=[Self[0]+f,  Self[1]+f];
end;   

(...)
var
  v1:  Vec2  =  (1,  2);
  v2:  Vec2  =  (10,  20);
  v: array of  Float;

begin
  v1 :=  [1,  2];
  v2 :=  [10,  20];

  //v  :=  v1  +  v2;    // Error: Operator is not overloaded: "Unit3.Vec2"
+ "Unit3.Vec2"

  v:=[v1[0]+v2[0],  v1[1]+v2[1]];

  WriteLn(v[0]); // 11
  WriteLn(v[1]); // 22

In this test, I'd like to test helper methods with operator overloading, but
it's not supported yet.
==================================================

==================================================
Test VII - helper class to TJSObject
==================================================
{ TJSValueHelper }

TJSValueHelper = type helper for TJSObject
  public
    function valid(ref: JSValue): boolean; assembler;
end;

var
  this: TJSObject; external name 'this';

implementation

{ TJSValueHelper }
function TJSValueHelper.valid(ref: JSValue): boolean; assembler;
asm
  return !( (ref == undefined) || (ref == null) );
end;  

(...)
var
dt : TDateTime;

begin
  dt := TDateTime(now);
  if this.valid(dt) then
    console.log(DateTimetoStr(dt)) else  // 2019-03-03 18:16:49
      dt := 0;
      console.log(dt);  

I think this very useful function!  and it works for me.

**Note: I think we have a bug here at "dt: TDateTime" initialization!
for instance: If I comment

 //dt := TDateTime(now);
  if this.valid(dt) then
    console.log(DateTimetoStr(dt)) else  
    //dt := 0;
    console.log(dt); 

the console outputs "1899-12-30" - I think the correct is "0"

==================================================
Test VIII - helper for array of record
==================================================
type
  TFunction = function: TJSPromise;

type
  TModelClassRegistration = record
    TableName: string;
    CreateFunc: TFunction;
  end;

type
  TModelClassRegistrations = array of TModelClassRegistration;

  { TTestHelper }
  TTestHelper = type helper for TModelClassRegistrations
    procedure Add(rec: TModelClassRegistration);
  end;

implementation

{ TTestHelper }
procedure TTestHelper.Add(rec: TModelClassRegistration);
begin
  TJSArray(Self).push(rec);
end;

(...)

function CreateServer: TJSPromise;
begin
result:=
  TJSPromise.New(
  procedure (resolve, reject: TJSPromiseResolver)
  begin
    console.log('test');
  end);
end;   

var
  rec: TModelClassRegistration;
  RegisteredModelClasses: TModelClassRegistrations;
  i: integer;                  

begin
  rec.TableName := 'devil_report';
  rec.CreateFunc := @CreateServer;
  RegisteredModelClasses.Add(rec);
  rec.TableName:= 'flowers_report';
  rec.CreateFunc := @CreateServer;
  RegisteredModelClasses.Add(rec);
  rec.TableName := 'cards_report';
  rec.CreateFunc := @CreateServer;
  RegisteredModelClasses.Add(rec);

  for i:= Low(RegisteredModelClasses) to High(RegisteredModelClasses) do
    console.log(RegisteredModelClasses[i])

We have the expected object output.
--------------------------------------------------------------------------------
regards,
warleyalex



--
Sent from: http://pas2js.38893.n8.nabble.com/


More information about the Pas2js mailing list