fcl-passrc: specialize generic forward proc

git-svn-id: trunk@43052 -
This commit is contained in:
Mattias Gaertner 2019-09-22 13:50:58 +00:00
parent 009a3435c1
commit 422afb8ebc
2 changed files with 78 additions and 35 deletions

View File

@ -6554,7 +6554,7 @@ var
i: Integer; i: Integer;
Body: TProcedureBody; Body: TProcedureBody;
SubEl: TPasElement; SubEl: TPasElement;
SubProcScope, ProcScope: TPasProcedureScope; SubProcScope, ProcScope, DeclProcScope: TPasProcedureScope;
SpecializedItem: TPRSpecializedItem; SpecializedItem: TPRSpecializedItem;
begin begin
{$IFDEF VerbosePasResolver} {$IFDEF VerbosePasResolver}
@ -6600,6 +6600,11 @@ begin
ProcScope.GroupScope:=nil; ProcScope.GroupScope:=nil;
end; end;
ProcScope.GenericStep:=psgsImplementationParsed; ProcScope.GenericStep:=psgsImplementationParsed;
if ProcScope.DeclarationProc<>nil then
begin
DeclProcScope:=ProcScope.DeclarationProc.CustomData as TPasProcedureScope;
DeclProcScope.GenericStep:=psgsImplementationParsed;
end;
end end
else if ProcScope.GroupScope<>nil then else if ProcScope.GroupScope<>nil then
RaiseInternalError(20190122142142,GetObjName(Proc)); RaiseInternalError(20190122142142,GetObjName(Proc));
@ -6924,7 +6929,7 @@ begin
DeclProcScope.ImplProc:=Proc; DeclProcScope.ImplProc:=Proc;
ProcScope.DeclarationProc:=DeclProc; ProcScope.DeclarationProc:=DeclProc;
// remove ImplProc from scope // remove ImplProc from scope
(ParentScope as TPasIdentifierScope).RemoveLocalIdentifier(Proc); ParentScope.RemoveLocalIdentifier(Proc);
// replace arguments with declaration arguments // replace arguments with declaration arguments
ReplaceProcScopeImplArgsWithDeclArgs(ProcScope); ReplaceProcScopeImplArgsWithDeclArgs(ProcScope);
exit; exit;
@ -8969,6 +8974,7 @@ begin
DeclTemplates:=GetProcTemplateTypes(DeclProc); DeclTemplates:=GetProcTemplateTypes(DeclProc);
if ImplTemplates<>nil then if ImplTemplates<>nil then
begin begin
writeln('AAA1 TPasResolver.ReplaceProcScopeImplArgsWithDeclArgs DeclProc=',DeclProc.Name,' ImplProc=',ImplProc.Name,' ',ImplTemplates.Count);
if (DeclTemplates=nil) or (ImplTemplates.Count<>DeclTemplates.Count) then if (DeclTemplates=nil) or (ImplTemplates.Count<>DeclTemplates.Count) then
RaiseNotYetImplemented(20190912153602,ImplProc); // inconsistency RaiseNotYetImplemented(20190912153602,ImplProc); // inconsistency
for i:=0 to ImplTemplates.Count-1 do for i:=0 to ImplTemplates.Count-1 do
@ -12061,6 +12067,7 @@ begin
IsClassConDestructor:=(El.ClassType=TPasClassConstructor) IsClassConDestructor:=(El.ClassType=TPasClassConstructor)
or (El.ClassType=TPasClassDestructor); or (El.ClassType=TPasClassDestructor);
ClassOrRecType:=nil;
if El.CustomData is TPasProcedureScope then if El.CustomData is TPasProcedureScope then
begin begin
// adding a specialized implementation proc // adding a specialized implementation proc
@ -12068,19 +12075,20 @@ begin
if ProcScope.DeclarationProc<>nil then if ProcScope.DeclarationProc<>nil then
TypeParams:=ProcScope.DeclarationProc.NameParts; TypeParams:=ProcScope.DeclarationProc.NameParts;
ClassOrRecScope:=ProcScope.ClassRecScope; ClassOrRecScope:=ProcScope.ClassRecScope;
if ClassOrRecScope=nil then if ClassOrRecScope<>nil then
RaiseNotYetImplemented(20190804175307,El);
ClassOrRecType:=TPasMembersType(ClassOrRecScope.Element);
if GetTypeParameterCount(ClassOrRecType)>0 then
RaiseNotYetImplemented(20190804175518,El);
if ProcScope.GroupScope<>nil then
RaiseNotYetImplemented(20190804175451,El);
if (not HasDot) and IsClassConDestructor then
begin begin
if El.ClassType=TPasClassConstructor then ClassOrRecType:=TPasMembersType(ClassOrRecScope.Element);
AddClassConDestructor(ClassOrRecScope,TPasProcedure(ClassOrRecScope.ClassConstructor)) if GetTypeParameterCount(ClassOrRecType)>0 then
else RaiseNotYetImplemented(20190804175518,El);
AddClassConDestructor(ClassOrRecScope,TPasProcedure(ClassOrRecScope.ClassDestructor)); if ProcScope.GroupScope<>nil then
RaiseNotYetImplemented(20190804175451,El);
if (not HasDot) and IsClassConDestructor then
begin
if El.ClassType=TPasClassConstructor then
AddClassConDestructor(ClassOrRecScope,TPasProcedure(ClassOrRecScope.ClassConstructor))
else
AddClassConDestructor(ClassOrRecScope,TPasProcedure(ClassOrRecScope.ClassDestructor));
end;
end; end;
PushScope(ProcScope); PushScope(ProcScope);
@ -16268,7 +16276,21 @@ var
SpecClassOrRecScope: TPasClassOrRecordScope; SpecClassOrRecScope: TPasClassOrRecordScope;
NewImplProcName, OldClassname: String; NewImplProcName, OldClassname: String;
p, LastDotP: Integer; p, LastDotP: Integer;
SpecializedProcItem: TPRSpecializedProcItem;
SpecializedTypeItem: TPRSpecializedTypeItem;
Templates: TFPList;
begin begin
SpecializedProcItem:=nil;
SpecializedTypeItem:=nil;
if SpecializedItem is TPRSpecializedProcItem then
// impl proc of a specialized forward proc
SpecializedProcItem:=TPRSpecializedProcItem(SpecializedItem)
else if SpecializedItem is TPRSpecializedTypeItem then
// method of a specialized class/record
SpecializedTypeItem:=TPRSpecializedTypeItem(SpecializedItem)
else
RaiseNotYetImplemented(20190922145050,SpecDeclProc);
GenDeclProcScope:=TPasProcedureScope(GenDeclProc.CustomData); GenDeclProcScope:=TPasProcedureScope(GenDeclProc.CustomData);
GenImplProc:=GenDeclProcScope.ImplProc; GenImplProc:=GenDeclProcScope.ImplProc;
if GenImplProc=nil then if GenImplProc=nil then
@ -16293,18 +16315,17 @@ begin
{$ENDIF} {$ENDIF}
// create impl proc name // create impl proc name
NewImplProcName:=GenImplProc.Name; if SpecializedTypeItem<>nil then
if SpecializedItem=nil then
begin begin
// method of a specialized class/record // method of a specialized class/record
if SpecClassOrRecScope=nil then if SpecClassOrRecScope=nil then
RaiseNotYetImplemented(20190921221839,SpecDeclProc); RaiseNotYetImplemented(20190921221839,SpecDeclProc);
NewImplProcName:=GenImplProc.Name;
p:=length(NewImplProcName); p:=length(NewImplProcName);
while (p>0) and (NewImplProcName[p]<>'.') do dec(p); while (p>0) and (NewImplProcName[p]<>'.') do dec(p);
if p=0 then if p=0 then
RaiseNotYetImplemented(20190921221730,GenImplProc); RaiseNotYetImplemented(20190921221730,GenImplProc);
// has classname -> replace generic clasname with specialized classname // has classname -> replace generic classname with specialized classname
LastDotP:=p; LastDotP:=p;
while (p>1) and (NewImplProcName[p-1]<>'.') do dec(p); while (p>1) and (NewImplProcName[p-1]<>'.') do dec(p);
OldClassname:=copy(NewImplProcName,p,LastDotP-p); OldClassname:=copy(NewImplProcName,p,LastDotP-p);
@ -16312,16 +16333,27 @@ begin
if not SameText(OldClassname,GenClassOrRec.Name) then if not SameText(OldClassname,GenClassOrRec.Name) then
RaiseNotYetImplemented(20190814141833,GenImplProc); RaiseNotYetImplemented(20190814141833,GenImplProc);
NewImplProcName:=LeftStr(NewImplProcName,p-1)+SpecClassOrRec.Name+copy(NewImplProcName,LastDotP,length(NewImplProcName)); NewImplProcName:=LeftStr(NewImplProcName,p-1)+SpecClassOrRec.Name+copy(NewImplProcName,LastDotP,length(NewImplProcName));
end
else
begin
// use classname of GenImplProc and name of SpecDeclProc
OldClassname:=GenImplProc.Name;
p:=length(OldClassname);
while (p>0) and (OldClassname[p]<>'.') do dec(p);
if p>0 then
NewImplProcName:=LeftStr(OldClassname,p)+SpecDeclProc.Name
else
NewImplProcName:=SpecDeclProc.Name;
end; end;
// create impl proc // create impl proc
NewClass:=TPTreeElement(GenImplProc.ClassType); NewClass:=TPTreeElement(GenImplProc.ClassType);
SpecImplProc:=TPasProcedure(NewClass.Create(NewImplProcName,GenImplProc.Parent)); SpecImplProc:=TPasProcedure(NewClass.Create(NewImplProcName,GenImplProc.Parent));
SpecDeclProcScope.ImplProc:=SpecImplProc; SpecDeclProcScope.ImplProc:=SpecImplProc;
if SpecializedItem is TPRSpecializedProcItem then if SpecializedProcItem<>nil then
TPRSpecializedProcItem(SpecializedItem).ImplProc:=SpecImplProc SpecializedProcItem.ImplProc:=SpecImplProc
else else
TPRSpecializedTypeItem(SpecializedItem).ImplProcs.Add(SpecImplProc); SpecializedTypeItem.ImplProcs.Add(SpecImplProc);
// create impl proc scope // create impl proc scope
SpecImplProcScope:=TPasProcedureScope(CreateScope(SpecImplProc,FScopeClass_Proc)); SpecImplProcScope:=TPasProcedureScope(CreateScope(SpecImplProc,FScopeClass_Proc));
@ -16331,9 +16363,20 @@ begin
SpecImplProcScope.BoolSwitches:=GenImplProcScope.BoolSwitches; SpecImplProcScope.BoolSwitches:=GenImplProcScope.BoolSwitches;
SpecImplProcScope.VisibilityContext:=SpecClassOrRec; SpecImplProcScope.VisibilityContext:=SpecClassOrRec;
SpecImplProcScope.ClassRecScope:=SpecClassOrRecScope; SpecImplProcScope.ClassRecScope:=SpecClassOrRecScope;
if GenDeclProcScope.SelfArg<>nil then
RaiseNotYetImplemented(20190922154603,GenImplProc);
if SpecializedProcItem<>nil then
begin
Templates:=GetProcTemplateTypes(GenDeclProc);
AddSpecializedTemplateIdentifiers(Templates,SpecializedItem,SpecImplProcScope,
false);
end;
// specialize props // specialize props
SpecializeElement(GenImplProc,SpecImplProc); SpecializePasElementProperties(GenImplProc,SpecImplProc);
AddProcedure(SpecImplProc,nil);
SpecializeProcedure(GenImplProc,SpecImplProc,SpecializedItem);
end; end;
procedure TPasResolver.SpecializeElement(GenEl, SpecEl: TPasElement); procedure TPasResolver.SpecializeElement(GenEl, SpecEl: TPasElement);
@ -16744,7 +16787,13 @@ var
GenBody: TProcedureBody; GenBody: TProcedureBody;
begin begin
GenProcScope:=GenEl.CustomData as TPasProcedureScope; GenProcScope:=GenEl.CustomData as TPasProcedureScope;
if SpecializedItem<>nil then SpecProcScope:=SpecEl.CustomData as TPasProcedureScope;
if SpecProcScope<>nil then
begin
if TopScope<>SpecProcScope then
RaiseNotYetImplemented(20190920194151,SpecEl);
end
else if SpecializedItem<>nil then
begin begin
// specialized generic/parametrized procedure // specialized generic/parametrized procedure
SpecProcScope:=TPasProcedureScope(PushScope(SpecEl,ScopeClass_Procedure)); SpecProcScope:=TPasProcedureScope(PushScope(SpecEl,ScopeClass_Procedure));
@ -16766,12 +16815,7 @@ begin
AddSpecializedTemplateIdentifiers(Templates,SpecializedItem,SpecProcScope,true); AddSpecializedTemplateIdentifiers(Templates,SpecializedItem,SpecProcScope,true);
end end
else else
begin RaiseNotYetImplemented(20190922153918,SpecEl);
// specialized procedure of a specialized parent
SpecProcScope:=SpecEl.CustomData as TPasProcedureScope;
if TopScope<>SpecProcScope then
RaiseNotYetImplemented(20190920194151,SpecEl);
end;
Include(SpecProcScope.Flags,ppsfIsSpecialized); Include(SpecProcScope.Flags,ppsfIsSpecialized);
if GenEl.PublicName<>nil then if GenEl.PublicName<>nil then

View File

@ -122,7 +122,7 @@ type
procedure TestGenProc_Function; procedure TestGenProc_Function;
procedure TestGenProc_FunctionDelphi; procedure TestGenProc_FunctionDelphi;
procedure TestGenProc_OverloadDuplicate; procedure TestGenProc_OverloadDuplicate;
procedure TestGenProc_Forward; // ToDo procedure TestGenProc_Forward;
//procedure TestGenProc_External; //procedure TestGenProc_External;
//procedure TestGenProc_UnitIntf; //procedure TestGenProc_UnitIntf;
procedure TestGenProc_BackRef1Fail; procedure TestGenProc_BackRef1Fail;
@ -1751,14 +1751,13 @@ end;
procedure TTestResolveGenerics.TestGenProc_Forward; procedure TTestResolveGenerics.TestGenProc_Forward;
begin begin
exit;
StartProgram(false); StartProgram(false);
Add([ Add([
'generic procedure Fly<T>(a: T); forward;', 'generic procedure Fly<T>(a: T); forward;',
//'generic procedure Run;', 'generic procedure Run;',
//'begin', 'begin',
//' specialize Fly<word>(3);', ' specialize Fly<word>(3);',
//'end;', 'end;',
'generic procedure Fly<T>(a: T);', 'generic procedure Fly<T>(a: T);',
'var i: T;', 'var i: T;',
'begin', 'begin',