mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2026-01-08 11:01:41 +01:00
* 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:
parent
07880add06
commit
6c586e4eca
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -137,7 +137,8 @@ type
|
||||
sp_strictprotected,
|
||||
sp_implicitrename,
|
||||
sp_hidden,
|
||||
sp_hint_experimental
|
||||
sp_hint_experimental,
|
||||
sp_generic_para
|
||||
);
|
||||
tsymoptions=set of tsymoption;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user