mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-12 23:29:31 +02:00
785 lines
17 KiB
ObjectPascal
785 lines
17 KiB
ObjectPascal
{
|
|
pas2jni - JNI bridge generator for Pascal.
|
|
|
|
Copyright (c) 2013 by Yury Sidorov.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
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. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
****************************************************************************}
|
|
|
|
unit def;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, contnrs;
|
|
|
|
type
|
|
TDefType = (dtNone, dtUnit, dtClass, dtProc, dtField, dtProp, dtParam, dtVar,
|
|
dtType, dtConst, dtProcType, dtEnum, dtSet, dtPointer, dtArray,
|
|
dtJniObject, dtJniEnv, dtClassRef);
|
|
|
|
TDefClass = class of TDef;
|
|
{ TDef }
|
|
|
|
TDef = class
|
|
private
|
|
FAliasName: string;
|
|
FRefCnt: integer;
|
|
FItems: TObjectList;
|
|
FInSetUsed: boolean;
|
|
procedure CheckItems;
|
|
function GetAliasName: string;
|
|
function GetCount: integer;
|
|
function GetIsUsed: boolean;
|
|
function GetItem(Index: Integer): TDef;
|
|
procedure SetItem(Index: Integer; const AValue: TDef);
|
|
protected
|
|
procedure SetIsUsed(const AValue: boolean); virtual;
|
|
function ResolveDef(d: TDef; ExpectedClass: TDefClass = nil): TDef;
|
|
procedure AddRef;
|
|
procedure DecRef;
|
|
procedure SetExtUsed(ExtDef: TDef; AUsed: boolean; var HasRef: boolean);
|
|
function ShouldUseChild(d: TDef): boolean; virtual;
|
|
public
|
|
DefType: TDefType;
|
|
DefId: integer;
|
|
SymId: integer;
|
|
Name: string;
|
|
Parent: TDef;
|
|
Tag: integer;
|
|
IsPrivate: boolean;
|
|
|
|
constructor Create; virtual; overload;
|
|
constructor Create(AParent: TDef; AType: TDefType); virtual; overload;
|
|
destructor Destroy; override;
|
|
function Add(ADef: TDef): integer;
|
|
function Insert(Index: integer; ADef: TDef): integer;
|
|
function FindDef(ADefId: integer; Recursive: boolean = True): TDef;
|
|
procedure ResolveDefs; virtual;
|
|
procedure SetNotUsed;
|
|
function GetRefDef: TDef; virtual;
|
|
function GetRefDef2: TDef; virtual;
|
|
property Items[Index: Integer]: TDef read GetItem write SetItem; default;
|
|
property Count: integer read GetCount;
|
|
property IsUsed: boolean read GetIsUsed write SetIsUsed;
|
|
property RefCnt: integer read FRefCnt;
|
|
property AliasName: string read GetAliasName write FAliasName;
|
|
end;
|
|
|
|
TClassType = (ctClass, ctInterface, ctObject, ctRecord);
|
|
|
|
{ TClassDef }
|
|
|
|
TClassDef = class(TDef)
|
|
private
|
|
FHasClassRef: boolean;
|
|
protected
|
|
procedure SetIsUsed(const AValue: boolean); override;
|
|
function ShouldUseChild(d: TDef): boolean; override;
|
|
public
|
|
CType: TClassType;
|
|
AncestorClass: TClassDef;
|
|
HasAbstractMethods: boolean;
|
|
HasReplacedItems: boolean;
|
|
ImplementsReplacedItems: boolean;
|
|
Size: integer;
|
|
IID: string;
|
|
procedure ResolveDefs; override;
|
|
function GetRefDef: TDef; override;
|
|
end;
|
|
|
|
TBasicType = (btVoid, btByte, btShortInt, btWord, btSmallInt, btLongWord, btLongInt, btInt64,
|
|
btSingle, btDouble, btString, btWideString, btBoolean, btChar, btWideChar, btEnum,
|
|
btGuid);
|
|
|
|
{ TTypeDef }
|
|
|
|
TTypeDef = class(TDef)
|
|
protected
|
|
procedure SetIsUsed(const AValue: boolean); override;
|
|
public
|
|
BasicType: TBasicType;
|
|
end;
|
|
|
|
{ TPointerDef }
|
|
|
|
TPointerDef = class(TDef)
|
|
private
|
|
FHasPtrRef: boolean;
|
|
protected
|
|
procedure SetIsUsed(const AValue: boolean); override;
|
|
public
|
|
PtrType: TDef;
|
|
procedure ResolveDefs; override;
|
|
function IsObjPtr: boolean;
|
|
function GetRefDef: TDef; override;
|
|
end;
|
|
|
|
{ TReplDef }
|
|
|
|
TReplDef = class(TDef)
|
|
protected
|
|
procedure SetIsUsed(const AValue: boolean); override;
|
|
public
|
|
IsReplaced: boolean;
|
|
IsReplImpl: boolean;
|
|
ReplacedItem: TReplDef;
|
|
|
|
function CanReplaced: boolean; virtual;
|
|
function IsReplacedBy(d: TReplDef): boolean; virtual;
|
|
procedure CheckReplaced;
|
|
end;
|
|
|
|
TVarOption = (voRead, voWrite, voConst, voVar, voOut);
|
|
TVarOptions = set of TVarOption;
|
|
|
|
{ TVarDef }
|
|
|
|
TVarDef = class(TReplDef)
|
|
private
|
|
FHasTypeRef: boolean;
|
|
protected
|
|
procedure SetIsUsed(const AValue: boolean); override;
|
|
public
|
|
VarOpt: TVarOptions;
|
|
VarType: TDef;
|
|
constructor Create; override;
|
|
procedure ResolveDefs; override;
|
|
function IsReplacedBy(d: TReplDef): boolean; override;
|
|
function CanReplaced: boolean; override;
|
|
function GetRefDef: TDef; override;
|
|
end;
|
|
|
|
TProcType = (ptProcedure, ptFunction, ptConstructor, ptDestructor);
|
|
TProcOption = (poOverride, poOverload, poMethodPtr, poPrivate, poProtected, poClassMethod);
|
|
TProcOptions = set of TProcOption;
|
|
|
|
{ TProcDef }
|
|
|
|
TProcDef = class(TReplDef)
|
|
private
|
|
FHasRetTypeRef: boolean;
|
|
protected
|
|
procedure SetIsUsed(const AValue: boolean); override;
|
|
function ShouldUseChild(d: TDef): boolean; override;
|
|
public
|
|
ProcType: TProcType;
|
|
ReturnType: TDef;
|
|
ProcOpt: TProcOptions;
|
|
procedure ResolveDefs; override;
|
|
function IsReplacedBy(d: TReplDef): boolean; override;
|
|
function CanReplaced: boolean; override;
|
|
function GetRefDef: TDef; override;
|
|
end;
|
|
|
|
TUnitDef = class(TDef)
|
|
public
|
|
OS: string;
|
|
CPU: string;
|
|
IntfCRC: string;
|
|
PPUVer: integer;
|
|
UsedUnits: array of TUnitDef;
|
|
Processed: boolean;
|
|
IsUnitUsed: boolean;
|
|
end;
|
|
|
|
TConstDef = class(TVarDef)
|
|
public
|
|
Value: string;
|
|
end;
|
|
|
|
{ TSetDef }
|
|
|
|
TSetDef = class(TDef)
|
|
private
|
|
FHasElTypeRef: boolean;
|
|
protected
|
|
procedure SetIsUsed(const AValue: boolean); override;
|
|
public
|
|
Size: integer;
|
|
Base: integer;
|
|
ElMax: integer;
|
|
ElType: TTypeDef;
|
|
function GetRefDef: TDef; override;
|
|
end;
|
|
|
|
{ TArrayDef }
|
|
|
|
TArrayDef = class(TDef)
|
|
private
|
|
FHasElTypeRef: boolean;
|
|
FHasRTypeRef: boolean;
|
|
protected
|
|
procedure SetIsUsed(const AValue: boolean); override;
|
|
public
|
|
ElType: TDef;
|
|
RangeType: TDef;
|
|
RangeLow, RangeHigh: integer;
|
|
function GetRefDef: TDef; override;
|
|
function GetRefDef2: TDef; override;
|
|
end;
|
|
|
|
{ TClassRefDef }
|
|
|
|
TClassRefDef = class(TDef)
|
|
private
|
|
FHasClassRef: boolean;
|
|
protected
|
|
procedure SetIsUsed(const AValue: boolean); override;
|
|
public
|
|
ClassRef: TDef;
|
|
procedure ResolveDefs; override;
|
|
function GetRefDef: TDef; override;
|
|
end;
|
|
|
|
|
|
const
|
|
ReplDefs = [dtField, dtProp, dtProc];
|
|
|
|
var
|
|
OnCanUseDef: function (def, refdef: TDef): boolean;
|
|
|
|
implementation
|
|
|
|
function IsSameType(t1, t2: TDef): boolean;
|
|
begin
|
|
Result:=t1 = t2;
|
|
if Result then
|
|
exit;
|
|
if (t1 = nil) or (t2 = nil) or (t1.DefType <> t2.DefType) then
|
|
exit;
|
|
if t1.DefType <> dtType then
|
|
exit;
|
|
Result:=TTypeDef(t1).BasicType = TTypeDef(t2).BasicType;
|
|
end;
|
|
|
|
{ TClassRefDef }
|
|
|
|
procedure TClassRefDef.SetIsUsed(const AValue: boolean);
|
|
begin
|
|
inherited SetIsUsed(AValue);
|
|
SetExtUsed(ClassRef, AValue, FHasClassRef);
|
|
end;
|
|
|
|
procedure TClassRefDef.ResolveDefs;
|
|
begin
|
|
inherited ResolveDefs;
|
|
ClassRef:=ResolveDef(ClassRef);
|
|
end;
|
|
|
|
function TClassRefDef.GetRefDef: TDef;
|
|
begin
|
|
Result:=ClassRef;
|
|
end;
|
|
|
|
{ TArrayDef }
|
|
|
|
procedure TArrayDef.SetIsUsed(const AValue: boolean);
|
|
begin
|
|
inherited SetIsUsed(AValue);
|
|
SetExtUsed(ElType, AValue, FHasElTypeRef);
|
|
SetExtUsed(RangeType, AValue, FHasRTypeRef);
|
|
end;
|
|
|
|
function TArrayDef.GetRefDef: TDef;
|
|
begin
|
|
Result:=ElType;
|
|
end;
|
|
|
|
function TArrayDef.GetRefDef2: TDef;
|
|
begin
|
|
Result:=RangeType;
|
|
end;
|
|
|
|
{ TPointerDef }
|
|
|
|
procedure TPointerDef.SetIsUsed(const AValue: boolean);
|
|
begin
|
|
if IsObjPtr then begin
|
|
inherited SetIsUsed(AValue);
|
|
SetExtUsed(PtrType, AValue, FHasPtrRef);
|
|
end
|
|
else
|
|
if AValue then
|
|
AddRef
|
|
else
|
|
DecRef;
|
|
end;
|
|
|
|
procedure TPointerDef.ResolveDefs;
|
|
begin
|
|
inherited ResolveDefs;
|
|
PtrType:=ResolveDef(PtrType);
|
|
end;
|
|
|
|
function TPointerDef.IsObjPtr: boolean;
|
|
begin
|
|
Result:=(PtrType <> nil) and (PtrType.DefType in [dtClass]);
|
|
end;
|
|
|
|
function TPointerDef.GetRefDef: TDef;
|
|
begin
|
|
Result:=PtrType;
|
|
end;
|
|
|
|
{ TReplDef }
|
|
|
|
procedure TReplDef.SetIsUsed(const AValue: boolean);
|
|
var
|
|
i: integer;
|
|
begin
|
|
i:=RefCnt;
|
|
inherited SetIsUsed(AValue);
|
|
if (i = 0) and (RefCnt > 0) then
|
|
CheckReplaced;
|
|
end;
|
|
|
|
function TReplDef.CanReplaced: boolean;
|
|
begin
|
|
Result:=not (IsPrivate or (Parent = nil) or (Parent.DefType <> dtClass));
|
|
end;
|
|
|
|
function TReplDef.IsReplacedBy(d: TReplDef): boolean;
|
|
begin
|
|
Result:=d.CanReplaced and (CompareText(Name, d.Name) = 0);
|
|
end;
|
|
|
|
procedure TReplDef.CheckReplaced;
|
|
|
|
function _Scan(cls: TClassDef): boolean;
|
|
var
|
|
i: integer;
|
|
d: TReplDef;
|
|
c: TClassDef;
|
|
begin
|
|
Result:=False;
|
|
c:=cls.AncestorClass;
|
|
if c = nil then
|
|
exit;
|
|
for i:=0 to c.Count - 1 do begin
|
|
d:=TReplDef(c[i]);
|
|
if (d.DefType in ReplDefs) and IsReplacedBy(d) then begin
|
|
d.IsReplaced:=True;
|
|
ReplacedItem:=d;
|
|
Result:=True;
|
|
break;
|
|
end;
|
|
end;
|
|
if not Result then
|
|
Result:=_Scan(c);
|
|
if Result then begin
|
|
cls.ImplementsReplacedItems:=True;
|
|
c.HasReplacedItems:=True;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if not CanReplaced then
|
|
exit;
|
|
if _Scan(TClassDef(Parent)) then
|
|
IsReplImpl:=True;
|
|
end;
|
|
|
|
{ TSetDef }
|
|
|
|
procedure TSetDef.SetIsUsed(const AValue: boolean);
|
|
begin
|
|
inherited SetIsUsed(AValue);
|
|
SetExtUsed(ElType, AValue, FHasElTypeRef);
|
|
end;
|
|
|
|
function TSetDef.GetRefDef: TDef;
|
|
begin
|
|
Result:=ElType;
|
|
end;
|
|
|
|
{ TTypeDef }
|
|
|
|
procedure TTypeDef.SetIsUsed(const AValue: boolean);
|
|
begin
|
|
if BasicType in [btEnum] then
|
|
inherited SetIsUsed(AValue)
|
|
else
|
|
if AValue then
|
|
AddRef
|
|
else
|
|
DecRef;
|
|
end;
|
|
|
|
{ TProcDef }
|
|
|
|
procedure TProcDef.SetIsUsed(const AValue: boolean);
|
|
var
|
|
i: integer;
|
|
begin
|
|
if IsPrivate then
|
|
exit;
|
|
if AValue and (RefCnt = 0) then begin
|
|
for i:=0 to Count - 1 do
|
|
if (Items[i].DefType = dtParam) and (TVarDef(Items[i]).VarType = nil) then
|
|
exit; // If procedure has unsupported parameters, don't use it
|
|
end;
|
|
inherited SetIsUsed(AValue);
|
|
if ReturnType <> Parent then
|
|
SetExtUsed(ReturnType, AValue, FHasRetTypeRef);
|
|
end;
|
|
|
|
function TProcDef.ShouldUseChild(d: TDef): boolean;
|
|
begin
|
|
Result:=d.DefType in [dtParam];
|
|
end;
|
|
|
|
procedure TProcDef.ResolveDefs;
|
|
begin
|
|
inherited ResolveDefs;
|
|
ReturnType:=ResolveDef(ReturnType);
|
|
end;
|
|
|
|
function TProcDef.IsReplacedBy(d: TReplDef): boolean;
|
|
var
|
|
i: integer;
|
|
p: TProcDef;
|
|
begin
|
|
Result:=False;
|
|
if d.DefType <> dtProc then
|
|
exit;
|
|
p:=TProcDef(d);
|
|
if (Count = p.Count) and inherited IsReplacedBy(p) then begin
|
|
// Check parameter types
|
|
for i:=0 to Count - 1 do
|
|
if not IsSameType(TVarDef(Items[i]).VarType, TVarDef(p.Items[i]).VarType) then
|
|
exit;
|
|
Result:=True;
|
|
end;
|
|
end;
|
|
|
|
function TProcDef.CanReplaced: boolean;
|
|
begin
|
|
Result:=inherited CanReplaced and (ProcType = ptFunction);
|
|
end;
|
|
|
|
function TProcDef.GetRefDef: TDef;
|
|
begin
|
|
Result:=ReturnType;
|
|
end;
|
|
|
|
{ TClassDef }
|
|
|
|
procedure TClassDef.SetIsUsed(const AValue: boolean);
|
|
begin
|
|
inherited SetIsUsed(AValue);
|
|
SetExtUsed(AncestorClass, AValue, FHasClassRef);
|
|
end;
|
|
|
|
function TClassDef.ShouldUseChild(d: TDef): boolean;
|
|
begin
|
|
Result:=d.DefType in [dtProc, dtField, dtProp];
|
|
end;
|
|
|
|
procedure TClassDef.ResolveDefs;
|
|
begin
|
|
inherited ResolveDefs;
|
|
AncestorClass:=TClassDef(ResolveDef(AncestorClass, TClassDef));
|
|
end;
|
|
|
|
function TClassDef.GetRefDef: TDef;
|
|
begin
|
|
Result:=AncestorClass;
|
|
end;
|
|
|
|
{ TVarDef }
|
|
|
|
procedure TVarDef.SetIsUsed(const AValue: boolean);
|
|
var
|
|
ptr, d: TDef;
|
|
begin
|
|
if IsPrivate then
|
|
exit;
|
|
inherited SetIsUsed(AValue);
|
|
// Detect circular pointers
|
|
if (VarType <> nil) and (VarType.DefType = dtPointer) and (VarType.RefCnt > 0) then begin
|
|
ptr:=TPointerDef(VarType).PtrType;
|
|
if ptr <> nil then begin
|
|
d:=Self;
|
|
while d <> nil do begin
|
|
if d = ptr then
|
|
exit;
|
|
d:=d.Parent;;
|
|
end;
|
|
end;
|
|
end;
|
|
SetExtUsed(VarType, AValue, FHasTypeRef);
|
|
end;
|
|
|
|
procedure TVarDef.ResolveDefs;
|
|
begin
|
|
inherited ResolveDefs;
|
|
VarType:=ResolveDef(VarType);
|
|
end;
|
|
|
|
function TVarDef.IsReplacedBy(d: TReplDef): boolean;
|
|
begin
|
|
Result:=(d.DefType in [dtProp, dtField]) and not IsSameType(VarType, TVarDef(d).VarType) and inherited IsReplacedBy(d);
|
|
end;
|
|
|
|
function TVarDef.CanReplaced: boolean;
|
|
begin
|
|
Result:=(voRead in VarOpt) and inherited CanReplaced;
|
|
end;
|
|
|
|
function TVarDef.GetRefDef: TDef;
|
|
begin
|
|
Result:=VarType;
|
|
end;
|
|
|
|
constructor TVarDef.Create;
|
|
begin
|
|
inherited Create;
|
|
VarOpt:=[voRead, voWrite];
|
|
end;
|
|
|
|
{ TDef }
|
|
|
|
procedure TDef.CheckItems;
|
|
begin
|
|
if FItems = nil then
|
|
FItems:=TObjectList.Create(True);
|
|
end;
|
|
|
|
function TDef.GetAliasName: string;
|
|
begin
|
|
if FAliasName <> '' then
|
|
Result:=FAliasName
|
|
else
|
|
Result:=Name;
|
|
end;
|
|
|
|
function TDef.GetCount: integer;
|
|
begin
|
|
if FItems = nil then
|
|
Result:=0
|
|
else begin
|
|
CheckItems;
|
|
Result:=FItems.Count;
|
|
end;
|
|
end;
|
|
|
|
function TDef.GetIsUsed: boolean;
|
|
begin
|
|
Result:=FRefCnt > 0;
|
|
end;
|
|
|
|
function TDef.GetItem(Index: Integer): TDef;
|
|
begin
|
|
CheckItems;
|
|
Result:=TDef(FItems[Index]);
|
|
end;
|
|
|
|
procedure TDef.SetIsUsed(const AValue: boolean);
|
|
var
|
|
i: integer;
|
|
f: boolean;
|
|
d: TDef;
|
|
begin
|
|
if FInSetUsed or (DefType = dtNone) or IsPrivate then
|
|
exit;
|
|
if AValue then begin
|
|
if Assigned(OnCanUseDef) and not OnCanUseDef(Self, Parent) then
|
|
exit;
|
|
AddRef;
|
|
f:=FRefCnt = 1;
|
|
end
|
|
else begin
|
|
if FRefCnt = 0 then
|
|
exit;
|
|
DecRef;
|
|
f:=FRefCnt = 0;
|
|
end;
|
|
if f then begin
|
|
// Update used mark of children only once
|
|
FInSetUsed:=True;
|
|
try
|
|
for i:=0 to Count - 1 do begin
|
|
d:=Items[i];
|
|
if ShouldUseChild(d) then
|
|
d.IsUsed:=AValue;
|
|
end;
|
|
finally
|
|
FInSetUsed:=False;
|
|
end;
|
|
// Update parent's used mark
|
|
if (Parent <> nil) and (Parent.DefType = dtUnit) then
|
|
if AValue then
|
|
Parent.AddRef
|
|
else
|
|
Parent.DecRef;
|
|
end;
|
|
end;
|
|
|
|
function TDef.ResolveDef(d: TDef; ExpectedClass: TDefClass): TDef;
|
|
begin
|
|
if (d = nil) or (d.DefType <> dtNone) then
|
|
Result:=d
|
|
else begin
|
|
Result:=d.Parent.FindDef(d.DefId);
|
|
if (ExpectedClass <> nil) and (Result <> nil) then
|
|
if not (Result is ExpectedClass) then
|
|
raise Exception.CreateFmt('Unexpected class. Expected: %s, got: %s', [ExpectedClass.ClassName, Result.ClassName]);
|
|
|
|
end;
|
|
end;
|
|
|
|
procedure TDef.AddRef;
|
|
begin
|
|
Inc(FRefCnt);
|
|
end;
|
|
|
|
procedure TDef.DecRef;
|
|
begin
|
|
if FRefCnt > 0 then
|
|
Dec(FRefCnt);
|
|
end;
|
|
|
|
procedure TDef.SetExtUsed(ExtDef: TDef; AUsed: boolean; var HasRef: boolean);
|
|
var
|
|
OldRefCnt: integer;
|
|
begin
|
|
if ExtDef = nil then
|
|
exit;
|
|
if AUsed then begin
|
|
if HasRef then
|
|
exit;
|
|
if Assigned(OnCanUseDef) and not OnCanUseDef(ExtDef, Self) then
|
|
exit;
|
|
OldRefCnt:=ExtDef.RefCnt;
|
|
ExtDef.IsUsed:=True;
|
|
HasRef:=OldRefCnt <> ExtDef.RefCnt;
|
|
end
|
|
else
|
|
if HasRef and not IsUsed then begin
|
|
ExtDef.IsUsed:=False;
|
|
HasRef:=False;
|
|
end;
|
|
end;
|
|
|
|
function TDef.ShouldUseChild(d: TDef): boolean;
|
|
begin
|
|
Result:=True;
|
|
end;
|
|
|
|
procedure TDef.SetItem(Index: Integer; const AValue: TDef);
|
|
begin
|
|
CheckItems;
|
|
FItems[Index]:=AValue;
|
|
end;
|
|
|
|
constructor TDef.Create;
|
|
begin
|
|
DefId:=-1;
|
|
DefType:=dtNone;
|
|
end;
|
|
|
|
constructor TDef.Create(AParent: TDef; AType: TDefType);
|
|
begin
|
|
Create;
|
|
if AParent <> nil then
|
|
AParent.Add(Self);
|
|
DefType:=AType;
|
|
end;
|
|
|
|
destructor TDef.Destroy;
|
|
begin
|
|
FreeAndNil(FItems);
|
|
if (Parent <> nil) and (Parent.FItems <> nil) then begin
|
|
Parent.FItems.OwnsObjects:=False;
|
|
try
|
|
Parent.FItems.Remove(Self);
|
|
finally
|
|
Parent.FItems.OwnsObjects:=True;
|
|
end;
|
|
end;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TDef.Add(ADef: TDef): integer;
|
|
begin
|
|
Result:=Insert(Count, ADef);
|
|
end;
|
|
|
|
function TDef.Insert(Index: integer; ADef: TDef): integer;
|
|
begin
|
|
CheckItems;
|
|
Result:=Index;
|
|
FItems.Insert(Result, ADef);
|
|
ADef.Parent:=Self;
|
|
end;
|
|
|
|
function TDef.FindDef(ADefId: integer; Recursive: boolean): TDef;
|
|
|
|
function _Find(d: TDef): TDef;
|
|
var
|
|
i: integer;
|
|
begin
|
|
Result:=nil;
|
|
for i:=0 to d.Count - 1 do
|
|
with d[i] do begin
|
|
if (DefType <> dtNone) and (DefId = ADefId) then begin
|
|
Result:=d[i];
|
|
break;
|
|
end;
|
|
if Recursive and (Count > 0) then begin
|
|
Result:=_Find(d[i]);
|
|
if Result <> nil then
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
Result:=_Find(Self);
|
|
end;
|
|
|
|
procedure TDef.ResolveDefs;
|
|
var
|
|
i: integer;
|
|
begin
|
|
for i:=0 to Count - 1 do
|
|
Items[i].ResolveDefs;
|
|
end;
|
|
|
|
procedure TDef.SetNotUsed;
|
|
begin
|
|
if FRefCnt = 0 then
|
|
exit;
|
|
FRefCnt:=1;
|
|
IsUsed:=False;
|
|
end;
|
|
|
|
function TDef.GetRefDef: TDef;
|
|
begin
|
|
Result:=nil;
|
|
end;
|
|
|
|
function TDef.GetRefDef2: TDef;
|
|
begin
|
|
Result:=nil;
|
|
end;
|
|
|
|
end.
|
|
|