[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