mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 17:49:25 +02:00
fcl-passrc: specialize class with nested record type
git-svn-id: trunk@42703 -
This commit is contained in:
parent
32573139a8
commit
8ad47efcb3
@ -1737,6 +1737,8 @@ type
|
|||||||
procedure SpecializeGenTypeImpl(GenericType: TPasGenericType;
|
procedure SpecializeGenTypeImpl(GenericType: TPasGenericType;
|
||||||
SpecializedItem: TPSSpecializedItem); virtual;
|
SpecializedItem: TPSSpecializedItem); virtual;
|
||||||
procedure SpecializeMembers(GenMembersType, SpecMembersType: TPasMembersType); virtual;
|
procedure SpecializeMembers(GenMembersType, SpecMembersType: TPasMembersType); virtual;
|
||||||
|
procedure SpecializeMembersImpl(GenericType, SpecType: TPasMembersType;
|
||||||
|
ImplProcs: TFPList); virtual;
|
||||||
procedure SpecializeElement(GenEl, SpecEl: TPasElement);
|
procedure SpecializeElement(GenEl, SpecEl: TPasElement);
|
||||||
procedure SpecializePasElementProperties(GenEl, SpecEl: TPasElement);
|
procedure SpecializePasElementProperties(GenEl, SpecEl: TPasElement);
|
||||||
procedure SpecializeVariable(GenEl, SpecEl: TPasVariable; Finish: boolean);
|
procedure SpecializeVariable(GenEl, SpecEl: TPasVariable; Finish: boolean);
|
||||||
@ -1792,6 +1794,7 @@ type
|
|||||||
procedure SpecializePointerType(GenEl, SpecEl: TPasPointerType);
|
procedure SpecializePointerType(GenEl, SpecEl: TPasPointerType);
|
||||||
procedure SpecializeRangeType(GenEl, SpecEl: TPasRangeType);
|
procedure SpecializeRangeType(GenEl, SpecEl: TPasRangeType);
|
||||||
procedure SpecializeArrayType(GenEl, SpecEl: TPasArrayType; SpecializedItem: TPSSpecializedItem);
|
procedure SpecializeArrayType(GenEl, SpecEl: TPasArrayType; SpecializedItem: TPSSpecializedItem);
|
||||||
|
procedure SpecializeRecordType(GenEl, SpecEl: TPasRecordType; SpecializedItem: TPSSpecializedItem);
|
||||||
procedure SpecializeEnumValue(GenEl, SpecEl: TPasEnumValue);
|
procedure SpecializeEnumValue(GenEl, SpecEl: TPasEnumValue);
|
||||||
procedure SpecializeEnumType(GenEl, SpecEl: TPasEnumType);
|
procedure SpecializeEnumType(GenEl, SpecEl: TPasEnumType);
|
||||||
procedure SpecializeSetType(GenEl, SpecEl: TPasSetType);
|
procedure SpecializeSetType(GenEl, SpecEl: TPasSetType);
|
||||||
@ -10984,8 +10987,13 @@ begin
|
|||||||
Proc:=TPasProcedure(DeclEl);
|
Proc:=TPasProcedure(DeclEl);
|
||||||
if Proc.IsAbstract or Proc.IsExternal then continue;
|
if Proc.IsAbstract or Proc.IsExternal then continue;
|
||||||
if TPasProcedureScope(Proc.CustomData).ImplProc=nil then
|
if TPasProcedureScope(Proc.CustomData).ImplProc=nil then
|
||||||
|
begin
|
||||||
|
{$IFDEF VerbosePasResolver}
|
||||||
|
writeln('TPasResolver.CheckPendingForwardProcs Proc.ParentPath=',Proc.PathName);
|
||||||
|
{$ENDIF}
|
||||||
RaiseMsg(20170216152221,nForwardProcNotResolved,sForwardProcNotResolved,
|
RaiseMsg(20170216152221,nForwardProcNotResolved,sForwardProcNotResolved,
|
||||||
[GetElementTypeName(Proc),Proc.Name],Proc);
|
[GetElementTypeName(Proc),Proc.Name],Proc);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
ClassOrRecScope.GenericStep:=psgsImplementationParsed;
|
ClassOrRecScope.GenericStep:=psgsImplementationParsed;
|
||||||
@ -14884,16 +14892,9 @@ begin
|
|||||||
begin
|
begin
|
||||||
NewRecordType:=TPasRecordType(SpecType);
|
NewRecordType:=TPasRecordType(SpecType);
|
||||||
GenRecordType:=TPasRecordType(GenericType);
|
GenRecordType:=TPasRecordType(GenericType);
|
||||||
NewRecordType.PackMode:=GenRecordType.PackMode;
|
|
||||||
GenScope:=TPasGenericScope(PushScope(NewRecordType,TPasRecordScope));
|
GenScope:=TPasGenericScope(PushScope(NewRecordType,TPasRecordScope));
|
||||||
GenScope.SpecializedItem:=SpecializedItem;
|
|
||||||
GenScope.VisibilityContext:=NewRecordType;
|
GenScope.VisibilityContext:=NewRecordType;
|
||||||
AddSpecializedTemplateIdentifiers(GenericTemplateTypes,
|
SpecializeRecordType(GenRecordType,NewRecordType,SpecializedItem);
|
||||||
SpecializedItem.Params,GenScope);
|
|
||||||
// specialize sub elements
|
|
||||||
SpecializeMembers(GenRecordType,NewRecordType);
|
|
||||||
SpecializedItem.Step:=psssInterfaceFinished;
|
|
||||||
FinishRecordType(NewRecordType);
|
|
||||||
end
|
end
|
||||||
else if C=TPasClassType then
|
else if C=TPasClassType then
|
||||||
begin
|
begin
|
||||||
@ -14952,7 +14953,6 @@ begin
|
|||||||
GenArrayType:=TPasArrayType(GenericType);
|
GenArrayType:=TPasArrayType(GenericType);
|
||||||
NewArrayType:=TPasArrayType(SpecType);
|
NewArrayType:=TPasArrayType(SpecType);
|
||||||
SpecializeArrayType(GenArrayType,NewArrayType,SpecializedItem);
|
SpecializeArrayType(GenArrayType,NewArrayType,SpecializedItem);
|
||||||
SpecializedItem.Step:=psssImplementationFinished;
|
|
||||||
end
|
end
|
||||||
else if (C=TPasProcedureType)
|
else if (C=TPasProcedureType)
|
||||||
or (C=TPasFunctionType) then
|
or (C=TPasFunctionType) then
|
||||||
@ -14960,7 +14960,6 @@ begin
|
|||||||
GenProcType:=TPasProcedureType(GenericType);
|
GenProcType:=TPasProcedureType(GenericType);
|
||||||
NewProcType:=TPasProcedureType(SpecType);
|
NewProcType:=TPasProcedureType(SpecType);
|
||||||
SpecializeProcedureType(GenProcType,NewProcType,SpecializedItem);
|
SpecializeProcedureType(GenProcType,NewProcType,SpecializedItem);
|
||||||
SpecializedItem.Step:=psssImplementationFinished;
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
RaiseNotYetImplemented(20190728134933,GenericType);
|
RaiseNotYetImplemented(20190728134933,GenericType);
|
||||||
@ -14970,16 +14969,7 @@ procedure TPasResolver.SpecializeGenTypeImpl(GenericType: TPasGenericType;
|
|||||||
SpecializedItem: TPSSpecializedItem);
|
SpecializedItem: TPSSpecializedItem);
|
||||||
var
|
var
|
||||||
SpecType: TPasGenericType;
|
SpecType: TPasGenericType;
|
||||||
GenClassOrRec, SpecClassOrRec: TPasMembersType;
|
|
||||||
GenMember, SpecMember, ImplParent: TPasElement;
|
|
||||||
GenIntfProc, GenImplProc, SpecImplProc, SpecIntfProc: TPasProcedure;
|
|
||||||
GenIntfProcScope, SpecIntfProcScope, GenImplProcScope,
|
|
||||||
SpecImplProcScope: TPasProcedureScope;
|
|
||||||
NewClass: TPTreeElement;
|
|
||||||
OldStashCount, i, p, LastDotP: Integer;
|
|
||||||
SpecClassOrRecScope: TPasClassOrRecordScope;
|
|
||||||
GenScope: TPasGenericScope;
|
GenScope: TPasGenericScope;
|
||||||
NewImplProcName, OldClassname: String;
|
|
||||||
begin
|
begin
|
||||||
// check generic type is resolved completely
|
// check generic type is resolved completely
|
||||||
GenScope:=TPasGenericScope(GenericType.CustomData);
|
GenScope:=TPasGenericScope(GenericType.CustomData);
|
||||||
@ -14999,87 +14989,10 @@ begin
|
|||||||
// specialize all methods
|
// specialize all methods
|
||||||
if GenericType is TPasMembersType then
|
if GenericType is TPasMembersType then
|
||||||
begin
|
begin
|
||||||
GenClassOrRec:=TPasMembersType(GenericType);
|
if SpecializedItem.ImplProcs=nil then
|
||||||
SpecClassOrRec:=TPasMembersType(SpecType);
|
SpecializedItem.ImplProcs:=TFPList.Create;
|
||||||
SpecClassOrRecScope:=TPasClassOrRecordScope(SpecClassOrRec.CustomData);
|
SpecializeMembersImpl(TPasMembersType(GenericType),TPasMembersType(SpecType),
|
||||||
|
SpecializedItem.ImplProcs);
|
||||||
{$IFDEF VerbosePasResolver}
|
|
||||||
writeln('TPasResolver.FinishClassType RestoreStashedScopes ',GetObjName(SpecializedItem.SpecializedType),' ',ScopeCount,' FStashScopeCount=',FStashScopeCount);
|
|
||||||
{$ENDIF}
|
|
||||||
ImplParent:=nil;
|
|
||||||
OldStashCount:=FStashScopeCount;
|
|
||||||
|
|
||||||
for i:=0 to GenClassOrRec.Members.Count-1 do
|
|
||||||
begin
|
|
||||||
GenMember:=TPasElement(GenClassOrRec.Members[i]);
|
|
||||||
if GenMember is TPasProcedure then
|
|
||||||
begin
|
|
||||||
GenIntfProc:=TPasProcedure(GenMember);
|
|
||||||
if GenIntfProc.IsAbstract or GenIntfProc.IsExternal then continue;
|
|
||||||
GenIntfProcScope:=TPasProcedureScope(GenIntfProc.CustomData);
|
|
||||||
GenImplProc:=GenIntfProcScope.ImplProc;
|
|
||||||
if GenImplProc=nil then
|
|
||||||
RaiseNotYetImplemented(20190804122134,GenIntfProc);
|
|
||||||
GenImplProcScope:=TPasProcedureScope(GenImplProc.CustomData);
|
|
||||||
SpecMember:=TPasElement(SpecClassOrRec.Members[i]);
|
|
||||||
if SpecMember.Name<>GenMember.Name then
|
|
||||||
RaiseNotYetImplemented(20190804124220,GenMember,GetObjName(SpecMember));
|
|
||||||
SpecIntfProc:=SpecMember as TPasProcedure;
|
|
||||||
SpecIntfProcScope:=TPasProcedureScope(SpecIntfProc.CustomData);
|
|
||||||
NewClass:=TPTreeElement(GenImplProc.ClassType);
|
|
||||||
|
|
||||||
{$IFDEF VerbosePasResolver}
|
|
||||||
writeln('TPasResolver.SpecializeGenTypeImpl Specialize GenImplProc: ',GetObjName(GenImplProc));
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
if ImplParent=nil then
|
|
||||||
begin
|
|
||||||
// switch scope (e.g. unit implementation section)
|
|
||||||
ImplParent:=GenImplProc.Parent;
|
|
||||||
OldStashCount:=InitSpecializeScopes(GenImplProc);
|
|
||||||
{$IFDEF VerbosePasResolver}
|
|
||||||
writeln('TPasResolver.SpecializeGenTypeImpl Specialize implprocs: SpecType=',GetObjName(SpecType),' ImplParent=',GetObjName(ImplParent),' ScopeCount=',ScopeCount,' FStashScopeCount=',FStashScopeCount,' TopScope=',GetObjName(TopScope));
|
|
||||||
{$ENDIF}
|
|
||||||
end
|
|
||||||
else if ImplParent<>GenImplProc.Parent then
|
|
||||||
RaiseNotYetImplemented(20190804130322,GenImplProc,GetObjName(ImplParent));
|
|
||||||
|
|
||||||
// create impl proc
|
|
||||||
NewImplProcName:=GenImplProc.Name;
|
|
||||||
p:=length(NewImplProcName);
|
|
||||||
while (p>1) and (NewImplProcName[p]<>'.') do dec(p);
|
|
||||||
LastDotP:=p;
|
|
||||||
while (p>1) and (NewImplProcName[p-1]<>'.') do dec(p);
|
|
||||||
OldClassname:=copy(NewImplProcName,p,LastDotP-p);
|
|
||||||
if not SameText(OldClassname,GenClassOrRec.Name) then
|
|
||||||
RaiseNotYetImplemented(20190814141833,GenImplProc);
|
|
||||||
NewImplProcName:=LeftStr(NewImplProcName,p-1)+SpecClassOrRec.Name+copy(NewImplProcName,LastDotP,length(NewImplProcName));
|
|
||||||
|
|
||||||
SpecImplProc:=TPasProcedure(NewClass.Create(NewImplProcName,GenImplProc.Parent));
|
|
||||||
SpecIntfProcScope.ImplProc:=SpecImplProc;
|
|
||||||
if SpecializedItem.ImplProcs=nil then
|
|
||||||
SpecializedItem.ImplProcs:=TFPList.Create;
|
|
||||||
SpecializedItem.ImplProcs.Add(SpecImplProc);
|
|
||||||
|
|
||||||
// create impl proc scope
|
|
||||||
SpecImplProcScope:=TPasProcedureScope(CreateScope(SpecImplProc,FScopeClass_Proc));
|
|
||||||
SpecImplProcScope.Flags:=[ppsfIsSpecialized];
|
|
||||||
SpecImplProcScope.DeclarationProc:=SpecIntfProc;
|
|
||||||
SpecImplProcScope.ModeSwitches:=GenImplProcScope.Modeswitches;
|
|
||||||
SpecImplProcScope.BoolSwitches:=GenImplProcScope.BoolSwitches;
|
|
||||||
SpecImplProcScope.VisibilityContext:=SpecClassOrRec;
|
|
||||||
SpecImplProcScope.ClassRecScope:=SpecClassOrRecScope;
|
|
||||||
|
|
||||||
// specialize props
|
|
||||||
SpecializeElement(GenImplProc,SpecImplProc);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if ImplParent<>nil then
|
|
||||||
begin
|
|
||||||
// restore scope
|
|
||||||
RestoreStashedScopes(OldStashCount);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
SpecializedItem.Step:=psssImplementationFinished;
|
SpecializedItem.Step:=psssImplementationFinished;
|
||||||
@ -15104,6 +15017,107 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPasResolver.SpecializeMembersImpl(GenericType,
|
||||||
|
SpecType: TPasMembersType; ImplProcs: TFPList);
|
||||||
|
var
|
||||||
|
GenClassOrRec, SpecClassOrRec: TPasMembersType;
|
||||||
|
SpecClassOrRecScope: TPasClassOrRecordScope;
|
||||||
|
OldStashCount, i, p, LastDotP: Integer;
|
||||||
|
GenMember, SpecMember, ImplParent: TPasElement;
|
||||||
|
GenIntfProc, GenImplProc, SpecIntfProc, SpecImplProc: TPasProcedure;
|
||||||
|
GenIntfProcScope, GenImplProcScope, SpecIntfProcScope,
|
||||||
|
SpecImplProcScope: TPasProcedureScope;
|
||||||
|
NewClass: TPTreeElement;
|
||||||
|
NewImplProcName, OldClassname: String;
|
||||||
|
begin
|
||||||
|
GenClassOrRec:=TPasMembersType(GenericType);
|
||||||
|
SpecClassOrRec:=TPasMembersType(SpecType);
|
||||||
|
SpecClassOrRecScope:=TPasClassOrRecordScope(SpecClassOrRec.CustomData);
|
||||||
|
|
||||||
|
{$IFDEF VerbosePasResolver}
|
||||||
|
writeln('TPasResolver.SpecializeMembersImpl RestoreStashedScopes ',GetObjPath(SpecClassOrRec),' ',ScopeCount,' FStashScopeCount=',FStashScopeCount);
|
||||||
|
{$ENDIF}
|
||||||
|
ImplParent:=nil;
|
||||||
|
OldStashCount:=FStashScopeCount;
|
||||||
|
|
||||||
|
for i:=0 to GenClassOrRec.Members.Count-1 do
|
||||||
|
begin
|
||||||
|
GenMember:=TPasElement(GenClassOrRec.Members[i]);
|
||||||
|
SpecMember:=TPasElement(SpecClassOrRec.Members[i]);
|
||||||
|
if SpecMember.ClassType<>GenMember.ClassType then
|
||||||
|
RaiseNotYetImplemented(20190816002658,GenMember,GetObjName(SpecMember));
|
||||||
|
if SpecMember.Name<>GenMember.Name then
|
||||||
|
RaiseNotYetImplemented(20190804124220,GenMember,GetObjName(SpecMember));
|
||||||
|
if GenMember is TPasProcedure then
|
||||||
|
begin
|
||||||
|
GenIntfProc:=TPasProcedure(GenMember);
|
||||||
|
if GenIntfProc.IsAbstract or GenIntfProc.IsExternal then continue;
|
||||||
|
GenIntfProcScope:=TPasProcedureScope(GenIntfProc.CustomData);
|
||||||
|
GenImplProc:=GenIntfProcScope.ImplProc;
|
||||||
|
if GenImplProc=nil then
|
||||||
|
RaiseNotYetImplemented(20190804122134,GenIntfProc);
|
||||||
|
GenImplProcScope:=TPasProcedureScope(GenImplProc.CustomData);
|
||||||
|
SpecIntfProc:=SpecMember as TPasProcedure;
|
||||||
|
SpecIntfProcScope:=TPasProcedureScope(SpecIntfProc.CustomData);
|
||||||
|
NewClass:=TPTreeElement(GenImplProc.ClassType);
|
||||||
|
|
||||||
|
{$IFDEF VerbosePasResolver}
|
||||||
|
writeln('TPasResolver.SpecializeMembersImpl Specialize GenImplProc: ',GetObjName(GenImplProc));
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
if ImplParent=nil then
|
||||||
|
begin
|
||||||
|
// switch scope (e.g. unit implementation section)
|
||||||
|
ImplParent:=GenImplProc.Parent;
|
||||||
|
OldStashCount:=InitSpecializeScopes(GenImplProc);
|
||||||
|
{$IFDEF VerbosePasResolver}
|
||||||
|
writeln('TPasResolver.SpecializeMembersImpl Specialize implprocs: SpecType=',GetObjName(SpecType),' ImplParent=',GetObjName(ImplParent),' ScopeCount=',ScopeCount,' FStashScopeCount=',FStashScopeCount,' TopScope=',GetObjName(TopScope));
|
||||||
|
{$ENDIF}
|
||||||
|
end
|
||||||
|
else if ImplParent<>GenImplProc.Parent then
|
||||||
|
RaiseNotYetImplemented(20190804130322,GenImplProc,GetObjName(ImplParent));
|
||||||
|
|
||||||
|
// create impl proc
|
||||||
|
NewImplProcName:=GenImplProc.Name;
|
||||||
|
p:=length(NewImplProcName);
|
||||||
|
while (p>1) and (NewImplProcName[p]<>'.') do dec(p);
|
||||||
|
LastDotP:=p;
|
||||||
|
while (p>1) and (NewImplProcName[p-1]<>'.') do dec(p);
|
||||||
|
OldClassname:=copy(NewImplProcName,p,LastDotP-p);
|
||||||
|
if not SameText(OldClassname,GenClassOrRec.Name) then
|
||||||
|
RaiseNotYetImplemented(20190814141833,GenImplProc);
|
||||||
|
NewImplProcName:=LeftStr(NewImplProcName,p-1)+SpecClassOrRec.Name+copy(NewImplProcName,LastDotP,length(NewImplProcName));
|
||||||
|
|
||||||
|
SpecImplProc:=TPasProcedure(NewClass.Create(NewImplProcName,GenImplProc.Parent));
|
||||||
|
SpecIntfProcScope.ImplProc:=SpecImplProc;
|
||||||
|
ImplProcs.Add(SpecImplProc);
|
||||||
|
|
||||||
|
// create impl proc scope
|
||||||
|
SpecImplProcScope:=TPasProcedureScope(CreateScope(SpecImplProc,FScopeClass_Proc));
|
||||||
|
SpecImplProcScope.Flags:=[ppsfIsSpecialized];
|
||||||
|
SpecImplProcScope.DeclarationProc:=SpecIntfProc;
|
||||||
|
SpecImplProcScope.ModeSwitches:=GenImplProcScope.Modeswitches;
|
||||||
|
SpecImplProcScope.BoolSwitches:=GenImplProcScope.BoolSwitches;
|
||||||
|
SpecImplProcScope.VisibilityContext:=SpecClassOrRec;
|
||||||
|
SpecImplProcScope.ClassRecScope:=SpecClassOrRecScope;
|
||||||
|
|
||||||
|
// specialize props
|
||||||
|
SpecializeElement(GenImplProc,SpecImplProc);
|
||||||
|
end
|
||||||
|
else if GenMember is TPasMembersType then
|
||||||
|
begin
|
||||||
|
// nested record/class type
|
||||||
|
SpecializeMembersImpl(TPasMembersType(GenMember),TPasMembersType(SpecMember),ImplProcs);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if ImplParent<>nil then
|
||||||
|
begin
|
||||||
|
// restore scope
|
||||||
|
RestoreStashedScopes(OldStashCount);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TPasResolver.SpecializeElement(GenEl, SpecEl: TPasElement);
|
procedure TPasResolver.SpecializeElement(GenEl, SpecEl: TPasElement);
|
||||||
var
|
var
|
||||||
C: TClass;
|
C: TClass;
|
||||||
@ -15155,8 +15169,8 @@ begin
|
|||||||
end
|
end
|
||||||
else if C=TPasArrayType then
|
else if C=TPasArrayType then
|
||||||
begin
|
begin
|
||||||
if TPasArrayType(GenEl).GenericTemplateTypes<>nil then
|
if GetTypeParameterCount(TPasArrayType(GenEl))>0 then
|
||||||
RaiseNotYetImplemented(20190812220312,GenEl);
|
RaiseNotYetImplemented(20190815201219,GenEl);
|
||||||
AddArrayType(TPasArrayType(SpecEl),nil);
|
AddArrayType(TPasArrayType(SpecEl),nil);
|
||||||
SpecializeArrayType(TPasArrayType(GenEl),TPasArrayType(SpecEl),nil);
|
SpecializeArrayType(TPasArrayType(GenEl),TPasArrayType(SpecEl),nil);
|
||||||
end
|
end
|
||||||
@ -15174,7 +15188,13 @@ begin
|
|||||||
SpecializeSetType(TPasSetType(GenEl),TPasSetType(SpecEl))
|
SpecializeSetType(TPasSetType(GenEl),TPasSetType(SpecEl))
|
||||||
else if C=TPasVariant then
|
else if C=TPasVariant then
|
||||||
SpecializeVariant(TPasVariant(GenEl),TPasVariant(SpecEl))
|
SpecializeVariant(TPasVariant(GenEl),TPasVariant(SpecEl))
|
||||||
// ToDo: TPasRecordType
|
else if C=TPasRecordType then
|
||||||
|
begin
|
||||||
|
if GetTypeParameterCount(TPasRecordType(GenEl))>0 then
|
||||||
|
RaiseNotYetImplemented(20190815201201,GenEl);
|
||||||
|
AddRecordType(TPasRecordType(SpecEl),nil);
|
||||||
|
SpecializeRecordType(TPasRecordType(GenEl),TPasRecordType(SpecEl),nil);
|
||||||
|
end
|
||||||
// ToDo: TPasClassType
|
// ToDo: TPasClassType
|
||||||
else if C=TPasStringType then
|
else if C=TPasStringType then
|
||||||
begin
|
begin
|
||||||
@ -15548,6 +15568,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
FinishProcedureType(SpecEl);
|
FinishProcedureType(SpecEl);
|
||||||
|
if SpecializedItem<>nil then
|
||||||
|
SpecializedItem.Step:=psssImplementationFinished;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasResolver.SpecializeProcedureBody(GenEl, SpecEl: TProcedureBody);
|
procedure TPasResolver.SpecializeProcedureBody(GenEl, SpecEl: TProcedureBody);
|
||||||
@ -15985,6 +16007,36 @@ begin
|
|||||||
SpecializeExprArray(GenEl,SpecEl,GenEl.Ranges,SpecEl.Ranges);
|
SpecializeExprArray(GenEl,SpecEl,GenEl.Ranges,SpecEl.Ranges);
|
||||||
SpecializeElType(GenEl,SpecEl,GenEl.ElType,SpecEl.ElType);
|
SpecializeElType(GenEl,SpecEl,GenEl.ElType,SpecEl.ElType);
|
||||||
FinishArrayType(SpecEl);
|
FinishArrayType(SpecEl);
|
||||||
|
if SpecializedItem<>nil then
|
||||||
|
SpecializedItem.Step:=psssImplementationFinished;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPasResolver.SpecializeRecordType(GenEl, SpecEl: TPasRecordType;
|
||||||
|
SpecializedItem: TPSSpecializedItem);
|
||||||
|
var
|
||||||
|
GenScope: TPasGenericScope;
|
||||||
|
begin
|
||||||
|
if SpecEl.CustomData=nil then
|
||||||
|
RaiseNotYetImplemented(20190815201634,SpecEl);
|
||||||
|
SpecEl.PackMode:=GenEl.PackMode;
|
||||||
|
GenScope:=TPasGenericScope(SpecEl.CustomData);
|
||||||
|
if SpecializedItem<>nil then
|
||||||
|
begin
|
||||||
|
// specialized generic record
|
||||||
|
GenScope.SpecializedItem:=SpecializedItem;
|
||||||
|
AddSpecializedTemplateIdentifiers(GenEl.GenericTemplateTypes,
|
||||||
|
SpecializedItem.Params,GenScope);
|
||||||
|
end
|
||||||
|
else if GenEl.GenericTemplateTypes.Count>0 then
|
||||||
|
begin
|
||||||
|
// generic recordtype inside a generic type
|
||||||
|
RaiseNotYetImplemented(20190815194327,GenEl);
|
||||||
|
end;
|
||||||
|
// specialize sub elements
|
||||||
|
SpecializeMembers(GenEl,SpecEl);
|
||||||
|
FinishRecordType(SpecEl);
|
||||||
|
if SpecializedItem<>nil then
|
||||||
|
SpecializedItem.Step:=psssInterfaceFinished;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasResolver.SpecializeEnumValue(GenEl, SpecEl: TPasEnumValue);
|
procedure TPasResolver.SpecializeEnumValue(GenEl, SpecEl: TPasEnumValue);
|
||||||
|
@ -55,14 +55,13 @@ type
|
|||||||
// ToDo: generic class overload <T> <S,T>
|
// ToDo: generic class overload <T> <S,T>
|
||||||
procedure TestGen_Class_GenAncestor;
|
procedure TestGen_Class_GenAncestor;
|
||||||
procedure TestGen_Class_AncestorSelfFail;
|
procedure TestGen_Class_AncestorSelfFail;
|
||||||
// ToDo: ancestor cycle: TBird<T> = class(TBird<word>) fail
|
|
||||||
// ToDo: class-of
|
// ToDo: class-of
|
||||||
// ToDo: UnitA.impl uses UnitB.intf uses UnitA.intf, UnitB has specialize of UnitA
|
// ToDo: UnitA.impl uses UnitB.intf uses UnitA.intf, UnitB has specialize of UnitA
|
||||||
procedure TestGen_Class_NestedType;
|
procedure TestGen_Class_NestedType;
|
||||||
// ToDo: procedure TestGen_NestedDottedType;
|
procedure TestGen_Class_NestedRecord;
|
||||||
|
procedure TestGen_Class_NestedClass; // ToDo
|
||||||
procedure TestGen_Class_Enums_NotPropagating;
|
procedure TestGen_Class_Enums_NotPropagating;
|
||||||
procedure TestGen_Class_List;
|
procedure TestGen_Class_List;
|
||||||
// ToDo: procedure TestGen_Class_SubClassType;
|
|
||||||
|
|
||||||
// generic external class
|
// generic external class
|
||||||
procedure TestGen_ExtClass_Array;
|
procedure TestGen_ExtClass_Array;
|
||||||
@ -93,6 +92,7 @@ type
|
|||||||
// ToDo: dot
|
// ToDo: dot
|
||||||
// ToDo: is as
|
// ToDo: is as
|
||||||
// ToDo: typecast
|
// ToDo: typecast
|
||||||
|
// ToTo: nested proc
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -628,6 +628,59 @@ begin
|
|||||||
ParseProgram;
|
ParseProgram;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolveGenerics.TestGen_Class_NestedRecord;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'{$mode objfpc}',
|
||||||
|
'{$modeswitch advancedrecords}',
|
||||||
|
'type',
|
||||||
|
' TObject = class end;',
|
||||||
|
' generic TBird<T> = class',
|
||||||
|
' public type TWing = record',
|
||||||
|
' s: T;',
|
||||||
|
' function GetIt: T;',
|
||||||
|
' end;',
|
||||||
|
' public',
|
||||||
|
' w: TWing;',
|
||||||
|
' end;',
|
||||||
|
' TBirdWord = specialize TBird<word>;',
|
||||||
|
'function TBird.TWing.GetIt: T;',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'var',
|
||||||
|
' b: TBirdWord;',
|
||||||
|
' i: word;',
|
||||||
|
'begin',
|
||||||
|
' b.w.s:=i;',
|
||||||
|
' i:=b.w.GetIt;',
|
||||||
|
'']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolveGenerics.TestGen_Class_NestedClass;
|
||||||
|
begin
|
||||||
|
exit;
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'{$mode objfpc}',
|
||||||
|
'type',
|
||||||
|
' TObject = class end;',
|
||||||
|
' generic TBird<T> = class',
|
||||||
|
' public type TWing = class',
|
||||||
|
' s: T;',
|
||||||
|
' end;',
|
||||||
|
' public',
|
||||||
|
' w: TWing;',
|
||||||
|
' end;',
|
||||||
|
' TBirdWord = specialize TBird<word>;',
|
||||||
|
'var',
|
||||||
|
' b: TBirdWord;',
|
||||||
|
'begin',
|
||||||
|
' b.w.s:=3;']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestResolveGenerics.TestGen_Class_Enums_NotPropagating;
|
procedure TTestResolveGenerics.TestGen_Class_Enums_NotPropagating;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user