mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-03 18:29:35 +01:00
* ptype.pas:
"generate_specialization" now parses the generic parameters without verifying them. The verification is done after their count is known and thus the correct generic def can be determined. Note: It does currently only work with the first found symbol, the extended lookup needs to be implemented yet (including the unit name works though) * pexpr.pas: In "factor_read_id" an "identifer not found" error is generated if the undefined non-generic def is used (e.g. as a type for a variable) Note: This check needs to be adjusted for the case "typeonly=false". Status of generics: Specializations can now be parsed, but declarations containing methods are still broken, because the correct def is not yet resolved (not even talking about inline specializations yet ;) ) git-svn-id: branches/svenbarth/generics@17394 -
This commit is contained in:
parent
80100734c5
commit
b18772916b
@ -1381,7 +1381,16 @@ implementation
|
||||
exit;
|
||||
end;
|
||||
{ if nothing found give error and return errorsym }
|
||||
if assigned(srsym) then
|
||||
if assigned(srsym) and
|
||||
not (
|
||||
{ in case of an overloaded generic symbol we need to
|
||||
generate an error if the non-generic symbol is still
|
||||
undefined and we're not doing a specialization }
|
||||
typeonly and (srsym.typ=typesym) and
|
||||
(ttypesym(srsym).typedef.typ=undefineddef) and
|
||||
(ttypesym(srsym).gendeflist.Count>0) and
|
||||
not (token in [_LT, _LSHARPBRACKET])
|
||||
) then
|
||||
check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg)
|
||||
else
|
||||
begin
|
||||
|
||||
@ -148,12 +148,17 @@ implementation
|
||||
st : TSymtable;
|
||||
srsym : tsym;
|
||||
pt2 : tnode;
|
||||
found,
|
||||
first,
|
||||
err : boolean;
|
||||
i : longint;
|
||||
i,
|
||||
j,
|
||||
gencount : longint;
|
||||
sym : tsym;
|
||||
genericdef : tstoreddef;
|
||||
genericsym,
|
||||
generictype : ttypesym;
|
||||
genericdeflist : TFPObjectList;
|
||||
generictypelist : TFPObjectList;
|
||||
oldsymtablestack : tsymtablestack;
|
||||
oldextendeddefs : TFPHashObjectList;
|
||||
@ -165,14 +170,21 @@ implementation
|
||||
onlyparsepara : boolean;
|
||||
specializest : tsymtable;
|
||||
item: psymtablestackitem;
|
||||
def : tdef;
|
||||
begin
|
||||
{ retrieve generic def that we are going to replace }
|
||||
genericdef:=tstoreddef(tt);
|
||||
tt:=nil;
|
||||
onlyparsepara:=false;
|
||||
|
||||
if not(df_generic in genericdef.defoptions) then
|
||||
if not assigned(genericdef.typesym) or
|
||||
(genericdef.typesym.typ<>typesym) then
|
||||
internalerror(2011042701);
|
||||
|
||||
genericsym:=ttypesym(genericdef.typesym);
|
||||
if genericsym.gendeflist.Count=0 then
|
||||
begin
|
||||
{ TODO : search for other generics with the same name }
|
||||
Message(parser_e_special_onlygenerics);
|
||||
tt:=generrordef;
|
||||
onlyparsepara:=true;
|
||||
@ -205,62 +217,109 @@ implementation
|
||||
|
||||
if not try_to_consume(_LT) then
|
||||
consume(_LSHARPBRACKET);
|
||||
{ Parse generic parameters, for each undefineddef in the symtable of
|
||||
the genericdef we need to have a new def }
|
||||
err:=false;
|
||||
first:=true;
|
||||
|
||||
generictypelist:=TFPObjectList.create(false);
|
||||
case genericdef.typ of
|
||||
procdef:
|
||||
st:=genericdef.GetSymtable(gs_para);
|
||||
objectdef,
|
||||
recorddef:
|
||||
st:=genericdef.GetSymtable(gs_record);
|
||||
arraydef:
|
||||
st:=tarraydef(genericdef).symtable;
|
||||
procvardef:
|
||||
st:=genericdef.GetSymtable(gs_para);
|
||||
else
|
||||
internalerror(200511182);
|
||||
end;
|
||||
genericdeflist:=TFPObjectList.Create(false);
|
||||
|
||||
{ Parse type parameters }
|
||||
if not assigned(genericdef.typesym) then
|
||||
internalerror(200710173);
|
||||
specializename:=genericdef.typesym.realname;
|
||||
err:=false;
|
||||
first:=true;
|
||||
specializename:='';
|
||||
while not (token in [_GT,_RSHARPBRACKET]) do
|
||||
begin
|
||||
if not first then
|
||||
consume(_COMMA)
|
||||
else
|
||||
first:=false;
|
||||
pt2:=factor(false,true);
|
||||
if pt2.nodetype=typen then
|
||||
begin
|
||||
if df_generic in pt2.resultdef.defoptions then
|
||||
Message(parser_e_no_generics_as_params);
|
||||
genericdeflist.Add(pt2.resultdef);
|
||||
if not assigned(pt2.resultdef.typesym) then
|
||||
message(type_e_generics_cannot_reference_itself)
|
||||
else
|
||||
specializename:=specializename+'$'+pt2.resultdef.typesym.realname;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Message(type_e_type_id_expected);
|
||||
err:=true;
|
||||
end;
|
||||
pt2.free;
|
||||
end;
|
||||
|
||||
if err then
|
||||
begin
|
||||
try_to_consume(_RSHARPBRACKET);
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ check whether we have a generic with the correct amount of params }
|
||||
found:=false;
|
||||
for i:=0 to genericsym.gendeflist.Count-1 do begin
|
||||
def:=tdef(genericsym.gendeflist[i]);
|
||||
{ select the symtable containing the params }
|
||||
case def.typ of
|
||||
procdef:
|
||||
st:=def.GetSymtable(gs_para);
|
||||
objectdef,
|
||||
recorddef:
|
||||
st:=def.GetSymtable(gs_record);
|
||||
arraydef:
|
||||
st:=tarraydef(def).symtable;
|
||||
procvardef:
|
||||
st:=def.GetSymtable(gs_para);
|
||||
else
|
||||
internalerror(200511182);
|
||||
end;
|
||||
|
||||
gencount:=0;
|
||||
for j:=0 to st.SymList.Count-1 do
|
||||
begin
|
||||
if sp_generic_para in tsym(st.SymList[j]).symoptions then
|
||||
inc(gencount);
|
||||
end;
|
||||
|
||||
if gencount=genericdeflist.count then
|
||||
begin
|
||||
found:=true;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
if not found then
|
||||
begin
|
||||
identifier_not_found(genericdef.typename);
|
||||
tt:=generrordef;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ we've found the correct def, so use it }
|
||||
genericdef:=tstoreddef(def);
|
||||
|
||||
{ build the new type's name }
|
||||
specializename:=genericdef.typesym.realname+specializename;
|
||||
uspecializename:=upper(specializename);
|
||||
|
||||
{ build the list containing the types for the generic params }
|
||||
gencount:=0;
|
||||
for i:=0 to st.SymList.Count-1 do
|
||||
begin
|
||||
sym:=tsym(st.SymList[i]);
|
||||
if (sp_generic_para in sym.symoptions) then
|
||||
if sp_generic_para in sym.symoptions then
|
||||
begin
|
||||
if not first then
|
||||
consume(_COMMA)
|
||||
else
|
||||
first:=false;
|
||||
pt2:=factor(false,true);
|
||||
if pt2.nodetype=typen then
|
||||
begin
|
||||
if df_generic in pt2.resultdef.defoptions then
|
||||
Message(parser_e_no_generics_as_params);
|
||||
generictype:=ttypesym.create(sym.realname,pt2.resultdef);
|
||||
generictypelist.add(generictype);
|
||||
if not assigned(pt2.resultdef.typesym) then
|
||||
message(type_e_generics_cannot_reference_itself)
|
||||
else
|
||||
specializename:=specializename+'$'+pt2.resultdef.typesym.realname;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Message(type_e_type_id_expected);
|
||||
err:=true;
|
||||
end;
|
||||
pt2.free;
|
||||
if gencount=genericdeflist.Count then
|
||||
internalerror(2011042702);
|
||||
generictype:=ttypesym.create(sym.realname,tdef(genericdeflist[gencount]));
|
||||
generictypelist.add(generictype);
|
||||
inc(gencount);
|
||||
end;
|
||||
end;
|
||||
uspecializename:=upper(specializename);
|
||||
{ force correct error location if too much type parameters are passed }
|
||||
if not (token in [_RSHARPBRACKET,_GT]) then
|
||||
consume(_RSHARPBRACKET);
|
||||
|
||||
|
||||
{ Special case if we are referencing the current defined object }
|
||||
if assigned(current_structdef) and
|
||||
@ -385,13 +444,14 @@ implementation
|
||||
tundefineddef.create;
|
||||
end;
|
||||
|
||||
genericdeflist.free;
|
||||
generictypelist.free;
|
||||
if not try_to_consume(_GT) then
|
||||
consume(_RSHARPBRACKET);
|
||||
end;
|
||||
|
||||
|
||||
procedure id_type(var def : tdef;isforwarddef,checkcurrentrecdef:boolean); forward;
|
||||
procedure id_type(var def : tdef;isforwarddef,checkcurrentrecdef,allowgenericsyms:boolean); forward;
|
||||
|
||||
{ def is the outermost type in which other types have to be searched
|
||||
|
||||
@ -435,7 +495,7 @@ implementation
|
||||
structstackindex:=-1;
|
||||
symtablestack.push(tabstractrecorddef(def).symtable);
|
||||
t2:=generrordef;
|
||||
id_type(t2,isforwarddef,false);
|
||||
id_type(t2,isforwarddef,false,false);
|
||||
symtablestack.pop(tabstractrecorddef(def).symtable);
|
||||
def:=t2;
|
||||
end;
|
||||
@ -480,7 +540,7 @@ implementation
|
||||
result:=false;
|
||||
end;
|
||||
|
||||
procedure id_type(var def : tdef;isforwarddef,checkcurrentrecdef:boolean);
|
||||
procedure id_type(var def : tdef;isforwarddef,checkcurrentrecdef,allowgenericsyms:boolean);
|
||||
{ reads a type definition }
|
||||
{ to a appropriating tdef, s gets the name of }
|
||||
{ the type to allow name mangling }
|
||||
@ -511,7 +571,9 @@ implementation
|
||||
table as forwarddef are not resolved directly }
|
||||
if assigned(srsym) and
|
||||
(srsym.typ=typesym) and
|
||||
(ttypesym(srsym).typedef.typ=errordef) then
|
||||
(ttypesym(srsym).typedef.typ=errordef) and
|
||||
(not allowgenericsyms or
|
||||
(ttypesym(srsym).gendeflist.Count=0)) then
|
||||
begin
|
||||
Message1(type_e_type_is_not_completly_defined,ttypesym(srsym).realname);
|
||||
def:=generrordef;
|
||||
@ -538,8 +600,11 @@ implementation
|
||||
def:=generrordef;
|
||||
exit;
|
||||
end;
|
||||
{ Give an error when referring to an errordef }
|
||||
if (ttypesym(srsym).typedef.typ=errordef) then
|
||||
{ Give an error when referring to an errordef that does not have
|
||||
generic overloads }
|
||||
if (ttypesym(srsym).typedef.typ=errordef) and
|
||||
(not allowgenericsyms or
|
||||
(ttypesym(srsym).gendeflist.Count=0)) then
|
||||
begin
|
||||
Message(sym_e_error_in_type_def);
|
||||
def:=generrordef;
|
||||
@ -600,7 +665,7 @@ implementation
|
||||
end
|
||||
else
|
||||
begin
|
||||
id_type(def,stoIsForwardDef in options,true);
|
||||
id_type(def,stoIsForwardDef in options,true,true);
|
||||
parse_nested_types(def,stoIsForwardDef in options,nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user