fpc/fcl/passrc/pastree.pp
2003-11-22 12:12:38 +00:00

1403 lines
33 KiB
ObjectPascal

{
$Id$
This file is part of the Free Component Library
Pascal parse tree classes
Copyright (c) 2000-2003 by
Areca Systems GmbH / Sebastian Guenther, sg@freepascal.org
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
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.
**********************************************************************}
unit PasTree;
interface
uses Classes;
resourcestring
// Parse tree node type names
SPasTreeElement = 'generic element';
SPasTreeSection = 'unit section';
SPasTreeModule = 'module';
SPasTreePackage = 'package';
SPasTreeResString = 'resource string';
SPasTreeType = 'generic type';
SPasTreePointerType = 'pointer type';
SPasTreeAliasType = 'alias type';
SPasTreeTypeAliasType = '"type" alias type';
SPasTreeClassOfType = '"class of" type';
SPasTreeRangeType = 'range type';
SPasTreeArrayType = 'array type';
SPasTreeEnumValue = 'enumeration value';
SPasTreeEnumType = 'enumeration type';
SPasTreeSetType = 'set type';
SPasTreeRecordType = 'record type';
SPasTreeObjectType = 'object';
SPasTreeClassType = 'class';
SPasTreeInterfaceType = 'interface';
SPasTreeArgument = 'argument';
SPasTreeProcedureType = 'procedure type';
SPasTreeResultElement = 'function result';
SPasTreeFunctionType = 'function type';
SPasTreeUnresolvedTypeRef = 'unresolved type reference';
SPasTreeVariable = 'variable';
SPasTreeConst = 'constant';
SPasTreeProperty = 'property';
SPasTreeOverloadedProcedure = 'overloaded procedure';
SPasTreeProcedure = 'procedure';
SPasTreeFunction = 'function';
SPasTreeConstructor = 'constructor';
SPasTreeDestructor = 'destructor';
SPasTreeProcedureImpl = 'procedure/function implementation';
SPasTreeConstructorImpl = 'constructor implementation';
SPasTreeDestructorImpl = 'destructor implementation';
type
TPasModule = class;
TPasMemberVisibility = (visDefault, visPrivate, visProtected, visPublic,
visPublished, visAutomated);
TPasMemberVisibilities = set of TPasMemberVisibility;
TPTreeElement = class of TPasElement;
TPasElement = class
private
FRefCount: LongWord;
FName: String;
FParent: TPasElement;
public
SourceFilename: String;
SourceLinenumber: Integer;
constructor Create(const AName: String; AParent: TPasElement); virtual;
procedure AddRef;
procedure Release;
function FullName: String; // Name including parent's names
function PathName: String; // = Module.Name + FullName
function GetModule: TPasModule;
function ElementTypeName: String; virtual;
function GetDeclaration(full : Boolean) : String; virtual;
Visibility: TPasMemberVisibility;
property RefCount: LongWord read FRefCount;
property Name: String read FName;
property Parent: TPasElement read FParent;
end;
TPasSection = class(TPasElement)
public
constructor Create(const AName: String; AParent: TPasElement); override;
destructor Destroy; override;
function ElementTypeName: String; override;
procedure AddUnitToUsesList(const AUnitName: String);
UsesList: TList; // TPasUnresolvedTypeRef or TPasModule elements
Declarations, ResStrings, Types, Consts, Classes,
Functions, Variables: TList;
end;
TPasModule = class(TPasElement)
public
destructor Destroy; override;
function ElementTypeName: String; override;
function GetDeclaration(full : boolean) : String; override;
InterfaceSection, ImplementationSection: TPasSection;
PackageName: String;
end;
TPasPackage = class(TPasElement)
public
constructor Create(const AName: String; AParent: TPasElement); override;
destructor Destroy; override;
function ElementTypeName: String; override;
Modules: TList; // List of TPasModule objects
end;
TPasResString = class(TPasElement)
public
function ElementTypeName: String; override;
function GetDeclaration(full : Boolean) : String; Override;
Value: String;
end;
TPasType = class(TPasElement)
public
function ElementTypeName: String; override;
end;
TPasPointerType = class(TPasType)
public
destructor Destroy; override;
function ElementTypeName: String; override;
function GetDeclaration(full : Boolean): String; override;
DestType: TPasType;
end;
TPasAliasType = class(TPasType)
public
destructor Destroy; override;
function ElementTypeName: String; override;
function GetDeclaration(full : Boolean): String; override;
DestType: TPasType;
end;
TPasTypeAliasType = class(TPasAliasType)
public
function ElementTypeName: String; override;
end;
TPasClassOfType = class(TPasAliasType)
public
function ElementTypeName: String; override;
function GetDeclaration(full: boolean) : String; override;
end;
TPasRangeType = class(TPasType)
public
function ElementTypeName: String; override;
function GetDeclaration(full : boolean) : String; override;
RangeStart, RangeEnd: String;
end;
TPasArrayType = class(TPasType)
public
destructor Destroy; override;
function ElementTypeName: String; override;
function GetDeclaration(full : boolean) : String; override;
IndexRange : String;
ElType: TPasType;
end;
TPasEnumValue = class(TPasElement)
public
function ElementTypeName: String; override;
IsValueUsed: Boolean;
Value: Integer;
end;
TPasEnumType = class(TPasType)
public
constructor Create(const AName: String; AParent: TPasElement); override;
destructor Destroy; override;
function ElementTypeName: String; override;
function GetDeclaration(full : boolean) : String; override;
Procedure GetEnumNames(Names : TStrings);
Values: TList; // List of TPasEnumValue objects
end;
TPasSetType = class(TPasType)
public
destructor Destroy; override;
function ElementTypeName: String; override;
function GetDeclaration(full : boolean) : String; override;
EnumType: TPasType;
end;
TPasRecordType = class(TPasType)
public
constructor Create(const AName: String; AParent: TPasElement); override;
destructor Destroy; override;
function ElementTypeName: String; override;
function GetDeclaration(full : boolean) : String; override;
IsPacked: Boolean;
Members: TList; // array of TPasVariable elements
end;
TPasObjKind = (okObject, okClass, okInterface);
TPasClassType = class(TPasType)
public
constructor Create(const AName: String; AParent: TPasElement); override;
destructor Destroy; override;
function ElementTypeName: String; override;
ObjKind: TPasObjKind;
AncestorType: TPasType; // TPasClassType or TPasUnresolvedTypeRef
Members: TList; // array of TPasElement objects
end;
TArgumentAccess = (argDefault, argConst, argVar, argOut);
TPasArgument = class(TPasElement)
public
destructor Destroy; override;
function ElementTypeName: String; override;
function GetDeclaration(full : boolean) : String; override;
Access: TArgumentAccess;
ArgType: TPasType;
Value: String;
end;
TPasProcedureType = class(TPasType)
public
constructor Create(const AName: String; AParent: TPasElement); override;
destructor Destroy; override;
class function TypeName: String; virtual;
function ElementTypeName: String; override;
IsOfObject: Boolean;
function GetDeclaration(full : boolean) : String; override;
procedure GetArguments(List : TStrings);
function CreateArgument(const AName, AUnresolvedTypeName: String):
TPasArgument;
Args: TList; // List of TPasArgument objects
end;
TPasResultElement = class(TPasElement)
public
destructor Destroy; override;
function ElementTypeName : String; override;
ResultType: TPasType;
end;
TPasFunctionType = class(TPasProcedureType)
public
destructor Destroy; override;
class function TypeName: String; override;
function ElementTypeName: String; override;
function GetDeclaration(Full : boolean) : String; override;
ResultEl: TPasResultElement;
end;
TPasUnresolvedTypeRef = class(TPasType)
public
// Typerefs cannot be parented! -> AParent _must_ be NIL
constructor Create(const AName: String; AParent: TPasElement); override;
function ElementTypeName: String; override;
end;
TPasTypeRef = class(TPasUnresolvedTypeRef)
public
// function GetDeclaration(full : Boolean): String; override;
RefType: TPasType;
end;
TPasVariable = class(TPasElement)
public
destructor Destroy; override;
function ElementTypeName: String; override;
function GetDeclaration(full : boolean) : String; override;
VarType: TPasType;
Value: String;
Modifiers : string;
end;
TPasConst = class(TPasVariable)
public
function ElementTypeName: String; override;
end;
TPasProperty = class(TPasVariable)
public
constructor Create(const AName: String; AParent: TPasElement); override;
destructor Destroy; override;
function ElementTypeName: String; override;
function GetDeclaration(full : boolean) : String; override;
Args: TList; // List of TPasArgument objects
IndexValue, ReadAccessorName, WriteAccessorName,
StoredAccessorName, DefaultValue: String;
IsDefault, IsNodefault: Boolean;
end;
TPasProcedureBase = class(TPasElement)
public
function TypeName: String; virtual; abstract;
end;
TPasOverloadedProc = class(TPasProcedureBase)
public
constructor Create(const AName: String; AParent: TPasElement); override;
destructor Destroy; override;
function ElementTypeName: String; override;
function TypeName: String; override;
Overloads: TList; // List of TPasProcedure nodes
end;
TPasProcedure = class(TPasProcedureBase)
public
destructor Destroy; override;
function ElementTypeName: String; override;
function TypeName: String; override;
ProcType: TPasProcedureType;
function GetDeclaration(full: Boolean): String; override;
procedure GetModifiers(List: TStrings);
IsVirtual, IsDynamic, IsAbstract, IsOverride,
IsOverload, IsMessage: Boolean;
end;
TPasFunction = class(TPasProcedure)
public
function ElementTypeName: String; override;
function GetDeclaration (full : boolean) : String; override;
end;
TPasConstructor = class(TPasProcedure)
public
function ElementTypeName: String; override;
function TypeName: String; override;
end;
TPasDestructor = class(TPasProcedure)
public
function ElementTypeName: String; override;
function TypeName: String; override;
end;
TPasImplBlock = class;
TPasProcedureImpl = class(TPasElement)
public
constructor Create(const AName: String; AParent: TPasElement); override;
destructor Destroy; override;
function ElementTypeName: String; override;
function TypeName: String; virtual;
ProcType: TPasProcedureType;
Locals: TList;
Body: TPasImplBlock;
end;
TPasConstructorImpl = class(TPasProcedureImpl)
public
function ElementTypeName: String; override;
function TypeName: String; override;
end;
TPasDestructorImpl = class(TPasProcedureImpl)
public
function ElementTypeName: String; override;
function TypeName: String; override;
end;
TPasImplElement = class(TPasElement)
end;
TPasImplCommand = class(TPasImplElement)
public
Command: String;
end;
TPasImplCommands = class(TPasImplElement)
public
constructor Create(const AName: String; AParent: TPasElement); override;
destructor Destroy; override;
Commands: TStrings;
end;
TPasImplIfElse = class(TPasImplElement)
public
destructor Destroy; override;
Condition: String;
IfBranch, ElseBranch: TPasImplElement;
end;
TPasImplForLoop = class(TPasImplElement)
public
destructor Destroy; override;
Variable: TPasVariable;
StartValue, EndValue: String;
Body: TPasImplElement;
end;
TPasImplBlock = class(TPasImplElement)
public
constructor Create(const AName: String; AParent: TPasElement); override;
destructor Destroy; override;
function AddCommand(const ACommand: String): TPasImplCommand;
function AddCommands: TPasImplCommands;
function AddIfElse(const ACondition: String): TPasImplIfElse;
function AddForLoop(AVar: TPasVariable;
const AStartValue, AEndValue: String): TPasImplForLoop;
Elements: TList; // TPasImplElement objects
end;
const
AccessNames: array[TArgumentAccess] of String[6] = ('', 'const ', 'var ', 'out ');
AllVisibilities: TPasMemberVisibilities =
[visDefault, visPrivate, visProtected, visPublic,
visPublished, visAutomated];
VisibilityNames: array[TPasMemberVisibility] of String = (
'default', 'private', 'protected', 'public', 'published', 'automated');
ObjKindNames: array[TPasObjKind] of String = (
'object', 'class', 'interface');
implementation
uses SysUtils;
{ Parse tree element type name functions }
function TPasElement.ElementTypeName: String; begin Result := SPasTreeElement end;
function TPasSection.ElementTypeName: String; begin Result := SPasTreeSection end;
function TPasModule.ElementTypeName: String; begin Result := SPasTreeModule end;
function TPasPackage.ElementTypeName: String; begin Result := SPasTreePackage end;
function TPasResString.ElementTypeName: String; begin Result := SPasTreeResString end;
function TPasType.ElementTypeName: String; begin Result := SPasTreeType end;
function TPasPointerType.ElementTypeName: String; begin Result := SPasTreePointerType end;
function TPasAliasType.ElementTypeName: String; begin Result := SPasTreeAliasType end;
function TPasTypeAliasType.ElementTypeName: String; begin Result := SPasTreeTypeAliasType end;
function TPasClassOfType.ElementTypeName: String; begin Result := SPasTreeClassOfType end;
function TPasRangeType.ElementTypeName: String; begin Result := SPasTreeRangeType end;
function TPasArrayType.ElementTypeName: String; begin Result := SPasTreeArrayType end;
function TPasEnumValue.ElementTypeName: String; begin Result := SPasTreeEnumValue end;
function TPasEnumType.ElementTypeName: String; begin Result := SPasTreeEnumType end;
function TPasSetType.ElementTypeName: String; begin Result := SPasTreeSetType end;
function TPasRecordType.ElementTypeName: String; begin Result := SPasTreeRecordType end;
function TPasArgument.ElementTypeName: String; begin Result := SPasTreeArgument end;
function TPasProcedureType.ElementTypeName: String; begin Result := SPasTreeProcedureType end;
function TPasResultElement.ElementTypeName: String; begin Result := SPasTreeResultElement end;
function TPasFunctionType.ElementTypeName: String; begin Result := SPasTreeFunctionType end;
function TPasUnresolvedTypeRef.ElementTypeName: String; begin Result := SPasTreeUnresolvedTypeRef end;
function TPasVariable.ElementTypeName: String; begin Result := SPasTreeVariable end;
function TPasConst.ElementTypeName: String; begin Result := SPasTreeConst end;
function TPasProperty.ElementTypeName: String; begin Result := SPasTreeProperty end;
function TPasOverloadedProc.ElementTypeName: String; begin Result := SPasTreeOverloadedProcedure end;
function TPasProcedure.ElementTypeName: String; begin Result := SPasTreeProcedure end;
function TPasFunction.ElementTypeName: String; begin Result := SPasTreeFunction end;
function TPasConstructor.ElementTypeName: String; begin Result := SPasTreeConstructor end;
function TPasDestructor.ElementTypeName: String; begin Result := SPasTreeDestructor end;
function TPasProcedureImpl.ElementTypeName: String; begin Result := SPasTreeProcedureImpl end;
function TPasConstructorImpl.ElementTypeName: String; begin Result := SPasTreeConstructorImpl end;
function TPasDestructorImpl.ElementTypeName: String; begin Result := SPasTreeDestructorImpl end;
function TPasClassType.ElementTypeName: String;
begin
case ObjKind of
okObject: Result := SPasTreeObjectType;
okClass: Result := SPasTreeClassType;
okInterface: Result := SPasTreeInterfaceType;
end;
end;
{ All other stuff: }
constructor TPasElement.Create(const AName: String; AParent: TPasElement);
begin
inherited Create;
FName := AName;
FParent := AParent;
end;
procedure TPasElement.AddRef;
begin
Inc(FRefCount);
end;
procedure TPasElement.Release;
begin
if FRefCount = 0 then
Free
else
Dec(FRefCount);
end;
function TPasElement.FullName: String;
var
p: TPasElement;
begin
Result := Name;
p := Parent;
while Assigned(p) and not p.InheritsFrom(TPasSection) do
begin
if (p.ClassType <> TPasOverloadedProc) and (Length(p.Name) > 0) then
if Length(Result) > 0 then
Result := p.Name + '.' + Result
else
Result := p.Name;
p := p.Parent;
end;
end;
function TPasElement.PathName: String;
var
p: TPasElement;
begin
Result := Name;
p := Parent;
while Assigned(p) do
begin
if (p.ClassType <> TPasOverloadedProc) and (Length(p.Name) > 0) then
if Length(Result) > 0 then
Result := p.Name + '.' + Result
else
Result := p.Name;
p := p.Parent;
end;
end;
function TPasElement.GetModule: TPasModule;
begin
if ClassType = TPasPackage then
Result := nil
else
begin
Result := TPasModule(Self);
while Assigned(Result) and not (Result.ClassType = TPasModule) do
Result := TPasModule(Result.Parent);
end;
end;
function TPasElement.GetDeclaration (full : boolean): String;
begin
if Full then
Result := Name
else
Result := '';
end;
constructor TPasSection.Create(const AName: String; AParent: TPasElement);
begin
inherited Create(AName, AParent);
UsesList := TList.Create;
Declarations := TList.Create;
ResStrings := TList.Create;
Types := TList.Create;
Consts := TList.Create;
Classes := TList.Create;
Functions := TList.Create;
Variables := TList.Create;
end;
destructor TPasSection.Destroy;
var
i: Integer;
begin
Variables.Free;
Functions.Free;
Classes.Free;
Consts.Free;
Types.Free;
ResStrings.Free;
for i := 0 to Declarations.Count - 1 do
TPasElement(Declarations[i]).Release;
Declarations.Free;
for i := 0 to UsesList.Count - 1 do
TPasType(UsesList[i]).Release;
UsesList.Free;
inherited Destroy;
end;
procedure TPasSection.AddUnitToUsesList(const AUnitName: String);
begin
UsesList.Add(TPasUnresolvedTypeRef.Create(AUnitName, Self));
end;
destructor TPasModule.Destroy;
begin
if Assigned(InterfaceSection) then
InterfaceSection.Release;
if Assigned(ImplementationSection) then
ImplementationSection.Release;
inherited Destroy;
end;
constructor TPasPackage.Create(const AName: String; AParent: TPasElement);
begin
if (Length(AName) > 0) and (AName[1] <> '#') then
inherited Create('#' + AName, AParent)
else
inherited Create(AName, AParent);
Modules := TList.Create;
end;
destructor TPasPackage.Destroy;
var
i: Integer;
begin
for i := 0 to Modules.Count - 1 do
TPasModule(Modules[i]).Release;
Modules.Free;
inherited Destroy;
end;
destructor TPasPointerType.Destroy;
begin
if Assigned(DestType) then
DestType.Release;
inherited Destroy;
end;
destructor TPasAliasType.Destroy;
begin
if Assigned(DestType) then
DestType.Release;
inherited Destroy;
end;
destructor TPasArrayType.Destroy;
begin
if Assigned(ElType) then
ElType.Release;
inherited Destroy;
end;
constructor TPasEnumType.Create(const AName: String; AParent: TPasElement);
begin
inherited Create(AName, AParent);
Values := TList.Create;
end;
destructor TPasEnumType.Destroy;
var
i: Integer;
begin
for i := 0 to Values.Count - 1 do
TPasEnumValue(Values[i]).Release;
Values.Free;
inherited Destroy;
end;
procedure TPasEnumType.GetEnumNames(Names: TStrings);
var
i: Integer;
begin
with Values do
begin
for i := 0 to Count - 2 do
Names.Add(TPasEnumValue(Items[i]).Name + ',');
if Count > 0 then
Names.Add(TPasEnumValue(Items[Count - 1]).Name);
end;
end;
destructor TPasSetType.Destroy;
begin
if Assigned(EnumType) then
EnumType.Release;
inherited Destroy;
end;
constructor TPasRecordType.Create(const AName: String; AParent: TPasElement);
begin
inherited Create(AName, AParent);
Members := TList.Create;
end;
destructor TPasRecordType.Destroy;
var
i: Integer;
begin
for i := 0 to Members.Count - 1 do
TPasVariable(Members[i]).Release;
Members.Free;
inherited Destroy;
end;
constructor TPasClassType.Create(const AName: String; AParent: TPasElement);
begin
inherited Create(AName, AParent);
Members := TList.Create;
end;
destructor TPasClassType.Destroy;
var
i: Integer;
begin
for i := 0 to Members.Count - 1 do
TPasElement(Members[i]).Release;
Members.Free;
if Assigned(AncestorType) then
AncestorType.Release;
inherited Destroy;
end;
destructor TPasArgument.Destroy;
begin
if Assigned(ArgType) then
ArgType.Release;
inherited Destroy;
end;
constructor TPasProcedureType.Create(const AName: String; AParent: TPasElement);
begin
inherited Create(AName, AParent);
Args := TList.Create;
end;
destructor TPasProcedureType.Destroy;
var
i: Integer;
begin
for i := 0 to Args.Count - 1 do
TPasArgument(Args[i]).Release;
Args.Free;
inherited Destroy;
end;
function TPasProcedureType.TypeName: String;
begin
Result := 'procedure';
end;
function TPasProcedureType.CreateArgument(const AName,
AUnresolvedTypeName: String): TPasArgument;
begin
Result := TPasArgument.Create(AName, Self);
Args.Add(Result);
Result.ArgType := TPasUnresolvedTypeRef.Create(AUnresolvedTypeName, Result);
end;
destructor TPasResultElement.Destroy;
begin
if Assigned(ResultType) then
ResultType.Release;
inherited Destroy;
end;
destructor TPasFunctionType.Destroy;
begin
if Assigned(ResultEl) then
ResultEl.Release;
inherited Destroy;
end;
function TPasFunctionType.TypeName: String;
begin
Result := 'function';
end;
constructor TPasUnresolvedTypeRef.Create(const AName: String; AParent: TPasElement);
begin
inherited Create(AName, nil);
end;
destructor TPasVariable.Destroy;
begin
{ Attention, in derived classes, VarType isn't necessarily set!
(e.g. in Constants) }
if Assigned(VarType) then
VarType.Release;
inherited Destroy;
end;
constructor TPasProperty.Create(const AName: String; AParent: TPasElement);
begin
inherited Create(AName, AParent);
Args := TList.Create;
end;
destructor TPasProperty.Destroy;
var
i: Integer;
begin
for i := 0 to Args.Count - 1 do
TPasArgument(Args[i]).Release;
Args.Free;
inherited Destroy;
end;
constructor TPasOverloadedProc.Create(const AName: String; AParent: TPasElement);
begin
inherited Create(AName, AParent);
Overloads := TList.Create;
end;
destructor TPasOverloadedProc.Destroy;
var
i: Integer;
begin
for i := 0 to Overloads.Count - 1 do
TPasProcedure(Overloads[i]).Release;
Overloads.Free;
inherited Destroy;
end;
function TPasOverloadedProc.TypeName: String;
begin
if Assigned(TPasProcedure(Overloads[0]).ProcType) then
Result := TPasProcedure(Overloads[0]).ProcType.TypeName
else
SetLength(Result, 0);
end;
destructor TPasProcedure.Destroy;
begin
if Assigned(ProcType) then
ProcType.Release;
inherited Destroy;
end;
function TPasProcedure.TypeName: String;
begin
Result := ProcType.TypeName;
end;
function TPasConstructor.TypeName: String;
begin
Result := 'constructor';
end;
function TPasDestructor.TypeName: String;
begin
Result := 'destructor';
end;
constructor TPasProcedureImpl.Create(const AName: String; AParent: TPasElement);
begin
inherited Create(AName, AParent);
Locals := TList.Create;
end;
destructor TPasProcedureImpl.Destroy;
var
i: Integer;
begin
if Assigned(Body) then
Body.Release;
for i := 0 to Locals.Count - 1 do
TPasElement(Locals[i]).Release;
Locals.Free;
if Assigned(ProcType) then
ProcType.Release;
inherited Destroy;
end;
function TPasProcedureImpl.TypeName: String;
begin
Result := ProcType.TypeName;
end;
function TPasConstructorImpl.TypeName: String;
begin
Result := 'constructor';
end;
function TPasDestructorImpl.TypeName: String;
begin
Result := 'destructor';
end;
constructor TPasImplCommands.Create(const AName: String; AParent: TPasElement);
begin
inherited Create(AName, AParent);
Commands := TStringList.Create;
end;
destructor TPasImplCommands.Destroy;
begin
Commands.Free;
inherited Destroy;
end;
destructor TPasImplIfElse.Destroy;
begin
if Assigned(IfBranch) then
IfBranch.Release;
if Assigned(ElseBranch) then
ElseBranch.Release;
inherited Destroy;
end;
destructor TPasImplForLoop.Destroy;
begin
if Assigned(Variable) then
Variable.Release;
if Assigned(Body) then
Body.Release;
inherited Destroy;
end;
constructor TPasImplBlock.Create(const AName: String; AParent: TPasElement);
begin
inherited Create(AName, AParent);
Elements := TList.Create;
end;
destructor TPasImplBlock.Destroy;
var
i: Integer;
begin
for i := 0 to Elements.Count - 1 do
TPasImplElement(Elements[i]).Release;
Elements.Free;
inherited Destroy;
end;
function TPasImplBlock.AddCommand(const ACommand: String): TPasImplCommand;
begin
Result := TPasImplCommand.Create('', Self);
Elements.Add(Result);
Result.Command := ACommand;
end;
function TPasImplBlock.AddCommands: TPasImplCommands;
begin
Result := TPasImplCommands.Create('', Self);
Elements.Add(Result);
end;
function TPasImplBlock.AddIfElse(const ACondition: String): TPasImplIfElse;
begin
Result := TPasImplIfElse.Create('', Self);
Elements.Add(Result);
Result.Condition := ACondition;
end;
function TPasImplBlock.AddForLoop(AVar: TPasVariable; const AStartValue,
AEndValue: String): TPasImplForLoop;
begin
Result := TPasImplForLoop.Create('', Self);
Elements.Add(Result);
Result.Variable := AVar;
Result.StartValue := AStartValue;
Result.EndValue := AEndValue;
end;
{ ---------------------------------------------------------------------
---------------------------------------------------------------------}
function TPasModule.GetDeclaration(full : boolean): String;
begin
Result := 'Unit ' + Name;
end;
{
function TPas.GetDeclaration : string;
begin
Result:=Name;
end;
}
function TPasResString.GetDeclaration (full : boolean) : string;
begin
Result:=Value;
If Full Then
Result:=Name+' = '+Result;
end;
function TPasPointerType.GetDeclaration (full : boolean) : string;
begin
Result:='^'+DestType.Name;
If Full then
Result:=Name+' = '+Result;
end;
function TPasAliasType.GetDeclaration (full : boolean) : string;
begin
Result:=DestType.Name;
If Full then
Result:=Name+' = '+Result;
end;
function TPasClassOfType.GetDeclaration (full : boolean) : string;
begin
Result:='Class of '+DestType.Name;
If Full then
Result:=Name+' = '+Result;
end;
function TPasRangeType.GetDeclaration (full : boolean) : string;
begin
Result:=RangeStart+'..'+RangeEnd;
If Full then
Result:=Name+' = '+Result;
end;
function TPasArrayType.GetDeclaration (full : boolean) : string;
begin
Result:='Array['+IndexRange+'] of ';
If Assigned(Eltype) then
Result:=Result+ElType.Name
else
Result:=Result+'const';
If Assigned(ELtype) then
If Full Then
Result:=Name+' = '+Result;
end;
Function IndentStrings(S : TStrings; indent : Integer) : String;
Var
I,CurrLen,CurrPos : Integer;
begin
Result:='';
CurrLen:=0;
CurrPos:=0;
For I:=0 to S.Count-1 do
begin
CurrLen:=Length(S[i]);
If (CurrLen+CurrPos)>72 then
begin
Result:=Result+LineEnding+StringOfChar(' ',Indent);
CurrPos:=Indent;
end;
Result:=Result+S[i];
CurrPos:=CurrPos+CurrLen;
end;
end;
function TPasEnumType.GetDeclaration (full : boolean) : string;
Var
S : TStringList;
i : integer;
begin
S:=TStringList.Create;
Try
If Full then
S.Add(Name+' = (')
else
S.Add('(');
GetEnumNames(S);
S[S.Count-1]:=S[S.Count-1]+')';
If Full then
Result:=IndentStrings(S,Length(Name)+4)
else
Result:=IndentStrings(S,1);
finally
S.Free;
end;
end;
function TPasSetType.GetDeclaration (full : boolean) : string;
Var
S : TStringList;
i : Integer;
begin
If EnumType is TPasEnumType then
begin
S:=TStringList.Create;
Try
If Full then
S.Add(Name+'= Set of (')
else
S.Add('Set of (');
TPasEnumType(EnumType).GetEnumNames(S);
S[S.Count-1]:=S[S.Count-1]+')';
I:=Pos('(',S[0]);
Result:=IndentStrings(S,i);
finally
S.Free;
end;
end
else
begin
Result:='Set of '+EnumType.Name;
If Full then
Result:=Name+' = '+Result;
end;
end;
function TPasRecordType.GetDeclaration (full : boolean) : string;
Var
S,T : TStringList;
temp : String;
I : integer;
begin
S:=TStringList.Create;
T:=TstringList.Create;
Try
Temp:='record';
If IsPacked then
Temp:='packed '+Temp;
If Full then
Temp:=Name+' = '+Temp;
S.Add(Temp);
For I:=0 to Members.Count-1 do
begin
Temp:=TPasVariable(Members[i]).GetDeclaration(True);
If Pos(LineEnding,Temp)>0 then
begin
T.Text:=Temp;
For I:=0 to T.Count-1 do
S.Add(' '+T[i]+';');
end
else
S.Add(' '+Temp+';');
end;
S.Add('end');
Result:=S.Text;
finally
S.free;
T.free;
end;
end;
procedure TPasProcedureType.GetArguments(List : TStrings);
Var
T : String;
I : Integer;
begin
For I:=0 to Args.Count-1 do
begin
T:=AccessNames[TPasArgument(Args[i]).Access];
T:=T+TPasArgument(Args[i]).GetDeclaration(True);
If I=0 then
T:='('+T;
If I<Args.Count-1 then
List.Add(T+';')
else
List.Add(T+')');
end;
end;
function TPasProcedureType.GetDeclaration (full : boolean) : string;
Var
S : TStringList;
begin
S:=TStringList.Create;
Try
If Full then
S.Add(Format('%s = ',[Name]));
S.Add(TypeName);
GetArguments(S);
If IsOfObject then
S.Add(' of object');
If Full then
Result:=IndentStrings(S,Length(S[0])+Length(S[1])+1)
else
Result:=IndentStrings(S,Length(S[0])+1);
finally
S.Free;
end;
end;
function TPasFunctionType.GetDeclaration (full : boolean) : string;
Var
S : TStringList;
T : String;
begin
S:=TStringList.Create;
Try
If Full then
S.Add(Format('%s = ',[Name]));
S.Add(TypeName);
GetArguments(S);
If Assigned(ResultEl) then
begin
T:=' : ';
If (ResultEl.ResultType.Name<>'') then
T:=T+ResultEl.ResultType.Name
else
T:=T+ResultEl.ResultType.GetDeclaration(False);
S.Add(T);
end;
If IsOfObject then
S.Add(' of object');
If Full then
Result:=IndentStrings(S,Length(S[0])+Length(S[1])+1)
else
Result:=IndentStrings(S,Length(S[0])+1);
finally
S.Free;
end;
end;
function TPasVariable.GetDeclaration (full : boolean) : string;
Const
Seps : Array[Boolean] of String = (' = ',' : ');
begin
If Assigned(VarType) then
begin
If VarType.Name='' then
Result:=VarType.GetDeclaration(False)
else
Result:=VarType.Name;
Result:=Result+Modifiers;
end
else
Result:=Value;
If Full then
Result:=Name+Seps[Assigned(VarType)]+Result;
end;
function TPasProperty.GetDeclaration (full : boolean) : string;
Var
S : String;
I : Integer;
begin
If Assigned(VarType) then
begin
If VarType.Name='' then
Result:=VarType.GetDeclaration(False)
else
Result:=VarType.Name;
end
else
Result:=Value;
S:='';
If Assigned(Args) and (Args.Count>0) then
begin
For I:=0 to Args.Count-1 do
begin
If (S<>'') then
S:=S+';';
S:=S+TPasElement(Args[i]).GetDeclaration(true);
end;
end;
If S<>'' then
S:='['+S+']'
else
S:=' ';
If Full then
Result:=Name+S+': '+Result;
If IsDefault then
Result:=Result+'; default'
end;
Procedure TPasProcedure.GetModifiers(List : TStrings);
Procedure DoAdd(B : Boolean; S : String);
begin
if B then
List.add('; '+S);
end;
begin
Doadd(IsVirtual,' Virtual');
DoAdd(IsDynamic,' Dynamic');
DoAdd(IsOverride,' Override');
DoAdd(IsAbstract,' Abstract');
DoAdd(IsOverload,' Overload');
DoAdd(IsMessage,' Message');
end;
function TPasProcedure.GetDeclaration (full : boolean) : string;
Var
S : TStringList;
Index : integer;
begin
S:=TStringList.Create;
try
If Full then
S.Add(TypeName+' '+Name);
ProcType.GetArguments(S);
GetModifiers(S);
Result:=IndentStrings(S,Length(S[0]));
finally
S.Free;
end;
end;
function TPasFunction.GetDeclaration (full : boolean) : string;
Var
S : TStringList;
T : String;
begin
S:=TStringList.Create;
try
If Full then
S.Add(TypeName+' '+Name);
ProcType.GetArguments(S);
If Assigned((Proctype as TPasFunctionType).ResultEl) then
With TPasFunctionType(ProcType).ResultEl.ResultType do
begin
T:=' : ';
If (Name<>'') then
T:=T+Name
else
T:=T+GetDeclaration(False);
S.Add(T);
end;
GetModifiers(S);
Result:=IndentStrings(S,Length(S[0]));
finally
S.Free;
end;
end;
function TPasArgument.GetDeclaration (full : boolean) : string;
begin
If Assigned(ArgType) then
begin
If ArgType.Name<>'' then
Result:=ArgType.Name
else
Result:=ArgType.GetDeclaration(False);
If Full then
Result:=Name+': '+Result;
end
else If Full then
Result:=Name
else
Result:='';
end;
end.
{
$Log$
Revision 1.2 2003-11-22 12:12:38 sg
* Parse tree elements now can store a line number and source file for the
position of their declaration
Revision 1.1 2003/03/13 21:47:42 sg
* First version as part of FCL
}