lazarus-ccr/wst/trunk/ws_helper/pascal_parser_intf.pas

1135 lines
36 KiB
ObjectPascal

{
This file is part of the Web Service Toolkit
Copyright (c) 2007 by Inoussa OUEDRAOGO
This file is provide under modified LGPL licence
( the files COPYING.modifiedLGPL and COPYING.LGPL).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
}
{$INCLUDE wst_global.inc}
unit pascal_parser_intf;
interface
uses
Classes, SysUtils, Contnrs,
pparser, pastree;
const
sEXTERNAL_NAME = '_E_N_';
sATTRIBUTE = '_ATTRIBUTE_';
sARRAY_ITEM_NAME = 'ARRAY_ITEM_NAME';
sARRAY_ITEM_EXT_NAME = 'ARRAY_ITEM_EXT_NAME';
sARRAY_STYLE = 'ARRAY_STYLE';
sARRAY_STYLE_SCOPED = 'ARRAY_STYLE_SCOPED';
sARRAY_STYLE_EMBEDDED = 'ARRAY_STYLE_EMBEDDED';
sARRAY_IS_COLLECTION = 'ARRAY_COLLECTION';
sXSD_NS = 'http://www.w3.org/2001/XMLSchema';
type
TElementNameKind = ( elkDeclaredName, elkName );
TElementNameKinds = set of TElementNameKind;
TBindingStyle = ( bsDocument, bsRPC, bsUnknown );
const
BindingStyleNames : array[TBindingStyle] of string = ( 'Document', 'RPC', 'Unknown' );
type
TArrayStyle = ( asScoped, asEmbeded );
ESymbolException = class(Exception)
end;
{ TwstBinding }
TwstBinding = class(TPasElement)
private
FAddress: string;
FBindingStyle: TBindingStyle;
FIntf: TPasClassType;
public
constructor Create(
const AName : string;
AIntf : TPasClassType;
AParent: TPasElement
);reintroduce;
destructor Destroy();override;
property Intf : TPasClassType read FIntf;
property Address : string read FAddress write FAddress;
property BindingStyle : TBindingStyle read FBindingStyle write FBindingStyle;
end;
{ TPropertyHolder }
TPropertyHolder = class
private
FObjects : TObjectList;
FProps : TObjectList;
private
procedure FreeList(AObject : TObject);
public
constructor Create();
destructor Destroy();override;
procedure SetValue(AOwner : TObject; const AName, AValue : string);
function GetValue(AOwner : TObject; const AName : string) : string;
function HasValue(AOwner : TObject; const AName : string) : Boolean;
function FindList(AOwner : TObject) : TStrings;
function GetList(AOwner : TObject) : TStrings;
end;
{ TwstPasTreeContainer }
TwstPasTreeContainer = class(TPasTreeContainer)
private
FCurrentModule: TPasModule;
FBindingList : TObjectList;
FProperties : TPropertyHolder;
private
function GetBinding(AIndex : Integer): TwstBinding;
function GetBindingCount: Integer;
public
constructor Create();
destructor Destroy();override;
function CreateElement(
AClass : TPTreeElement;
const AName : String;
AParent : TPasElement;
AVisibility : TPasMemberVisibility;
const ASourceFilename : String;
ASourceLinenumber : Integer
): TPasElement;overload;override;
function CreateArray(
const AName : string;
AItemType : TPasType;
const AItemName,
AItemExternalName : string;
const AStyle : TArrayStyle
) : TPasArrayType;
function GetArrayItemName(AArray : TPasArrayType) : string;
function GetArrayItemExternalName(AArray : TPasArrayType) : string;
function GetArrayStyle(AArray : TPasArrayType) : TArrayStyle;
procedure SetArrayStyle(AArray : TPasArrayType; const AStyle : TArrayStyle);
procedure SetArrayItemExternalName(AArray : TPasArrayType; const AExternalName : string);
function IsCollection(AArray : TPasArrayType) : Boolean;
procedure SetCollectionFlag(AArray : TPasArrayType; const AFlag : Boolean);
function FindElement(const AName: String): TPasElement; overload; override;
function FindElement(const AName: String; const ANameKinds : TElementNameKinds): TPasElement; overload;
function FindElementNS(const AName, ANameSpace : string): TPasElement;
function FindElementInModule(
const AName: String;
AModule: TPasModule;
const ANameKinds : TElementNameKinds = [elkDeclaredName, elkName]
): TPasElement;
function FindModule(const AName: String): TPasModule;override;
function IsEnumItemNameUsed(const AName : string; AModule : TPasModule) : Boolean;overload;
function IsEnumItemNameUsed(const AName : string) : Boolean;overload;
procedure SetCurrentModule(AModule : TPasModule);
property CurrentModule : TPasModule read FCurrentModule;
function AddBinding(const AName : string; AIntf : TPasClassType):TwstBinding;
procedure DeleteBinding(ABinding : TwstBinding);
function FindBinding(const AName : string):TwstBinding;overload;
function FindBinding(const AIntf : TPasClassType; const AOrder : Integer = 0):TwstBinding;overload;
property BindingCount : Integer read GetBindingCount;
property Binding[AIndex : Integer] : TwstBinding read GetBinding;
property Properties : TPropertyHolder read FProperties;
procedure FreeProperties(AObject : TPasElement);
procedure RegisterExternalAlias(AObject : TPasElement; const AExternalName : String);
function SameName(AObject : TPasElement; const AName : string) : Boolean;
function HasExternalName(AObject : TPasElement) : Boolean;
function GetExternalName(AObject : TPasElement) : string;overload;
function GetExternalName(AObject : TPasElement; const AReturnNameIfEmpty : Boolean) : string;overload;
function GetNameSpace(AType : TPasType) : string ;
function IsAttributeProperty(AObject : TPasVariable) : Boolean;
procedure SetPropertyAsAttribute(AObject : TPasVariable; const AValue : Boolean);
function IsInitNeed(AType: TPasType): Boolean;
function IsOfType(AType: TPasType; AClass: TClass): Boolean;
end;
TPasNativeModule = class(TPasModule)
end;
TPasClassTypeClass = class of TPasClassType;
TPasNativeSimpleContentClassType = class;
{ TPasNativeClassType }
TPasNativeClassType = class(TPasClassType)
private
FExtendableType : TPasNativeSimpleContentClassType;
public
destructor Destroy();override;
procedure SetExtendableType(AExtendableType : TPasNativeSimpleContentClassType);
property ExtendableType : TPasNativeSimpleContentClassType read FExtendableType;
end;
TPasNativeSimpleContentClassType = class(TPasNativeClassType) end;
TPasNativeSpecialSimpleContentClassType = class(TPasNativeSimpleContentClassType) end;
{ TPasNativeSimpleType }
TPasNativeSimpleType = class(TPasType)
private
FExtendableType: TPasNativeSimpleContentClassType;
public
destructor Destroy();override;
procedure SetExtendableType(AExtendableType : TPasNativeSimpleContentClassType);
property ExtendableType : TPasNativeSimpleContentClassType read FExtendableType;
end;
TPasNativeSpecialSimpleType = class(TPasNativeSimpleType) end;
function GetParameterIndex(
AProcType : TPasProcedureType;
const AParamName : string;
const AStartPos : Integer = 0
) : Integer;
function FindParameter(
AProcType : TPasProcedureType;
const AParamName : string;
const AStartPos : Integer = 0
) : TPasArgument;
function FindMember(AClass : TPasClassType; const AName : string) : TPasElement ; overload;
function FindMember(AClass : TPasRecordType; const AName : string) : TPasElement ; overload;
function GetElementCount(AList : TList; AElementClass : TPTreeElement):Integer ;
function GetUltimeType(AType : TPasType) : TPasType;
function MakeInternalSymbolNameFrom(const AName : string) : string ;
function CreateWstInterfaceSymbolTable(AContainer : TwstPasTreeContainer) : TPasModule;
implementation
uses parserutils, wst_types;
const
SIMPLE_TYPES_COUNT = 14;
SIMPLE_TYPES : Array[0..Pred(SIMPLE_TYPES_COUNT)] Of array[0..2] of string = (
('integer', 'TComplexInt32SContentRemotable', 'int'),
('LongWord', 'TComplexInt32UContentRemotable', 'unsignedInt' ),
('SmallInt', 'TComplexInt16SContentRemotable', 'short'),
('ShortInt', 'TComplexInt8SContentRemotable', 'byte'),
('char', '', ''),
('boolean', 'TComplexBooleanContentRemotable', 'boolean'),
('Byte', 'TComplexInt8UContentRemotable', 'unsignedByte'),
('Word', 'TComplexInt16UContentRemotable', 'unsignedShort'),
('Longint', 'TComplexInt32SContentRemotable', 'int'),
('Int64', 'TComplexInt64SContentRemotable', 'long'),
('Qword', 'TComplexInt64UContentRemotable', 'unsignedLong'),
('Single', 'TComplexFloatSingleContentRemotable', 'single'),
('Double', 'TComplexFloatDoubleContentRemotable', 'double'),
('Extended', 'TComplexFloatExtendedContentRemotable', 'decimal')
);
BOXED_TYPES_COUNT = 2;
BOXED_TYPES : Array[0..Pred(BOXED_TYPES_COUNT)] Of array[0..2] of string = (
('TBase64StringRemotable', 'TBase64StringExtRemotable', 'base64Binary'),
('TBase16StringRemotable', 'TBase16StringExtRemotable', 'hexBinary')
);
SPECIAL_SIMPLE_TYPES_COUNT = 4 {$IFDEF WST_UNICODESTRING} + 1 {$ENDIF WST_UNICODESTRING};
SPECIAL_SIMPLE_TYPES : Array[0..Pred(SPECIAL_SIMPLE_TYPES_COUNT)] Of array[0..2] of string = (
('string', 'TComplexStringContentRemotable', 'string'),
('WideString', 'TComplexWideStringContentRemotable', 'string'),
('AnsiChar', 'TComplexAnsiCharContentRemotable', 'string'),
('WideChar', 'TComplexWideCharContentRemotable', 'string')
{$IFDEF WST_UNICODESTRING}
,('UnicodeString', 'TComplexUnicodeStringContentRemotable', 'string')
{$ENDIF WST_UNICODESTRING}
);
procedure AddSystemSymbol(
ADest : TPasModule;
AContainer : TwstPasTreeContainer
);
procedure RegisterSpecialSimpleTypes();
var
i : Integer;
splTyp : TPasNativeSpecialSimpleType;
syb : TPasNativeSpecialSimpleContentClassType;
s : string;
typlst : array[0..Pred(SPECIAL_SIMPLE_TYPES_COUNT)] of TPasNativeSpecialSimpleType;
begin
for i := Low(SPECIAL_SIMPLE_TYPES) to High(SPECIAL_SIMPLE_TYPES) do begin
splTyp := TPasNativeSpecialSimpleType(AContainer.CreateElement(TPasNativeSpecialSimpleType,SPECIAL_SIMPLE_TYPES[i][0],ADest.InterfaceSection,visPublic,'',0));
ADest.InterfaceSection.Declarations.Add(splTyp);
ADest.InterfaceSection.Types.Add(splTyp);
typlst[i] := splTyp;
s := SPECIAL_SIMPLE_TYPES[i][1];
if not IsStrEmpty(s) then begin
syb := AContainer.FindElementInModule(SPECIAL_SIMPLE_TYPES[i][1],ADest) as TPasNativeSpecialSimpleContentClassType;
if not Assigned(syb) then begin
syb := TPasNativeSpecialSimpleContentClassType(AContainer.CreateElement(TPasNativeSpecialSimpleContentClassType,s,ADest.InterfaceSection,visDefault,'',0));
ADest.InterfaceSection.Declarations.Add(syb);
ADest.InterfaceSection.Types.Add(splTyp);
end;
splTyp.SetExtendableType(syb);
end;
end;
for i := Low(SPECIAL_SIMPLE_TYPES) to High(SPECIAL_SIMPLE_TYPES) do begin
splTyp := typlst[i];
if not IsStrEmpty(SPECIAL_SIMPLE_TYPES[i][2]) then begin
AContainer.RegisterExternalAlias(splTyp,SPECIAL_SIMPLE_TYPES[i][2]);
if ( splTyp.ExtendableType <> nil ) then begin
AContainer.RegisterExternalAlias(splTyp.ExtendableType,SPECIAL_SIMPLE_TYPES[i][2]);
end;
end;
end;
end;
procedure RegisterSimpleTypes();
var
i : Integer;
splTyp : TPasNativeSimpleType;
syb : TPasNativeSimpleContentClassType;
s : string;
typlst : array[0..Pred(SIMPLE_TYPES_COUNT)] of TPasNativeSimpleType;
begin
for i := Low(SIMPLE_TYPES) to High(SIMPLE_TYPES) do begin
splTyp := TPasNativeSimpleType(AContainer.CreateElement(TPasNativeSimpleType,SIMPLE_TYPES[i][0],ADest.InterfaceSection,visPublic,'',0));
ADest.InterfaceSection.Declarations.Add(splTyp);
ADest.InterfaceSection.Types.Add(splTyp);
typlst[i] := splTyp;
s := SIMPLE_TYPES[i][1];
if not IsStrEmpty(s) then begin
syb := AContainer.FindElementInModule(SIMPLE_TYPES[i][1],ADest) as TPasNativeSimpleContentClassType;
if not Assigned(syb) then begin
syb := TPasNativeSimpleContentClassType(AContainer.CreateElement(TPasNativeSimpleContentClassType,s,ADest.InterfaceSection,visDefault,'',0));
ADest.InterfaceSection.Declarations.Add(syb);
ADest.InterfaceSection.Types.Add(splTyp);
end;
splTyp.SetExtendableType(syb);
end;
end;
for i := Low(SIMPLE_TYPES) to High(SIMPLE_TYPES) do begin
splTyp := typlst[i];
if not IsStrEmpty(SIMPLE_TYPES[i][2]) then begin
AContainer.RegisterExternalAlias(splTyp,SIMPLE_TYPES[i][2]);
if ( splTyp.ExtendableType <> nil ) then begin
AContainer.RegisterExternalAlias(splTyp.ExtendableType,SIMPLE_TYPES[i][2]);
end;
end;
end;
end;
procedure RegisterBoxedTypes();
var
i : Integer;
nativeType : TPasNativeSimpleContentClassType;
syb : TPasNativeSimpleContentClassType;
s : string;
typlst : array[0..Pred(BOXED_TYPES_COUNT)] of TPasNativeSimpleContentClassType;
begin
for i := Low(BOXED_TYPES) to High(BOXED_TYPES) do begin
nativeType := TPasNativeSimpleContentClassType(AContainer.CreateElement(TPasNativeSimpleContentClassType,BOXED_TYPES[i][0],ADest.InterfaceSection,visPublic,'',0));
ADest.InterfaceSection.Declarations.Add(nativeType);
ADest.InterfaceSection.Types.Add(nativeType);
typlst[i] := nativeType;
s := BOXED_TYPES[i][1];
if not IsStrEmpty(s) then begin
syb := AContainer.FindElementInModule(BOXED_TYPES[i][1],ADest) as TPasNativeSimpleContentClassType;
if not Assigned(syb) then begin
syb := TPasNativeSimpleContentClassType(AContainer.CreateElement(TPasNativeSimpleContentClassType,s,ADest.InterfaceSection,visDefault,'',0));
ADest.InterfaceSection.Declarations.Add(syb);
ADest.InterfaceSection.Types.Add(syb);
end;
nativeType.SetExtendableType(syb);
end;
end;
for i := Low(BOXED_TYPES) to High(BOXED_TYPES) do begin
nativeType := typlst[i];
if not IsStrEmpty(BOXED_TYPES[i][2]) then begin
AContainer.RegisterExternalAlias(nativeType,BOXED_TYPES[i][2]);
if ( nativeType.ExtendableType <> nil ) then begin
AContainer.RegisterExternalAlias(nativeType.ExtendableType,BOXED_TYPES[i][2]);
end;
end;
end;
end;
begin
RegisterSimpleTypes();
RegisterSpecialSimpleTypes();
RegisterBoxedTypes();
end;
function CreateWstInterfaceSymbolTable(AContainer : TwstPasTreeContainer) : TPasModule;
function AddClassDef(
ATable : TPasModule;
const AClassName,
AParentName : string;
const AClassType : TPasClassTypeClass = nil
):TPasClassType;
var
locClassType : TPasClassTypeClass;
begin
if Assigned(AClassType) then begin
locClassType := AClassType;
end else begin
locClassType := TPasClassType;
end;
Result := TPasClassType(AContainer.CreateElement(locClassType,AClassName,ATable.InterfaceSection,visDefault,'',0));
if not IsStrEmpty(AParentName) then begin
Result.AncestorType := AContainer.FindElementInModule(AParentName,ATable) as TPasType;
if Assigned(Result.AncestorType) then
Result.AncestorType.AddRef();
end;
ATable.InterfaceSection.Classes.Add(Result);
ATable.InterfaceSection.Declarations.Add(Result);
ATable.InterfaceSection.Types.Add(Result);
end;
function AddAlias(const AName, ABaseType : string; ATable : TPasModule) : TPasTypeAliasType;
begin
Result := TPasTypeAliasType(AContainer.CreateElement(TPasAliasType,AName,ATable.InterfaceSection,visPublic,'',0));
Result.DestType := AContainer.FindElementInModule(ABaseType,ATable) as TPasType;
if Assigned(Result.DestType) then
Result.DestType.AddRef();
ATable.InterfaceSection.Declarations.Add(Result);
ATable.InterfaceSection.Classes.Add(Result);
ATable.InterfaceSection.Types.Add(Result);
end;
var
loc_TBaseComplexSimpleContentRemotable : TPasClassType;
begin
Result := TPasNativeModule(AContainer.CreateElement(TPasNativeModule,'base_service_intf',AContainer.Package,visPublic,'',0));
try
AContainer.Package.Modules.Add(Result);
AContainer.RegisterExternalAlias(Result,sXSD_NS);
Result.InterfaceSection := TPasSection(AContainer.CreateElement(TPasSection,'',Result,visDefault,'',0));
AddSystemSymbol(Result,AContainer);
AddClassDef(Result,'TBaseRemotable','',TPasNativeClassType);
AddClassDef(Result,'TAbstractSimpleRemotable','TBaseRemotable',TPasNativeClassType);
AContainer.RegisterExternalAlias(AddClassDef(Result,'TDateRemotable','TAbstractSimpleRemotable'),'dateTime');
{$IFDEF WST_HAS_TDURATIONREMOTABLE}
AContainer.RegisterExternalAlias(AddClassDef(Result,'TDurationRemotable','TAbstractSimpleRemotable'),'duration');
{$ENDIF WST_HAS_TDURATIONREMOTABLE}
AContainer.RegisterExternalAlias(AddClassDef(Result,'TTimeRemotable','TAbstractSimpleRemotable'),'time');
AddClassDef(Result,'TAbstractComplexRemotable','TBaseRemotable',TPasNativeClassType);
loc_TBaseComplexSimpleContentRemotable := AddClassDef(Result,'TBaseComplexSimpleContentRemotable','TAbstractComplexRemotable',TPasNativeClassType);
(AContainer.FindElementInModule('TComplexInt16SContentRemotable',Result) as TPasClassType).AncestorType := loc_TBaseComplexSimpleContentRemotable;
(AContainer.FindElementInModule('TComplexFloatDoubleContentRemotable',Result) as TPasClassType).AncestorType := loc_TBaseComplexSimpleContentRemotable;
loc_TBaseComplexSimpleContentRemotable.AddRef();
loc_TBaseComplexSimpleContentRemotable.AddRef();
AddClassDef(Result,'TBaseComplexRemotable','TAbstractComplexRemotable',TPasNativeClassType);
AddClassDef(Result,'THeaderBlock','TBaseComplexRemotable',TPasNativeClassType);
AddClassDef(Result,'TSimpleContentHeaderBlock','THeaderBlock',TPasNativeClassType);
AddClassDef(Result,'TBaseArrayRemotable','TAbstractComplexRemotable',TPasNativeClassType);
AddClassDef(Result,'TBaseObjectArrayRemotable','TBaseArrayRemotable',TPasNativeClassType);
AddClassDef(Result,'TBaseSimpleTypeArrayRemotable','TBaseArrayRemotable',TPasNativeClassType);
AddClassDef(Result,'TArrayOfStringRemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfBooleanRemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfInt8URemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfInt8SRemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfInt16SRemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfInt16URemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfInt32URemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfInt32SRemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfInt64SRemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfInt64URemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfFloatSingleRemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfFloatDoubleRemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfFloatExtendedRemotable','TBaseSimpleTypeArrayRemotable');
AddClassDef(Result,'TArrayOfFloatCurrencyRemotable','TBaseSimpleTypeArrayRemotable');
AddAlias('token','string',Result);
AddAlias('anyURI','string',Result);
AddAlias('ID','string',Result);
AddAlias('float','Single',Result);
AddAlias('nonNegativeInteger','LongWord',Result);
AddAlias('positiveInteger','nonNegativeInteger',Result);
{$IFNDEF WST_HAS_TDURATIONREMOTABLE}
AddAlias('duration','string',Result);
{$ENDIF WST_HAS_TDURATIONREMOTABLE}
{$IFNDEF WST_HAS_TTIMEREMOTABLE}
AddAlias('time','string',Result);
{$ENDIF WST_HAS_TTIMEREMOTABLE}
except
FreeAndNil(Result);
raise;
end;
end;
function GetUltimeType(AType : TPasType) : TPasType;
begin
Result := AType;
if ( Result <> nil ) then begin
while Result.InheritsFrom(TPasAliasType) and
( TPasAliasType(Result).DestType <> nil )
do begin
Result := TPasAliasType(Result).DestType;
end;
end;
end;
function GetElementCount(AList : TList; AElementClass : TPTreeElement):Integer ;
var
i : Integer;
begin
Result := 0;
if Assigned(AList) then begin
for i := 0 to Pred(AList.Count) do begin
if TObject(AList[i]).InheritsFrom(AElementClass) then begin
Inc(Result);
end;
end;
end;
end;
function GetParameterIndex(
AProcType : TPasProcedureType;
const AParamName : string;
const AStartPos : Integer
) : Integer;
var
pl : TList;
i : Integer;
begin
pl := AProcType.Args;
if ( AStartPos >= 0 ) then
i := AStartPos
else
i := 0;
for i := i to Pred(pl.Count) do begin
if AnsiSameText(AParamName,TPasArgument(pl[i]).Name) then begin
Result := i;
Exit;
end;
end;
Result := -1;
end;
function FindParameter(
AProcType : TPasProcedureType;
const AParamName : string;
const AStartPos : Integer
) : TPasArgument;
var
i : Integer;
begin
i := GetParameterIndex(AProcType,AParamName,AStartPos);
if ( i >= 0 ) then begin
Result := TPasArgument(AProcType.Args[i]);
end else begin
Result := nil;
end;
end;
function InternalFindMember(AMemberList : TList; const AName : string) : TPasElement ;
var
i : Integer;
begin
Result := nil;
if ( AMemberList <> nil ) then begin
for i := 0 to Pred(AMemberList.Count) do begin
if AnsiSameText(AName,TPasElement(AMemberList[i]).Name) then begin
Result := TPasElement(AMemberList[i]);
end;
end;
end;
end;
function FindMember(AClass : TPasClassType; const AName : string) : TPasElement ;
begin
Result := nil;
if ( AClass <> nil ) then begin
Result := InternalFindMember(AClass.Members,AName);
end;
end;
function FindMember(AClass : TPasRecordType; const AName : string) : TPasElement ;
begin
Result := nil;
if ( AClass <> nil ) then begin
Result := InternalFindMember(AClass.Members,AName);
end;
end;
function MakeInternalSymbolNameFrom(const AName : string) : string ;
begin
Result := ExtractIdentifier(AName);
if IsStrEmpty(AName) then begin
raise ESymbolException.CreateFmt('Unable to make an internal symbol Name from "%s".',[AName]);
end;
if IsReservedKeyWord(Result) then begin
Result := '_' + Result;
end;
end;
{ TwstPasTreeContainer }
function TwstPasTreeContainer.GetBinding(AIndex : Integer): TwstBinding;
begin
Result := TwstBinding(FBindingList[AIndex]);
end;
function TwstPasTreeContainer.GetBindingCount: Integer;
begin
Result := FBindingList.Count;
end;
constructor TwstPasTreeContainer.Create();
begin
FPackage := TPasPackage.Create('sample',nil);
FBindingList := TObjectList.Create(True);
FProperties := TPropertyHolder.Create();
end;
destructor TwstPasTreeContainer.Destroy();
begin
FreeAndNil(FProperties);
FreeAndNil(FBindingList);
FreeAndNil(FPackage);
inherited Destroy();
end;
function TwstPasTreeContainer.CreateElement(
AClass : TPTreeElement;
const AName : String;
AParent : TPasElement;
AVisibility : TPasMemberVisibility;
const ASourceFilename : String;
ASourceLinenumber : Integer
) : TPasElement;
begin
Result := AClass.Create(AName,AParent);
RegisterExternalAlias(Result,AName);
Result.Visibility := AVisibility;
Result.SourceFilename := ASourceFilename;
Result.SourceLinenumber := ASourceLinenumber;
if Result.InheritsFrom(TPasModule) then begin
FCurrentModule := Result as TPasModule;
//Package.Modules.Add(Result);
end;
end;
function TwstPasTreeContainer.CreateArray(
const AName : string;
AItemType : TPasType;
const AItemName,
AItemExternalName : string;
const AStyle : TArrayStyle
) : TPasArrayType;
var
s : string;
begin
Result := TPasArrayType(CreateElement(TPasArrayType,AName,CurrentModule.InterfaceSection,visDefault,'',0));
Result.ElType := AItemType;
AItemType.AddRef();
Properties.SetValue(Result,sARRAY_ITEM_NAME,AItemName);
Properties.SetValue(Result,sARRAY_ITEM_EXT_NAME,AItemExternalName);
if ( AStyle = asEmbeded ) then
s := sARRAY_STYLE_EMBEDDED
else
s := sARRAY_STYLE_SCOPED;
Properties.SetValue(Result,sARRAY_STYLE,s);
end;
function TwstPasTreeContainer.GetArrayItemName(AArray: TPasArrayType): string;
begin
Result := Properties.GetValue(AArray,sARRAY_ITEM_NAME);
end;
function TwstPasTreeContainer.GetArrayItemExternalName(AArray: TPasArrayType): string;
begin
Result := Properties.GetValue(AArray,sARRAY_ITEM_EXT_NAME);
end;
function TwstPasTreeContainer.GetArrayStyle(AArray: TPasArrayType): TArrayStyle;
begin
if AnsiSameText(sARRAY_STYLE_EMBEDDED,Properties.GetValue(AArray,sARRAY_STYLE)) then
Result := asEmbeded
else
Result := asScoped;
end;
procedure TwstPasTreeContainer.SetArrayStyle(
AArray : TPasArrayType;
const AStyle : TArrayStyle
);
begin
if ( AStyle = asEmbeded ) then
Properties.SetValue(AArray,sARRAY_STYLE,sARRAY_STYLE_EMBEDDED)
else
Properties.SetValue(AArray,sARRAY_STYLE,sARRAY_STYLE_SCOPED);
end;
procedure TwstPasTreeContainer.SetArrayItemExternalName(
AArray : TPasArrayType;
const AExternalName : string
);
begin
Properties.SetValue(AArray,sARRAY_ITEM_EXT_NAME,AExternalName);
end;
function TwstPasTreeContainer.IsCollection(AArray : TPasArrayType) : Boolean;
begin
Result := AnsiSameText('true',Properties.GetValue(AArray,sARRAY_IS_COLLECTION));
end;
procedure TwstPasTreeContainer.SetCollectionFlag(
AArray : TPasArrayType;
const AFlag : Boolean
);
begin
if AFlag then
Properties.SetValue(AArray,sARRAY_IS_COLLECTION,'true')
else
Properties.SetValue(AArray,sARRAY_IS_COLLECTION,'false');
end;
function TwstPasTreeContainer.FindElementInModule(
const AName: String;
AModule : TPasModule;
const ANameKinds : TElementNameKinds
): TPasElement;
var
decs : TList;
i, c : Integer;
begin
Result := nil;
if Assigned(AModule) and Assigned(AModule.InterfaceSection.Declarations) then begin
decs := AModule.InterfaceSection.Declarations;
c := decs.Count;
if ( elkDeclaredName in ANameKinds ) then begin
for i := 0 to Pred(c) do begin
if AnsiSameText(AName, GetExternalName(TPasElement(decs[i]))) then begin
Result := TPasElement(decs[i]);
Exit;
end;
end;
end;
if ( Result = nil ) and ( elkName in ANameKinds ) then begin
for i := 0 to Pred(c) do begin
if AnsiSameText(AName, TPasElement(decs[i]).Name) then begin
Result := TPasElement(decs[i]);
Exit;
end;
end;
end;
end;
end;
function TwstPasTreeContainer.FindElement(const AName: String): TPasElement;
begin
Result := FindElement(AName,[elkDeclaredName,elkName]);
end;
function TwstPasTreeContainer.FindElement(
const AName: String;
const ANameKinds: TElementNameKinds
): TPasElement;
var
i : Integer;
mls : TList;
mdl : TPasModule;
begin
Result := FindElementInModule(AName,CurrentModule,ANameKinds);
if ( Result = nil ) then begin
mls := Package.Modules;
for i := 0 to Pred(mls.Count) do begin
mdl := TPasModule(mls[i]);
if ( CurrentModule <> mdl ) then begin
Result := FindElementInModule(AName,mdl,ANameKinds);
if ( Result <> nil ) then begin
Break;
end;
end;
end;
end;
end;
function TwstPasTreeContainer.FindModule(const AName: String): TPasModule;
var
i , c : Integer;
mdl : TList;
begin
Result := nil;
mdl := Package.Modules;
c := mdl.Count;
for i := 0 to Pred(c) do begin
if SameName(TPasModule(mdl[i]),AName) then begin
Result := TPasModule(mdl[i]);
end;
end;
end;
function TwstPasTreeContainer.IsEnumItemNameUsed(const AName: string;AModule: TPasModule): Boolean;
var
i, c, j : Integer;
elt : TPasElement;
enumList : TList;
typeList : TList;
begin
Result := False;
typeList := AModule.InterfaceSection.Declarations;
c := typeList.Count;
for i := 0 to Pred(c) do begin
elt := TPasElement(typeList[i]);
if elt.InheritsFrom(TPasEnumType) then begin
enumList := TPasEnumType(elt).Values;
for j := 0 to Pred(enumList.Count) do begin
if AnsiSameText(AName,TPasEnumValue(enumList[j]).Name) then begin
Result := True;
Exit;
end;
end;
end;
end;
end;
function TwstPasTreeContainer.IsEnumItemNameUsed(const AName: string): Boolean;
begin
Result := IsEnumItemNameUsed(AName,CurrentModule);
end;
function TwstPasTreeContainer.IsOfType(AType : TPasType; AClass : TClass) : Boolean;
var
ut : TPasType;
begin
Result := False;
if Assigned(AType) then begin
ut := AType;
if ut.InheritsFrom(TPasUnresolvedTypeRef) then begin
ut := FindElement(GetExternalName(ut)) as TPasType;
if ( ut = nil ) then
ut := AType;
end;
ut := GetUltimeType(ut);
if ut.InheritsFrom(AClass) then begin
Result := True;
end;
end;
end;
function TwstPasTreeContainer.IsInitNeed(AType : TPasType) : Boolean;
begin
Result := IsOfType(AType,TPasClassType) or
IsOfType(AType,TPasPointerType) or
IsOfType(AType,TPasArrayType) or
IsOfType(AType,TPasRecordType);
end;
procedure TwstPasTreeContainer.SetCurrentModule(AModule: TPasModule);
begin
FCurrentModule := AModule;
end;
function TwstPasTreeContainer.AddBinding(const AName : string; AIntf : TPasClassType):TwstBinding;
begin
Result := FindBinding(AName);
if Assigned(Result) then begin
raise Exception.CreateFmt('Duplicated binding : "%s"',[AName]);
end;
Result := TwstBinding.Create(AName, AIntf, AIntf.Parent);
FBindingList.Add(Result);
end;
procedure TwstPasTreeContainer.DeleteBinding(ABinding: TwstBinding);
begin
FBindingList.Extract(ABinding);
ABinding.Release();
end;
function TwstPasTreeContainer.FindBinding(const AName: string): TwstBinding;
var
i : Integer;
begin
for i := 0 to Pred(BindingCount) do begin
if AnsiSameText(AName,Binding[i].Name) then begin
Result := Binding[i];
Exit;
end;
end;
Result := nil;
end;
function TwstPasTreeContainer.FindBinding(const AIntf: TPasClassType; const AOrder : Integer): TwstBinding;
var
i, c, ordr : Integer;
begin
ordr := AOrder;
c := BindingCount;
for i := 0 to Pred(c) do begin
Result := Binding[i];
if ( Result.Intf = AIntf ) then begin
if ( ordr <= 0 ) then
Exit
else
Dec(ordr);
end;
end;
Result := nil;
end;
procedure TwstPasTreeContainer.FreeProperties(AObject: TPasElement);
procedure FreeClassProps(AObj : TPasClassType);
var
ls : TList;
k : PtrInt;
begin
ls := AObj.Members;
for k := 0 to Pred(ls.Count) do begin
FProperties.FreeList(TPasElement(ls[k]));
end;
end;
procedure FreeRecordFields(AObj : TPasRecordType);
var
ls : TList;
k : PtrInt;
begin
ls := AObj.Members;
for k := 0 to Pred(ls.Count) do begin
FProperties.FreeList(TPasElement(ls[k]));
end;
end;
begin
if Assigned(AObject) then begin
FProperties.FreeList(AObject);
if AObject.InheritsFrom(TPasClassType) then
FreeClassProps(AObject as TPasClassType)
else if AObject.InheritsFrom(TPasRecordType) then
FreeRecordFields(AObject as TPasRecordType);
end;
end;
procedure TwstPasTreeContainer.RegisterExternalAlias(
AObject : TPasElement;
const AExternalName : String
);
begin
Properties.SetValue(AObject,sEXTERNAL_NAME,AExternalName);
end;
function TwstPasTreeContainer.SameName(
AObject : TPasElement;
const AName : string
): Boolean;
begin
Result := AnsiSameText(AName,AObject.Name) or AnsiSameText(AName,GetExternalName(AObject)) ;
end;
function TwstPasTreeContainer.HasExternalName(AObject : TPasElement) : Boolean;
begin
Result := Properties.HasValue(AObject,sEXTERNAL_NAME);
end;
function TwstPasTreeContainer.GetExternalName(AObject: TPasElement): string;
begin
Result := GetExternalName(AObject,True);
end;
function TwstPasTreeContainer.GetExternalName(
AObject : TPasElement;
const AReturnNameIfEmpty : Boolean
) : string;
begin
Result := Properties.GetValue(AObject,sEXTERNAL_NAME);
if IsStrEmpty(Result) and AReturnNameIfEmpty then begin
Result := AObject.Name;
end;
end;
function TwstPasTreeContainer.IsAttributeProperty(AObject: TPasVariable): Boolean;
begin
Result := AnsiSameText(Properties.GetValue(AObject,sATTRIBUTE),'True');
end;
procedure TwstPasTreeContainer.SetPropertyAsAttribute(AObject: TPasVariable; const AValue: Boolean);
var
s : string;
begin
if AValue then
s := 'True'
else
s := 'False';
Properties.SetValue(AObject,sATTRIBUTE,s);
end;
function TwstPasTreeContainer.FindElementNS(const AName, ANameSpace: string): TPasElement;
var
mdl : TPasModule;
begin
Result := nil;
mdl := FindModule(ANameSpace);
if Assigned(mdl) then begin
Result := FindElementInModule(AName,mdl);
end;
end;
function TwstPasTreeContainer.GetNameSpace(AType: TPasType): string;
begin
if Assigned(AType) and
Assigned(AType.Parent{Section}) and
Assigned(AType.Parent.Parent{Module})
then begin
Result := GetExternalName(AType.Parent.Parent);
end else begin
Result := '';
end;
end;
{ TwstBinding }
constructor TwstBinding.Create(
const AName : string;
AIntf : TPasClassType;
AParent: TPasElement
);
begin
Assert((not IsStrEmpty(AName)) and Assigned(AIntf) and ( AIntf.ObjKind = okInterface ));
inherited Create(AName,AParent);
FIntf := AIntf;
FIntf.AddRef();
end;
destructor TwstBinding.Destroy();
begin
if Assigned(FIntf) then begin
FIntf.Release();
FIntf := nil;
end;
inherited Destroy();
end;
{ TPropertyHolder }
function TPropertyHolder.FindList(AOwner: TObject): TStrings;
var
i : Integer;
begin
i := FObjects.IndexOf(AOwner);
if ( i >= 0 ) then begin
Result := FProps[i] as TStrings;
end else begin
Result := nil ;
end;
end;
function TPropertyHolder.GetList(AOwner: TObject): TStrings;
begin
Result := FindList(AOwner);
if ( Result = nil ) then begin
FObjects.Add(AOwner);
Result := TStringList.Create();
FProps.Add(Result);
end;
end;
procedure TPropertyHolder.FreeList(AObject: TObject);
var
i : PtrInt;
begin
i := FObjects.IndexOf(AObject);
if ( i >= 0 ) then begin
FObjects.Delete(i);
FProps.Delete(i);
end;
end;
constructor TPropertyHolder.Create();
begin
FObjects := TObjectList.Create(False);
FProps := TObjectList.Create(True);
end;
destructor TPropertyHolder.Destroy();
begin
FreeAndNil(FProps);
FreeAndNil(FObjects);
inherited Destroy();
end;
procedure TPropertyHolder.SetValue(AOwner: TObject; const AName, AValue: string);
begin
GetList(AOwner).Values[AName] := AValue;
end;
function TPropertyHolder.GetValue(AOwner: TObject; const AName: string): string;
var
ls : TStrings;
begin
ls := FindList(AOwner);
if ( ls = nil ) then begin
Result := '';
end else begin
Result := ls.Values[AName];
end;
end;
function TPropertyHolder.HasValue(AOwner : TObject; const AName : string) : Boolean;
var
ls : TStrings;
begin
ls := FindList(AOwner);
if ( ls <> nil ) and ( ls.IndexOfName(AName) > -1 ) then
Result := True
else
Result := False;
end;
{ TPasNativeSimpleTypeDefinition }
destructor TPasNativeSimpleType.Destroy();
begin
if Assigned(FExtendableType) then begin
FExtendableType.Release();
FExtendableType := nil
end;
inherited Destroy();
end;
procedure TPasNativeSimpleType.SetExtendableType(
AExtendableType : TPasNativeSimpleContentClassType
);
begin
if ( FExtendableType <> AExtendableType ) then begin
if ( FExtendableType <> nil ) then begin
FExtendableType.Release();
end;
FExtendableType := AExtendableType;
if ( FExtendableType <> nil ) then
FExtendableType.AddRef();
end;
end;
{ TPasNativeClassType }
destructor TPasNativeClassType.Destroy();
begin
if Assigned(FExtendableType) then begin
FExtendableType.Release();
FExtendableType := nil
end;
inherited Destroy();
end;
procedure TPasNativeClassType.SetExtendableType(AExtendableType : TPasNativeSimpleContentClassType);
begin
if ( FExtendableType <> AExtendableType ) then begin
if ( FExtendableType <> nil ) then begin
FExtendableType.Release();
end;
FExtendableType := AExtendableType;
if ( FExtendableType <> nil ) then
FExtendableType.AddRef();
end;
end;
end.