* 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 -
This commit is contained in:
peter 2008-07-18 23:30:44 +00:00
parent 07880add06
commit 6c586e4eca
5 changed files with 67 additions and 27 deletions

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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

View File

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