Quellcode durchsuchen

* store specializations in globalsymtable for units, use localsymtable
for programs. this allows speciailizations to be done in the interface
part of the unit
* support tobject.typemember.typemember nesting for generics
* fix generic parameter checking when a typemember was created with the
type of a parameter
* known issue is nested specializations don't work yet because the token
replay can't handled nested replays yet

git-svn-id: trunk@11404 -

peter vor 17 Jahren
Ursprung
Commit
6c586e4eca
5 geänderte Dateien mit 67 neuen und 27 gelöschten Zeilen
  1. 1 0
      compiler/pdecl.pas
  2. 4 0
      compiler/pdecsub.pas
  3. 26 21
      compiler/psub.pas
  4. 34 5
      compiler/ptype.pas
  5. 2 1
      compiler/symconst.pas

+ 1 - 0
compiler/pdecl.pas

@@ -381,6 +381,7 @@ implementation
             if token=_ID then
               begin
                 generictype:=ttypesym.create(orgpattern,cundefinedtype);
+                include(generictype.symoptions,sp_generic_para);
                 result.add(generictype);
               end;
             consume(_ID);

+ 4 - 0
compiler/pdecsub.pas

@@ -901,6 +901,7 @@ implementation
         pd : tprocdef;
         isclassmethod : boolean;
         locationstr: string;
+        old_parse_generic,
         popclass : boolean;
       begin
         locationstr:='';
@@ -929,6 +930,7 @@ implementation
                     begin
                       if try_to_consume(_COLON) then
                        begin
+                         old_parse_generic:=parse_generic;
                          inc(testcurobject);
                          { Add ObjectSymtable to be able to find generic type definitions }
                          popclass:=false;
@@ -938,11 +940,13 @@ implementation
                            begin
                              symtablestack.push(pd._class.symtable);
                              popclass:=true;
+                             parse_generic:=(df_generic in pd._class.defoptions);
                            end;
                          single_type(pd.returndef,false);
                          if popclass then
                            symtablestack.pop(pd._class.symtable);
                          dec(testcurobject);
+                         parse_generic:=old_parse_generic;
 
                          if (target_info.system in [system_m68k_amiga]) then
                           begin

+ 26 - 21
compiler/psub.pas

@@ -1809,6 +1809,7 @@ implementation
         oldsymtablestack   : tsymtablestack;
         pu : tused_unit;
         hmodule : tmodule;
+        specobj : tobjectdef;
       begin
         if not((tsym(p).typ=typesym) and
                (ttypesym(p).typedef.typesym=tsym(p)) and
@@ -1818,11 +1819,12 @@ implementation
           exit;
 
         { Setup symtablestack a definition time }
+        specobj:=tobjectdef(ttypesym(p).typedef);
         oldsymtablestack:=symtablestack;
         symtablestack:=tsymtablestack.create;
         if not assigned(tobjectdef(ttypesym(p).typedef).genericdef) then
           internalerror(200705151);
-        hmodule:=find_module_from_symtable(tobjectdef(ttypesym(p).typedef).genericdef.owner);
+        hmodule:=find_module_from_symtable(specobj.genericdef.owner);
         if hmodule=nil then
           internalerror(200705152);
         pu:=tused_unit(hmodule.used_units.first);
@@ -1838,29 +1840,32 @@ implementation
         if assigned(hmodule.localsymtable) then
           symtablestack.push(hmodule.localsymtable);
 
-        { definitions }
-        for i:=0 to tobjectdef(ttypesym(p).typedef).symtable.DefList.Count-1 do
+        { procedure definitions for classes or objects }
+        if is_class(specobj) or is_object(specobj) then
           begin
-            hp:=tdef(tobjectdef(ttypesym(p).typedef).symtable.DefList[i]);
-            if hp.typ=procdef then
-             begin
-               if assigned(tprocdef(hp).genericdef) and
-                 (tprocdef(hp).genericdef.typ=procdef) and
-                 assigned(tprocdef(tprocdef(hp).genericdef).generictokenbuf) then
+            for i:=0 to specobj.symtable.DefList.Count-1 do
+              begin
+                hp:=tdef(specobj.symtable.DefList[i]);
+                if hp.typ=procdef then
                  begin
-                   oldcurrent_filepos:=current_filepos;
-                   current_filepos:=tprocdef(tprocdef(hp).genericdef).fileinfo;
-                   { use the index the module got from the current compilation process }
-                   current_filepos.moduleindex:=hmodule.unit_index;
-                   current_tokenpos:=current_filepos;
-                   current_scanner.startreplaytokens(tprocdef(tprocdef(hp).genericdef).generictokenbuf);
-                   read_proc_body(nil,tprocdef(hp));
-                   current_filepos:=oldcurrent_filepos;
-                 end
-               else
-                 MessagePos1(tprocdef(tprocdef(hp).genericdef).fileinfo,sym_e_forward_not_resolved,tprocdef(tprocdef(hp).genericdef).fullprocname(false));
+                   if assigned(tprocdef(hp).genericdef) and
+                     (tprocdef(hp).genericdef.typ=procdef) and
+                     assigned(tprocdef(tprocdef(hp).genericdef).generictokenbuf) then
+                     begin
+                       oldcurrent_filepos:=current_filepos;
+                       current_filepos:=tprocdef(tprocdef(hp).genericdef).fileinfo;
+                       { use the index the module got from the current compilation process }
+                       current_filepos.moduleindex:=hmodule.unit_index;
+                       current_tokenpos:=current_filepos;
+                       current_scanner.startreplaytokens(tprocdef(tprocdef(hp).genericdef).generictokenbuf);
+                       read_proc_body(nil,tprocdef(hp));
+                       current_filepos:=oldcurrent_filepos;
+                     end
+                   else
+                     MessagePos1(tprocdef(tprocdef(hp).genericdef).fileinfo,sym_e_forward_not_resolved,tprocdef(tprocdef(hp).genericdef).fullprocname(false));
+                 end;
              end;
-         end;
+          end;
 
         { Restore symtablestack }
         symtablestack.free;

+ 34 - 5
compiler/ptype.pas

@@ -97,6 +97,7 @@ implementation
         specializename : string;
         vmtbuilder : TVMTBuilder;
         onlyparsepara : boolean;
+        specializest : tsymtable;
       begin
         { retrieve generic def that we are going to replace }
         genericdef:=tstoreddef(tt);
@@ -155,8 +156,7 @@ implementation
         for i:=0 to st.SymList.Count-1 do
           begin
             sym:=tsym(st.SymList[i]);
-            if (sym.typ=typesym) and
-               (ttypesym(sym).typedef.typ=undefineddef) then
+            if (sp_generic_para in sym.symoptions) then
               begin
                 if not first then
                   consume(_COMMA)
@@ -191,10 +191,18 @@ implementation
            (aktobjectdef.objname^=uspecializename) then
           tt:=aktobjectdef;
 
+        { for units specializations can already be needed in the interface, therefor we
+          will use the global symtable. Programs don't have a globalsymtable and there we
+          use the localsymtable }
+        if current_module.is_unit then
+          specializest:=current_module.globalsymtable
+        else
+          specializest:=current_module.localsymtable;
+
         { Can we reuse an already specialized type? }
         if not assigned(tt) then
           begin
-            srsym:=tsym(tsymtable(current_module.localsymtable).find(uspecializename));
+            srsym:=tsym(specializest.find(uspecializename));
             if assigned(srsym) then
               begin
                 if srsym.typ<>typesym then
@@ -236,7 +244,7 @@ implementation
                 { Firsta new typesym so we can reuse this specialization and
                   references to this specialization can be handled }
                 srsym:=ttypesym.create(specializename,generrordef);
-                current_module.localsymtable.insert(srsym);
+                specializest.insert(srsym);
 
                 if not assigned(genericdef.generictokenbuf) then
                   internalerror(200511171);
@@ -379,7 +387,28 @@ implementation
                        again:=true;
                      end
                    else
-                     id_type(def,isforwarddef);
+                     begin
+                       id_type(def,isforwarddef);
+                       { handle types inside classes for generics, e.g. TNode.TLongint }
+                       while (token=_POINT) do
+                         begin
+                           if parse_generic then
+                             begin
+                                consume(_POINT);
+                                consume(_ID);
+                             end
+                            else if ((def.typ=objectdef) and (df_specialization in def.defoptions)) then
+                              begin
+                                symtablestack.push(tobjectdef(def).symtable);
+                                consume(_POINT);
+                                id_type(t2,isforwarddef);
+                                symtablestack.pop(tobjectdef(def).symtable);
+                                def:=t2;
+                              end
+                            else
+                              break;
+                         end;
+                     end;
                  end;
 
                else

+ 2 - 1
compiler/symconst.pas

@@ -137,7 +137,8 @@ type
     sp_strictprotected,
     sp_implicitrename,
     sp_hidden,
-    sp_hint_experimental
+    sp_hint_experimental,
+    sp_generic_para
   );
   tsymoptions=set of tsymoption;