* Refactor of is_cyclic to use a linked list on the stack instead of a dynamic array

This commit is contained in:
J. Gareth "Curious Kit" Moreton 2022-12-04 20:32:45 +00:00 committed by FPK
parent 4b659175d9
commit a1abe51f2a

View File

@ -230,7 +230,7 @@ interface
function is_voidpointer(p : tdef) : boolean; function is_voidpointer(p : tdef) : boolean;
{# Returns true if p is a cyclic reference (refers to itself at some point via pointer or array) } {# Returns true if p is a cyclic reference (refers to itself at some point via pointer or array) }
function is_cyclic(p : tdef): Boolean; function is_cyclic(p : tdef): Boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
{# Returns true, if definition is a float } {# Returns true, if definition is a float }
function is_fpu(def : tdef) : boolean; function is_fpu(def : tdef) : boolean;
@ -1033,41 +1033,47 @@ implementation
end; end;
{ true, if p is a cyclic reference (refers to itself at some point via pointer or array) } type
function is_cyclic(p : tdef): Boolean; PDefListItem = ^TDefListItem;
var TDefListItem = record
DefList: array of TDef; Next: PDefListItem;
CurrentTop: Integer; Def: tdef;
end;
function is_cyclic_internal(def: tdef): Boolean; { See "is_cyclic" below }
function is_cyclic_internal(const def: tdef; const first: PDefListItem): Boolean;
var var
X: Integer; thisdef: TDefListItem;
curitem: PDefListItem;
begin begin
if not (def.typ in [arraydef, pointerdef]) then if not (def.typ in [arraydef, pointerdef]) then
Exit(False); Exit(False);
CurrentTop := Length(DefList); curitem := first;
while assigned(curitem) do
{ Check to see if the definition has appeared already } begin
for X := 0 to CurrentTop - 1 do if curitem^.Def = def then
if def = DefList[X] then
Exit(True); Exit(True);
curitem := curitem^.Next;
end;
SetLength(DefList, CurrentTop + 1); thisdef.Next := first;
DefList[CurrentTop] := def; thisdef.Def := def;
case def.typ of case def.typ of
arraydef: arraydef:
Result := is_cyclic_internal(tarraydef(def).elementdef); Result := is_cyclic_internal(tarraydef(def).elementdef, @thisdef);
pointerdef: pointerdef:
Result := is_cyclic_internal(tabstractpointerdef(def).pointeddef); Result := is_cyclic_internal(tabstractpointerdef(def).pointeddef, @thisdef);
else else
InternalError(2022120301); InternalError(2022120301);
end; end;
end; end;
{ true, if p is a cyclic reference (refers to itself at some point via pointer or array) }
function is_cyclic(p : tdef): Boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
begin begin
Result := is_cyclic_internal(p); Result := is_cyclic_internal(p, nil);
end; end;
{ true, if def is a 8 bit int type } { true, if def is a 8 bit int type }