mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-11 11:29:44 +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;
|
exit;
|
||||||
end;
|
end;
|
||||||
{ if nothing found give error and return errorsym }
|
{ 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)
|
check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
|||||||
@ -148,12 +148,17 @@ implementation
|
|||||||
st : TSymtable;
|
st : TSymtable;
|
||||||
srsym : tsym;
|
srsym : tsym;
|
||||||
pt2 : tnode;
|
pt2 : tnode;
|
||||||
|
found,
|
||||||
first,
|
first,
|
||||||
err : boolean;
|
err : boolean;
|
||||||
i : longint;
|
i,
|
||||||
|
j,
|
||||||
|
gencount : longint;
|
||||||
sym : tsym;
|
sym : tsym;
|
||||||
genericdef : tstoreddef;
|
genericdef : tstoreddef;
|
||||||
|
genericsym,
|
||||||
generictype : ttypesym;
|
generictype : ttypesym;
|
||||||
|
genericdeflist : TFPObjectList;
|
||||||
generictypelist : TFPObjectList;
|
generictypelist : TFPObjectList;
|
||||||
oldsymtablestack : tsymtablestack;
|
oldsymtablestack : tsymtablestack;
|
||||||
oldextendeddefs : TFPHashObjectList;
|
oldextendeddefs : TFPHashObjectList;
|
||||||
@ -165,14 +170,21 @@ implementation
|
|||||||
onlyparsepara : boolean;
|
onlyparsepara : boolean;
|
||||||
specializest : tsymtable;
|
specializest : tsymtable;
|
||||||
item: psymtablestackitem;
|
item: psymtablestackitem;
|
||||||
|
def : tdef;
|
||||||
begin
|
begin
|
||||||
{ retrieve generic def that we are going to replace }
|
{ retrieve generic def that we are going to replace }
|
||||||
genericdef:=tstoreddef(tt);
|
genericdef:=tstoreddef(tt);
|
||||||
tt:=nil;
|
tt:=nil;
|
||||||
onlyparsepara:=false;
|
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
|
begin
|
||||||
|
{ TODO : search for other generics with the same name }
|
||||||
Message(parser_e_special_onlygenerics);
|
Message(parser_e_special_onlygenerics);
|
||||||
tt:=generrordef;
|
tt:=generrordef;
|
||||||
onlyparsepara:=true;
|
onlyparsepara:=true;
|
||||||
@ -205,33 +217,17 @@ implementation
|
|||||||
|
|
||||||
if not try_to_consume(_LT) then
|
if not try_to_consume(_LT) then
|
||||||
consume(_LSHARPBRACKET);
|
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);
|
generictypelist:=TFPObjectList.create(false);
|
||||||
case genericdef.typ of
|
genericdeflist:=TFPObjectList.Create(false);
|
||||||
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;
|
|
||||||
|
|
||||||
{ Parse type parameters }
|
{ Parse type parameters }
|
||||||
if not assigned(genericdef.typesym) then
|
if not assigned(genericdef.typesym) then
|
||||||
internalerror(200710173);
|
internalerror(200710173);
|
||||||
specializename:=genericdef.typesym.realname;
|
err:=false;
|
||||||
for i:=0 to st.SymList.Count-1 do
|
first:=true;
|
||||||
begin
|
specializename:='';
|
||||||
sym:=tsym(st.SymList[i]);
|
while not (token in [_GT,_RSHARPBRACKET]) do
|
||||||
if (sp_generic_para in sym.symoptions) then
|
|
||||||
begin
|
begin
|
||||||
if not first then
|
if not first then
|
||||||
consume(_COMMA)
|
consume(_COMMA)
|
||||||
@ -242,8 +238,7 @@ implementation
|
|||||||
begin
|
begin
|
||||||
if df_generic in pt2.resultdef.defoptions then
|
if df_generic in pt2.resultdef.defoptions then
|
||||||
Message(parser_e_no_generics_as_params);
|
Message(parser_e_no_generics_as_params);
|
||||||
generictype:=ttypesym.create(sym.realname,pt2.resultdef);
|
genericdeflist.Add(pt2.resultdef);
|
||||||
generictypelist.add(generictype);
|
|
||||||
if not assigned(pt2.resultdef.typesym) then
|
if not assigned(pt2.resultdef.typesym) then
|
||||||
message(type_e_generics_cannot_reference_itself)
|
message(type_e_generics_cannot_reference_itself)
|
||||||
else
|
else
|
||||||
@ -256,11 +251,75 @@ implementation
|
|||||||
end;
|
end;
|
||||||
pt2.free;
|
pt2.free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if err then
|
||||||
|
begin
|
||||||
|
try_to_consume(_RSHARPBRACKET);
|
||||||
|
exit;
|
||||||
end;
|
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);
|
uspecializename:=upper(specializename);
|
||||||
{ force correct error location if too much type parameters are passed }
|
|
||||||
if not (token in [_RSHARPBRACKET,_GT]) then
|
{ build the list containing the types for the generic params }
|
||||||
consume(_RSHARPBRACKET);
|
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
|
||||||
|
begin
|
||||||
|
if gencount=genericdeflist.Count then
|
||||||
|
internalerror(2011042702);
|
||||||
|
generictype:=ttypesym.create(sym.realname,tdef(genericdeflist[gencount]));
|
||||||
|
generictypelist.add(generictype);
|
||||||
|
inc(gencount);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ Special case if we are referencing the current defined object }
|
{ Special case if we are referencing the current defined object }
|
||||||
if assigned(current_structdef) and
|
if assigned(current_structdef) and
|
||||||
@ -385,13 +444,14 @@ implementation
|
|||||||
tundefineddef.create;
|
tundefineddef.create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
genericdeflist.free;
|
||||||
generictypelist.free;
|
generictypelist.free;
|
||||||
if not try_to_consume(_GT) then
|
if not try_to_consume(_GT) then
|
||||||
consume(_RSHARPBRACKET);
|
consume(_RSHARPBRACKET);
|
||||||
end;
|
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
|
{ def is the outermost type in which other types have to be searched
|
||||||
|
|
||||||
@ -435,7 +495,7 @@ implementation
|
|||||||
structstackindex:=-1;
|
structstackindex:=-1;
|
||||||
symtablestack.push(tabstractrecorddef(def).symtable);
|
symtablestack.push(tabstractrecorddef(def).symtable);
|
||||||
t2:=generrordef;
|
t2:=generrordef;
|
||||||
id_type(t2,isforwarddef,false);
|
id_type(t2,isforwarddef,false,false);
|
||||||
symtablestack.pop(tabstractrecorddef(def).symtable);
|
symtablestack.pop(tabstractrecorddef(def).symtable);
|
||||||
def:=t2;
|
def:=t2;
|
||||||
end;
|
end;
|
||||||
@ -480,7 +540,7 @@ implementation
|
|||||||
result:=false;
|
result:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure id_type(var def : tdef;isforwarddef,checkcurrentrecdef:boolean);
|
procedure id_type(var def : tdef;isforwarddef,checkcurrentrecdef,allowgenericsyms:boolean);
|
||||||
{ reads a type definition }
|
{ reads a type definition }
|
||||||
{ to a appropriating tdef, s gets the name of }
|
{ to a appropriating tdef, s gets the name of }
|
||||||
{ the type to allow name mangling }
|
{ the type to allow name mangling }
|
||||||
@ -511,7 +571,9 @@ implementation
|
|||||||
table as forwarddef are not resolved directly }
|
table as forwarddef are not resolved directly }
|
||||||
if assigned(srsym) and
|
if assigned(srsym) and
|
||||||
(srsym.typ=typesym) 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
|
begin
|
||||||
Message1(type_e_type_is_not_completly_defined,ttypesym(srsym).realname);
|
Message1(type_e_type_is_not_completly_defined,ttypesym(srsym).realname);
|
||||||
def:=generrordef;
|
def:=generrordef;
|
||||||
@ -538,8 +600,11 @@ implementation
|
|||||||
def:=generrordef;
|
def:=generrordef;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
{ Give an error when referring to an errordef }
|
{ Give an error when referring to an errordef that does not have
|
||||||
if (ttypesym(srsym).typedef.typ=errordef) then
|
generic overloads }
|
||||||
|
if (ttypesym(srsym).typedef.typ=errordef) and
|
||||||
|
(not allowgenericsyms or
|
||||||
|
(ttypesym(srsym).gendeflist.Count=0)) then
|
||||||
begin
|
begin
|
||||||
Message(sym_e_error_in_type_def);
|
Message(sym_e_error_in_type_def);
|
||||||
def:=generrordef;
|
def:=generrordef;
|
||||||
@ -600,7 +665,7 @@ implementation
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
id_type(def,stoIsForwardDef in options,true);
|
id_type(def,stoIsForwardDef in options,true,true);
|
||||||
parse_nested_types(def,stoIsForwardDef in options,nil);
|
parse_nested_types(def,stoIsForwardDef in options,nil);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user