瀏覽代碼

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

J. Gareth "Curious Kit" Moreton 2 年之前
父節點
當前提交
a1abe51f2a
共有 1 個文件被更改,包括 34 次插入28 次删除
  1. 34 28
      compiler/defutil.pas

+ 34 - 28
compiler/defutil.pas

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