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 -
This commit is contained in:
svenbarth 2012-09-13 11:35:35 +00:00
parent 2d0f01e0dd
commit 29c71d39ac
5 changed files with 50 additions and 2 deletions

View File

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

View File

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

View File

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

View File

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

View File

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