paxCompiler Importer


importe.jpg

paxCompiler importer (paxImp.exe) is a freeware program that generates import units from source code units of your application, so all members defined in your application become accessible for your paxCompiler scripts. You can create import files for all Delphi versions starting with Delphi 5 (D5-XE7).

(Click here to download the importer).

paxCompiler importer works in 2 modes.

AnsiChars option permits you to create import files for old Delphi versions which does not support UnicodeStrings. You can assign directives of conditional compilation to importer to provide proper parsing of source units. You can also introduce some restrictions on list of source files to help importer to select suitable files from the list.

Demo

Let's consider how it works on a very simple demo. Let's suppose we have a source code unit MyUnit.pas:

unit MyUnit;
interface
uses
  Classes;
const
  Comm = '\\';
type
  TLang = (wEnglish, wFrench, wAll);
  TMyClass = class(TStringList)
  public
    procedure CountWords(const Pattern: String; Lang: TLang);
  end;
  function Deliver(C: Integer): Boolean;
var
  LastCount: Integer;
implementation
..........................

Mode 1 - global import

Applying importer to 2 files System.Classes.pas and MyUnit.pas we get 3 output files IMP_System.Classes.pas, IMP_MyUnit.pas and IMPORT_Common.pas. The IMPORT_Common.pas content is:

unit IMPORT_Common;
interface
procedure Register_Common;
implementation
uses
  IMP_System.Classes,
  IMP_MyUnit;
procedure Register_Common;
begin
  Register_System_Classes;
  Register_MyUnit;
end;
end.

All members of System.Classes.pas and MyUnit.pas are available for your application via content of IMP_System.Classes.pas and IMP_MyUnit.pas.

IMP_MyUnit.pas has view:

unit IMP_MyUnit;
interface

function Register_MyUnit: Integer;

implementation

uses
  PAXCOMP_STDLIB,
  PaxRegister,
  System.Classes,
  MyUnit;

// procedure CountWords(const Pattern: String; Lang: TLang);
function RegisterMethodProcedure_TMyClass_CountWords(H: Integer): Integer;
begin
  result := RegisterMethod(H, 'CountWords'
    , _typeVOID // result type
    , @ TMyClass.CountWords // address
    );
  RegisterParameter(result, 'Pattern', _typeUNICSTRING, _parCONST);
  RegisterParameter(result, 'Lang', 'TLang', _parVAL);
end;

function RegisterConstant_Comm(H: Integer): Integer;
begin
  result := RegisterConstant(H, 'Comm = ''\\'';');
end;

function RegisterEnumType_TLang(H: Integer): Integer;
begin
  result := RegisterEnumType(H, 'TLang');
  RegisterEnumValue(result, 'wEnglish', 0);
  RegisterEnumValue(result, 'wFrench', 1);
  RegisterEnumValue(result, 'wAll', 2);
end;

function RegisterClassType_TMyClass(H: Integer): Integer;
begin
  result := RegisterClassType(H, TMyClass);
  RegisterMethodProcedure_TMyClass_CountWords(result);
end;

// function Deliver(C: Integer): Boolean;
function RegisterFunction_Deliver(H: Integer): Integer;
begin
  result := RegisterRoutine(H, 'Deliver'
    , _typeBOOLEAN // result type
    , @ Deliver // address
    );
  RegisterParameter(result, 'C', _typeINTEGER, _parVAL);
end;

function RegisterVariable_LastCount(H: Integer): Integer;
var
  T: Integer;
begin
  T := _typeINTEGER;
  result := RegisterVariable(H, 'LastCount', T, @LastCount);
end;

procedure Part1(result: Integer);
begin
  RegisterConstant_Comm(result);
  RegisterEnumType_TLang(result);
  RegisterClassType_TMyClass(result);
  RegisterFunction_Deliver(result);
  RegisterVariable_LastCount(result);
end;

function Register_MyUnit: Integer;
begin
  result := RegisterNamespace(0, 'MyUnit');
  RegisterUsingNamespace('System.Classes');
  Part1(result);
  UnregisterUsingNamespaces;
end;

end.

To make host-defined members to be accessible in your scripts, you have to call procedure Register_Common before you create first instance of TPaxCompiler class:

Register_Common;
.................
PaxCompiler1 := TPaxCompiler.Create(nil);

If you are using TPaxCompiler instance as component in a form designer, the best way is to place Register_Common call in the initialization section of a unit of your application.

Mode 2- import global members only

You have to switch on "Import global members only" check box on the panel of importer. Generated IMPORT_Common.pas is

unit IMPORT_Common;
interface
uses
  PaxCompiler;
procedure Register_Common(compiler: TPaxCompiler);
implementation
uses
  IMP_System.Classes,
  IMP_MyUnit;
procedure Register_Common(compiler: TPaxCompiler);
begin
  Register_System_Classes(compiler);
  Register_MyUnit(compiler);
end;
end.

As you can see, parameter compiler has been added to all procedures. Import unit IMP_MyUnit.pas has view:

unit IMP_MyUnit;
interface
uses
  PaxCompiler;

function Register_MyUnit(compiler: TPaxCompiler): Integer;

implementation

uses
  PAXCOMP_STDLIB,
  PaxRegister,
  System.Classes,
  MyUnit;

function RegisterConstant__Comm(H: Integer; compiler: TPaxCompiler): Integer;
begin
  if not Compiler.InScript('Comm') then begin result := 0; Exit; end;
  result := compiler.RegisterConstant(H, 'Comm = ''\\'';');
end;

// function Deliver(C: Integer): Boolean;
function RegisterFunction_Deliver(H: Integer; compiler: TPaxCompiler): Integer;
begin
  if not Compiler.InScript('Deliver') then begin result := 0; Exit; end;
  result := compiler.RegisterRoutine(H, 'Deliver'
    , _typeBOOLEAN // result type
    , @ Deliver // address
    );
  compiler.RegisterParameter(result, 'C', _typeINTEGER, _parVAL);
end;

function RegisterVariable_LastCount(H: Integer; compiler: TPaxCompiler): Integer;
var
  T: Integer;
begin
  if not Compiler.InScript('LastCount') then begin result := 0; Exit; end;
  T := _typeINTEGER;
  result := compiler.RegisterVariable(H, 'LastCount', T, @LastCount);
end;

procedure Part1(result: Integer; compiler: TPaxCompiler);
begin
  RegisterConstant__Comm(result, compiler);
  RegisterFunction_Deliver(result, compiler);
  RegisterVariable_LastCount(result, compiler);
end;

function Register_MyUnit(compiler: TPaxCompiler): Integer;
begin
  if not compiler.InScript('MyUnit') then Exit;
  result := compiler.RegisterNamespace(0, 'MyUnit');
  compiler.RegisterUsingNamespace('System.Classes');
  Part1(result, compiler);
  compiler.UnregisterUsingNamespaces;
end;

end.

As it was said above, all types are imported automatically via Delphi RTTI, the unit contains import of global members only. It is necessary to add, that call of Register_Common should be applied after paxCompiler ends the parsing stage of compilation process. Therefore paxCompiler already knows all identifiers which must be evaluated. The call of Register_Common must be placed into body of OnImportGlobalMembers event handler:

PaxCompiler1.OnImportGlobalMembers := Handler.DoImportGlobalMembers;

......................................

procedure THandler.DoImportGlobalMembers(Sender: TPaxCompiler);
begin
  Register_Common(Sender);
end;


Copyright © 2014 Alexander Baranovsky. All rights reserved.