Browse Source

Preparations for upcoming work on generics:
+ symconst.pas: add a new flag to symtables to mark them as containing at least one generic (will be used to decide whether an expression like "Foo<Bar" should even remotely be considered a specialization)
* utils/ppudump.pp: respect the new flag
* pdecl.pas, types_dec: add the flag for every generic we have parsed
* pgenutil.pas, generate_specialization: add the flag to the specialize symtable if a nested generic set it for the temporary symtable (does not happen currently, but will in the future when nested generics are supported)
+ keep references to all generic para symbols in the def; this way the symtable containing the type parameters does not need to be walked every time we need to do something with the parameters

git-svn-id: trunk@22379 -

svenbarth 13 years ago
parent
commit
29c71d39ac
5 changed files with 50 additions and 2 deletions
  1. 3 0
      compiler/pdecl.pas
  2. 5 0
      compiler/pgenutil.pas
  3. 2 1
      compiler/symconst.pas
  4. 38 0
      compiler/symdef.pas
  5. 2 1
      compiler/utils/ppudump.pp

+ 3 - 0
compiler/pdecl.pas

@@ -619,6 +619,9 @@ implementation
               { update the definition of the type }
               { update the definition of the type }
               if assigned(hdef) then
               if assigned(hdef) then
                 begin
                 begin
+                  if df_generic in hdef.defoptions then
+                    { flag parent symtables that they now contain a generic }
+                    hdef.owner.includeoption(sto_has_generic);
                   if assigned(hdef.typesym) then
                   if assigned(hdef.typesym) then
                     begin
                     begin
                       istyperenaming:=true;
                       istyperenaming:=true;

+ 5 - 0
compiler/pgenutil.pas

@@ -478,6 +478,11 @@ uses
                 tdef(item).ChangeOwner(specializest);
                 tdef(item).ChangeOwner(specializest);
               end;
               end;
 
 
+            { if a generic was declared during the specialization we need to
+              flag the specialize symtable accordingly }
+            if sto_has_generic in tempst.tableoptions then
+              specializest.includeoption(sto_has_generic);
+
             tempst.free;
             tempst.free;
 
 
             specialization_done(state);
             specialization_done(state);

+ 2 - 1
compiler/symconst.pas

@@ -497,7 +497,8 @@ type
 
 
   { options for symtables }
   { options for symtables }
   tsymtableoption = (
   tsymtableoption = (
-    sto_has_helper        { contains at least one helper symbol }
+    sto_has_helper,       { contains at least one helper symbol }
+    sto_has_generic       { contains at least one generic symbol }
   );
   );
   tsymtableoptions = set of tsymtableoption;
   tsymtableoptions = set of tsymtableoption;
 
 

+ 38 - 0
compiler/symdef.pas

@@ -53,6 +53,7 @@ interface
        tstoreddef = class(tdef)
        tstoreddef = class(tdef)
        protected
        protected
           typesymderef  : tderef;
           typesymderef  : tderef;
+          procedure fillgenericparas(symtable:tsymtable);
        public
        public
 {$ifdef EXTDEBUG}
 {$ifdef EXTDEBUG}
           fileinfo   : tfileposinfo;
           fileinfo   : tfileposinfo;
@@ -61,6 +62,9 @@ interface
           genericdef      : tstoreddef;
           genericdef      : tstoreddef;
           genericdefderef : tderef;
           genericdefderef : tderef;
           generictokenbuf : tdynamicarray;
           generictokenbuf : tdynamicarray;
+          { this list contains references to the symbols that make up the
+            generic parameters; the symbols are not owned by this list }
+          genericparas    : tfphashobjectlist;
           constructor create(dt:tdeftyp);
           constructor create(dt:tdeftyp);
           constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
           constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
           destructor  destroy;override;
           destructor  destroy;override;
@@ -84,6 +88,10 @@ interface
           function is_fpuregable : boolean;
           function is_fpuregable : boolean;
           { generics }
           { generics }
           procedure initgeneric;
           procedure initgeneric;
+          { this function can be used to determine whether a def is really a
+            generic declaration or just a normal type declared inside another
+            generic }
+          function is_generic:boolean;inline;
        private
        private
           savesize  : asizeuint;
           savesize  : asizeuint;
        end;
        end;
@@ -1330,6 +1338,23 @@ implementation
                      TDEF (base class for definitions)
                      TDEF (base class for definitions)
 ****************************************************************************}
 ****************************************************************************}
 
 
+    procedure tstoreddef.fillgenericparas(symtable: tsymtable);
+      var
+        sym : tsym;
+        i : longint;
+      begin
+        if not assigned(symtable) then
+          internalerror(2012091201);
+        if [df_generic,df_specialization]*defoptions=[] then
+          exit;
+        for i:=0 to symtable.symlist.count-1 do
+          begin
+            sym:=tsym(symtable.symlist[i]);
+            if sp_generic_para in sym.symoptions then
+              genericparas.Add(sym.name,sym);
+          end;
+      end;
+
     constructor tstoreddef.create(dt:tdeftyp);
     constructor tstoreddef.create(dt:tdeftyp);
       var
       var
         insertstack : psymtablestackitem;
         insertstack : psymtablestackitem;
@@ -1341,6 +1366,7 @@ implementation
 {$endif}
 {$endif}
          generictokenbuf:=nil;
          generictokenbuf:=nil;
          genericdef:=nil;
          genericdef:=nil;
+         genericparas:=tfphashobjectlist.create(false);
 
 
          { Don't register forwarddefs, they are disposed at the
          { Don't register forwarddefs, they are disposed at the
            end of an type block }
            end of an type block }
@@ -1376,6 +1402,7 @@ implementation
             generictokenbuf.free;
             generictokenbuf.free;
             generictokenbuf:=nil;
             generictokenbuf:=nil;
           end;
           end;
+        genericparas.free;
         inherited destroy;
         inherited destroy;
       end;
       end;
 
 
@@ -1386,6 +1413,7 @@ implementation
         buf  : array[0..255] of byte;
         buf  : array[0..255] of byte;
       begin
       begin
          inherited create(dt);
          inherited create(dt);
+         genericparas:=tfphashobjectlist.create(false);
          DefId:=ppufile.getlongint;
          DefId:=ppufile.getlongint;
          current_module.deflist[DefId]:=self;
          current_module.deflist[DefId]:=self;
 {$ifdef EXTDEBUG}
 {$ifdef EXTDEBUG}
@@ -1626,6 +1654,11 @@ implementation
        generictokenbuf:=tdynamicarray.create(256);
        generictokenbuf:=tdynamicarray.create(256);
      end;
      end;
 
 
+   function tstoreddef.is_generic: boolean;
+     begin
+       result:=genericparas.count>0;
+     end;
+
 
 
 {****************************************************************************
 {****************************************************************************
                                Tstringdef
                                Tstringdef
@@ -2946,6 +2979,7 @@ implementation
         tarraysymtable(symtable).deref;
         tarraysymtable(symtable).deref;
         _elementdef:=tdef(_elementdefderef.resolve);
         _elementdef:=tdef(_elementdefderef.resolve);
         rangedef:=tdef(rangedefderef.resolve);
         rangedef:=tdef(rangedefderef.resolve);
+        fillgenericparas(symtable);
       end;
       end;
 
 
 
 
@@ -3489,6 +3523,8 @@ implementation
          else
          else
            tstoredsymtable(symtable).deref;
            tstoredsymtable(symtable).deref;
 
 
+         fillgenericparas(symtable);
+
          { assign TGUID? load only from system unit }
          { assign TGUID? load only from system unit }
          if not(assigned(rec_tguid)) and
          if not(assigned(rec_tguid)) and
             (upper(typename)='TGUID') and
             (upper(typename)='TGUID') and
@@ -3687,6 +3723,7 @@ implementation
          tparasymtable(parast).deref;
          tparasymtable(parast).deref;
          { recalculated parameters }
          { recalculated parameters }
          calcparas;
          calcparas;
+         fillgenericparas(parast);
       end;
       end;
 
 
 
 
@@ -5502,6 +5539,7 @@ implementation
            end
            end
          else
          else
            tstoredsymtable(symtable).deref;
            tstoredsymtable(symtable).deref;
+         fillgenericparas(symtable);
          if objecttype=odt_helper then
          if objecttype=odt_helper then
            extendeddef:=tdef(extendeddefderef.resolve);
            extendeddef:=tdef(extendeddefderef.resolve);
          for i:=0 to vmtentries.count-1 do
          for i:=0 to vmtentries.count-1 do

+ 2 - 1
compiler/utils/ppudump.pp

@@ -492,7 +492,8 @@ type
 const
 const
   symtblopts=ord(high(tsymtableoption))  + 1;
   symtblopts=ord(high(tsymtableoption))  + 1;
   symtblopt : array[1..symtblopts] of tsymtblopt=(
   symtblopt : array[1..symtblopts] of tsymtblopt=(
-     (mask:sto_has_helper;   str:'Has helper')
+     (mask:sto_has_helper;   str:'Has helper'),
+     (mask:sto_has_generic;  str:'Has generic')
   );
   );
 var
 var
   options : tsymtableoptions;
   options : tsymtableoptions;