mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-01 13:11:06 +02:00
fcl-passrc: specialize generic method
git-svn-id: trunk@43090 -
This commit is contained in:
parent
49026e1261
commit
683d4d4301
@ -1761,6 +1761,11 @@ type
|
|||||||
function EvalBaseTypeCast(Params: TParamsExpr; bt: TResolverBaseType): TResEvalvalue;
|
function EvalBaseTypeCast(Params: TParamsExpr; bt: TResolverBaseType): TResEvalvalue;
|
||||||
protected
|
protected
|
||||||
// generic/specialize
|
// generic/specialize
|
||||||
|
type
|
||||||
|
TScopeStashState = record
|
||||||
|
ScopeCount: integer;
|
||||||
|
StashCount: integer;
|
||||||
|
end;
|
||||||
procedure AddGenericTemplateIdentifiers(GenericTemplateTypes: TFPList;
|
procedure AddGenericTemplateIdentifiers(GenericTemplateTypes: TFPList;
|
||||||
Scope: TPasIdentifierScope);
|
Scope: TPasIdentifierScope);
|
||||||
procedure AddSpecializedTemplateIdentifiers(GenericTemplateTypes: TFPList;
|
procedure AddSpecializedTemplateIdentifiers(GenericTemplateTypes: TFPList;
|
||||||
@ -1789,7 +1794,8 @@ type
|
|||||||
GenTempl: TPasGenericTemplateType; ErrorPos: TPasElement);
|
GenTempl: TPasGenericTemplateType; ErrorPos: TPasElement);
|
||||||
function CreateSpecializedItem(El: TPasElement; GenericEl: TPasElement;
|
function CreateSpecializedItem(El: TPasElement; GenericEl: TPasElement;
|
||||||
const ParamsResolved: TPasTypeArray): TPRSpecializedItem; virtual;
|
const ParamsResolved: TPasTypeArray): TPRSpecializedItem; virtual;
|
||||||
function InitSpecializeScopes(El: TPasElement): integer; virtual;
|
procedure InitSpecializeScopes(El: TPasElement; out State: TScopeStashState); virtual;
|
||||||
|
procedure RestoreSpecializeScopes(const State: TScopeStashState); virtual;
|
||||||
procedure SpecializeGenericIntf(SpecializedItem: TPRSpecializedItem); virtual;
|
procedure SpecializeGenericIntf(SpecializedItem: TPRSpecializedItem); virtual;
|
||||||
procedure SpecializeGenericImpl(SpecializedItem: TPRSpecializedItem); virtual;
|
procedure SpecializeGenericImpl(SpecializedItem: TPRSpecializedItem); virtual;
|
||||||
procedure SpecializeMembers(GenMembersType, SpecMembersType: TPasMembersType); virtual;
|
procedure SpecializeMembers(GenMembersType, SpecMembersType: TPasMembersType); virtual;
|
||||||
@ -6027,7 +6033,7 @@ type
|
|||||||
end;
|
end;
|
||||||
var
|
var
|
||||||
ClassScope: TPasClassScope;
|
ClassScope: TPasClassScope;
|
||||||
i, j, k, OldStashCount: Integer;
|
i, j, k: Integer;
|
||||||
IntfType: TPasClassType;
|
IntfType: TPasClassType;
|
||||||
Resolutions: array of TMethResolution;
|
Resolutions: array of TMethResolution;
|
||||||
Map: TPasClassIntfMap;
|
Map: TPasClassIntfMap;
|
||||||
@ -6043,6 +6049,7 @@ var
|
|||||||
SectionScope: TPasSectionScope;
|
SectionScope: TPasSectionScope;
|
||||||
SpecializedItems: TObjectList;
|
SpecializedItems: TObjectList;
|
||||||
SpecializedItem: TPRSpecializedTypeItem;
|
SpecializedItem: TPRSpecializedTypeItem;
|
||||||
|
OldScopeState: TScopeStashState;
|
||||||
begin
|
begin
|
||||||
Resolutions:=nil;
|
Resolutions:=nil;
|
||||||
ClassScope:=nil;
|
ClassScope:=nil;
|
||||||
@ -6218,7 +6225,7 @@ begin
|
|||||||
SpecializedItem:=TPRSpecializedTypeItem(SpecializedItems[i]);
|
SpecializedItem:=TPRSpecializedTypeItem(SpecializedItems[i]);
|
||||||
SpecializedItem.GenericEl:=El;
|
SpecializedItem.GenericEl:=El;
|
||||||
if SpecializedItem.Step<>prssNone then continue;
|
if SpecializedItem.Step<>prssNone then continue;
|
||||||
OldStashCount:=InitSpecializeScopes(El);
|
InitSpecializeScopes(El,OldScopeState);
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
WriteScopesShort('TPasResolver.FinishClassType Finishing specialize interface: '+GetObjName(SpecializedItem.SpecializedType));
|
WriteScopesShort('TPasResolver.FinishClassType Finishing specialize interface: '+GetObjName(SpecializedItem.SpecializedType));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -6228,7 +6235,7 @@ begin
|
|||||||
WriteScopesShort('TPasResolver.FinishClassType Finished specialize interface: '+GetObjName(SpecializedItem.SpecializedType));
|
WriteScopesShort('TPasResolver.FinishClassType Finished specialize interface: '+GetObjName(SpecializedItem.SpecializedType));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
RestoreStashedScopes(OldStashCount);
|
RestoreSpecializeScopes(OldScopeState);
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
WriteScopesShort('TPasResolver.FinishClassType RestoreStashedScopes '+GetObjName(SpecializedItem.SpecializedType));
|
WriteScopesShort('TPasResolver.FinishClassType RestoreStashedScopes '+GetObjName(SpecializedItem.SpecializedType));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -7026,13 +7033,16 @@ begin
|
|||||||
ProcScope.ClassRecScope:=ClassOrRecScope;
|
ProcScope.ClassRecScope:=ClassOrRecScope;
|
||||||
|
|
||||||
TemplTypes:=GetProcTemplateTypes(Proc);
|
TemplTypes:=GetProcTemplateTypes(Proc);
|
||||||
if TemplTypes<>nil then
|
|
||||||
RaiseNotYetImplemented(20190911105953,Proc);
|
|
||||||
|
|
||||||
FindData:=Default(TFindProcData);
|
FindData:=Default(TFindProcData);
|
||||||
IsClassConDestructor:=(Proc.ClassType=TPasClassConstructor)
|
IsClassConDestructor:=(Proc.ClassType=TPasClassConstructor)
|
||||||
or (Proc.ClassType=TPasClassDestructor);
|
or (Proc.ClassType=TPasClassDestructor);
|
||||||
if not IsClassConDestructor then
|
if IsClassConDestructor then
|
||||||
|
begin
|
||||||
|
if TemplTypes<>nil then
|
||||||
|
RaiseNotYetImplemented(20190911105953,Proc);
|
||||||
|
end
|
||||||
|
else
|
||||||
begin
|
begin
|
||||||
FindData.Proc:=Proc;
|
FindData.Proc:=Proc;
|
||||||
FindData.Args:=Proc.ProcType.Args;
|
FindData.Args:=Proc.ProcType.Args;
|
||||||
@ -7107,7 +7117,7 @@ var
|
|||||||
SelfArg: TPasArgument;
|
SelfArg: TPasArgument;
|
||||||
p: Integer;
|
p: Integer;
|
||||||
SelfType, LoSelfType: TPasType;
|
SelfType, LoSelfType: TPasType;
|
||||||
ImplTemplTypes: TFPList;
|
LastNamePart: TProcedureNamePart;
|
||||||
begin
|
begin
|
||||||
if ImplProc.IsExternal then
|
if ImplProc.IsExternal then
|
||||||
RaiseMsg(20170216151715,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(ImplProc),'external'],ImplProc);
|
RaiseMsg(20170216151715,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(ImplProc),'external'],ImplProc);
|
||||||
@ -7126,10 +7136,8 @@ begin
|
|||||||
|
|
||||||
if ImplProc.NameParts<>nil then
|
if ImplProc.NameParts<>nil then
|
||||||
begin
|
begin
|
||||||
ProcName:=TProcedureNamePart(ImplProc.NameParts[ImplProc.NameParts.Count-1]).Name;
|
LastNamePart:=TProcedureNamePart(ImplProc.NameParts[ImplProc.NameParts.Count-1]);
|
||||||
ImplTemplTypes:=GetProcTemplateTypes(ImplProc);
|
ProcName:=LastNamePart.Name;
|
||||||
if ImplTemplTypes<>nil then
|
|
||||||
RaiseNotYetImplemented(20190911105319,ImplProc);
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@ -7139,7 +7147,6 @@ begin
|
|||||||
if p<1 then break;
|
if p<1 then break;
|
||||||
Delete(ProcName,1,p);
|
Delete(ProcName,1,p);
|
||||||
until false;
|
until false;
|
||||||
ImplTemplTypes:=nil;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if ImplProcScope.DeclarationProc=nil then
|
if ImplProcScope.DeclarationProc=nil then
|
||||||
@ -12222,11 +12229,6 @@ begin
|
|||||||
NamePart:=TProcedureNamePart(TypeParams[Level-1]);
|
NamePart:=TProcedureNamePart(TypeParams[Level-1]);
|
||||||
if NamePart.Name<>ProcName then
|
if NamePart.Name<>ProcName then
|
||||||
RaiseNotYetImplemented(20190818122551,El,IntToStr(Level)+': '+NamePart.Name+'<>'+ProcName);
|
RaiseNotYetImplemented(20190818122551,El,IntToStr(Level)+': '+NamePart.Name+'<>'+ProcName);
|
||||||
if NamePart.Templates<>nil then
|
|
||||||
begin
|
|
||||||
// ToDo: generic method
|
|
||||||
RaiseNotYetImplemented(20190818122619,El);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -15959,7 +15961,8 @@ begin
|
|||||||
SpecializeGenericImpl(Result);
|
SpecializeGenericImpl(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPasResolver.InitSpecializeScopes(El: TPasElement): integer;
|
procedure TPasResolver.InitSpecializeScopes(El: TPasElement; out
|
||||||
|
State: TScopeStashState);
|
||||||
|
|
||||||
function PushParentScopes(CurEl: TPasElement): integer;
|
function PushParentScopes(CurEl: TPasElement): integer;
|
||||||
var
|
var
|
||||||
@ -16012,6 +16015,7 @@ function TPasResolver.InitSpecializeScopes(El: TPasElement): integer;
|
|||||||
StashScopes(Keep);
|
StashScopes(Keep);
|
||||||
if Keep<>FScopeCount then
|
if Keep<>FScopeCount then
|
||||||
RaiseNotYetImplemented(20190813005130,El);
|
RaiseNotYetImplemented(20190813005130,El);
|
||||||
|
State.ScopeCount:=ScopeCount;
|
||||||
end;
|
end;
|
||||||
if (CurEl.ClassType=TImplementationSection) then
|
if (CurEl.ClassType=TImplementationSection) then
|
||||||
begin
|
begin
|
||||||
@ -16035,7 +16039,8 @@ begin
|
|||||||
{$IFDEF VerboseInitSpecializeScopes}
|
{$IFDEF VerboseInitSpecializeScopes}
|
||||||
writeln('TPasResolver.InitSpecializeScopes START ',GetObjName(El));
|
writeln('TPasResolver.InitSpecializeScopes START ',GetObjName(El));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
Result:=FStashScopeCount;
|
State.ScopeCount:=ScopeCount;
|
||||||
|
State.StashCount:=FStashScopeCount;
|
||||||
Keep:=PushParentScopes(El.Parent)+1;
|
Keep:=PushParentScopes(El.Parent)+1;
|
||||||
if Keep<FScopeCount then
|
if Keep<FScopeCount then
|
||||||
begin
|
begin
|
||||||
@ -16052,17 +16057,24 @@ begin
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPasResolver.RestoreSpecializeScopes(const State: TScopeStashState);
|
||||||
|
begin
|
||||||
|
while ScopeCount>State.ScopeCount do
|
||||||
|
PopScope;
|
||||||
|
RestoreStashedScopes(State.StashCount);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TPasResolver.SpecializeGenericIntf(SpecializedItem: TPRSpecializedItem
|
procedure TPasResolver.SpecializeGenericIntf(SpecializedItem: TPRSpecializedItem
|
||||||
);
|
);
|
||||||
var
|
var
|
||||||
SpecEl, GenericEl: TPasElement;
|
SpecEl, GenericEl: TPasElement;
|
||||||
OldStashCount: Integer;
|
|
||||||
C: TClass;
|
C: TClass;
|
||||||
NewRecordType, GenRecordType: TPasRecordType;
|
NewRecordType, GenRecordType: TPasRecordType;
|
||||||
NewClassType, GenClassType: TPasClassType;
|
NewClassType, GenClassType: TPasClassType;
|
||||||
NewArrayType, GenArrayType: TPasArrayType;
|
NewArrayType, GenArrayType: TPasArrayType;
|
||||||
GenProcType, NewProcType: TPasProcedureType;
|
GenProcType, NewProcType: TPasProcedureType;
|
||||||
GenProc, NewProc: TPasProcedure;
|
GenProc, NewProc: TPasProcedure;
|
||||||
|
OldScopeState: TScopeStashState;
|
||||||
begin
|
begin
|
||||||
if SpecializedItem.Step<>prssNone then
|
if SpecializedItem.Step<>prssNone then
|
||||||
exit;
|
exit;
|
||||||
@ -16071,7 +16083,8 @@ begin
|
|||||||
GenericEl:=SpecializedItem.GenericEl;
|
GenericEl:=SpecializedItem.GenericEl;
|
||||||
|
|
||||||
// change scope
|
// change scope
|
||||||
OldStashCount:=InitSpecializeScopes(GenericEl);
|
WriteScopesShort('AAA1 TPasResolver.SpecializeGenericIntf *******************');
|
||||||
|
InitSpecializeScopes(GenericEl,OldScopeState);
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
WriteScopesShort('TPasResolver.SpecializeGenericIntf Init SpecEl='+SpecEl.FullName+' GenericEl='+GenericEl.FullName);
|
WriteScopesShort('TPasResolver.SpecializeGenericIntf Init SpecEl='+SpecEl.FullName+' GenericEl='+GenericEl.FullName);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -16117,7 +16130,7 @@ begin
|
|||||||
WriteScopesShort('TPasResolver.SpecializeGenericIntf Finish: '+SpecEl.FullName);
|
WriteScopesShort('TPasResolver.SpecializeGenericIntf Finish: '+SpecEl.FullName);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
RestoreStashedScopes(OldStashCount);
|
RestoreSpecializeScopes(OldScopeState);
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
WriteScopesShort('TPasResolver.SpecializeGenericIntf RestoreStashedScopes: '+SpecEl.FullName);
|
WriteScopesShort('TPasResolver.SpecializeGenericIntf RestoreStashedScopes: '+SpecEl.FullName);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -16132,7 +16145,7 @@ var
|
|||||||
SpecializedProcItem: TPRSpecializedProcItem;
|
SpecializedProcItem: TPRSpecializedProcItem;
|
||||||
GenImplProc, GenIntfProc, SpecDeclProc: TPasProcedure;
|
GenImplProc, GenIntfProc, SpecDeclProc: TPasProcedure;
|
||||||
GenDeclProcScope: TPasProcedureScope;
|
GenDeclProcScope: TPasProcedureScope;
|
||||||
OldStashCount: Integer;
|
OldScopeState: TScopeStashState;
|
||||||
begin
|
begin
|
||||||
// check specialized type step
|
// check specialized type step
|
||||||
if SpecializedItem.Step>prssInterfaceFinished then
|
if SpecializedItem.Step>prssInterfaceFinished then
|
||||||
@ -16179,9 +16192,9 @@ begin
|
|||||||
RaiseNotYetImplemented(20190920192731,GenImplProc); // GenScope.GenericStep is wrong
|
RaiseNotYetImplemented(20190920192731,GenImplProc); // GenScope.GenericStep is wrong
|
||||||
SpecDeclProc:=SpecializedProcItem.SpecializedProc;
|
SpecDeclProc:=SpecializedProcItem.SpecializedProc;
|
||||||
|
|
||||||
OldStashCount:=InitSpecializeScopes(GenImplProc);
|
InitSpecializeScopes(GenImplProc,OldScopeState);
|
||||||
SpecializeGenImplProc(GenIntfProc,SpecDeclProc,SpecializedProcItem);
|
SpecializeGenImplProc(GenIntfProc,SpecDeclProc,SpecializedProcItem);
|
||||||
RestoreStashedScopes(OldStashCount);
|
RestoreSpecializeScopes(OldScopeState);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -16211,10 +16224,11 @@ procedure TPasResolver.SpecializeMembersImpl(GenericType,
|
|||||||
SpecType: TPasMembersType; SpecializedItem: TPRSpecializedTypeItem);
|
SpecType: TPasMembersType; SpecializedItem: TPRSpecializedTypeItem);
|
||||||
var
|
var
|
||||||
GenClassOrRec, SpecClassOrRec: TPasMembersType;
|
GenClassOrRec, SpecClassOrRec: TPasMembersType;
|
||||||
OldStashCount, i: Integer;
|
i: Integer;
|
||||||
GenMember, SpecMember, ImplParent: TPasElement;
|
GenMember, SpecMember, ImplParent: TPasElement;
|
||||||
GenIntfProc, GenImplProc, SpecIntfProc: TPasProcedure;
|
GenIntfProc, GenImplProc, SpecIntfProc: TPasProcedure;
|
||||||
GenIntfProcScope: TPasProcedureScope;
|
GenIntfProcScope: TPasProcedureScope;
|
||||||
|
OldScopeState: TScopeStashState;
|
||||||
begin
|
begin
|
||||||
GenClassOrRec:=TPasMembersType(GenericType);
|
GenClassOrRec:=TPasMembersType(GenericType);
|
||||||
SpecClassOrRec:=TPasMembersType(SpecType);
|
SpecClassOrRec:=TPasMembersType(SpecType);
|
||||||
@ -16225,7 +16239,7 @@ begin
|
|||||||
|
|
||||||
// specialize member bodies
|
// specialize member bodies
|
||||||
ImplParent:=nil;
|
ImplParent:=nil;
|
||||||
OldStashCount:=FStashScopeCount;
|
OldScopeState:=default(TScopeStashState);
|
||||||
for i:=0 to GenClassOrRec.Members.Count-1 do
|
for i:=0 to GenClassOrRec.Members.Count-1 do
|
||||||
begin
|
begin
|
||||||
GenMember:=TPasElement(GenClassOrRec.Members[i]);
|
GenMember:=TPasElement(GenClassOrRec.Members[i]);
|
||||||
@ -16247,7 +16261,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
// switch scope (e.g. unit implementation section)
|
// switch scope (e.g. unit implementation section)
|
||||||
ImplParent:=GenImplProc.Parent;
|
ImplParent:=GenImplProc.Parent;
|
||||||
OldStashCount:=InitSpecializeScopes(GenImplProc);
|
InitSpecializeScopes(GenImplProc,OldScopeState);
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
writeln('TPasResolver.SpecializeGenImplProc Specialize implprocs: SpecType=',GetObjName(SpecType),' ImplParent=',GetObjName(ImplParent),' ScopeCount=',ScopeCount,' FStashScopeCount=',FStashScopeCount,' TopScope=',GetObjName(TopScope));
|
writeln('TPasResolver.SpecializeGenImplProc Specialize implprocs: SpecType=',GetObjName(SpecType),' ImplParent=',GetObjName(ImplParent),' ScopeCount=',ScopeCount,' FStashScopeCount=',FStashScopeCount,' TopScope=',GetObjName(TopScope));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -16267,7 +16281,7 @@ begin
|
|||||||
if ImplParent<>nil then
|
if ImplParent<>nil then
|
||||||
begin
|
begin
|
||||||
// restore scope
|
// restore scope
|
||||||
RestoreStashedScopes(OldStashCount);
|
RestoreSpecializeScopes(OldScopeState);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -16808,8 +16822,7 @@ begin
|
|||||||
RaiseNotYetImplemented(20190920203700,SpecEl);
|
RaiseNotYetImplemented(20190920203700,SpecEl);
|
||||||
if GenProcScope.OverriddenProc<>nil then
|
if GenProcScope.OverriddenProc<>nil then
|
||||||
RaiseNotYetImplemented(20190920203536,SpecEl);
|
RaiseNotYetImplemented(20190920203536,SpecEl);
|
||||||
if GenProcScope.ClassRecScope<>nil then
|
SpecProcScope.ClassRecScope:=GenProcScope.ClassRecScope;
|
||||||
RaiseNotYetImplemented(20190920203609,SpecEl);
|
|
||||||
if GenProcScope.SelfArg<>nil then
|
if GenProcScope.SelfArg<>nil then
|
||||||
RaiseNotYetImplemented(20190920203626,SpecEl);
|
RaiseNotYetImplemented(20190920203626,SpecEl);
|
||||||
// SpecProcScope.Flags
|
// SpecProcScope.Flags
|
||||||
@ -16897,7 +16910,7 @@ begin
|
|||||||
FinishProcedure(SpecEl);
|
FinishProcedure(SpecEl);
|
||||||
end
|
end
|
||||||
else if SpecializedItem=nil then
|
else if SpecializedItem=nil then
|
||||||
// forward or unit-intf declaration
|
// declaration proc, parent is specialized
|
||||||
FinishProcedure(SpecEl)
|
FinishProcedure(SpecEl)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
@ -4683,14 +4683,17 @@ procedure TPasProcedure.ForEachCall(const aMethodCall: TOnForEachPasElement;
|
|||||||
const Arg: Pointer);
|
const Arg: Pointer);
|
||||||
var
|
var
|
||||||
i, j: Integer;
|
i, j: Integer;
|
||||||
|
Templates: TFPList;
|
||||||
begin
|
begin
|
||||||
inherited ForEachCall(aMethodCall, Arg);
|
inherited ForEachCall(aMethodCall, Arg);
|
||||||
if NameParts<>nil then
|
if NameParts<>nil then
|
||||||
for i:=0 to NameParts.Count-1 do
|
for i:=0 to NameParts.Count-1 do
|
||||||
with TProcedureNamePart(NameParts[i]) do
|
begin
|
||||||
if Templates<>nil then
|
Templates:=TProcedureNamePart(NameParts[i]).Templates;
|
||||||
for j:=0 to Templates.Count-1 do
|
if Templates<>nil then
|
||||||
ForEachChildCall(aMethodCall,Arg,TPasElement(Templates[i]),false);
|
for j:=0 to Templates.Count-1 do
|
||||||
|
ForEachChildCall(aMethodCall,Arg,TPasElement(Templates[j]),false);
|
||||||
|
end;
|
||||||
ForEachChildCall(aMethodCall,Arg,ProcType,false);
|
ForEachChildCall(aMethodCall,Arg,ProcType,false);
|
||||||
ForEachChildCall(aMethodCall,Arg,PublicName,false);
|
ForEachChildCall(aMethodCall,Arg,PublicName,false);
|
||||||
ForEachChildCall(aMethodCall,Arg,LibraryExpr,false);
|
ForEachChildCall(aMethodCall,Arg,LibraryExpr,false);
|
||||||
|
@ -143,7 +143,10 @@ type
|
|||||||
// generic methods
|
// generic methods
|
||||||
procedure TestGenMethod_VirtualFail;
|
procedure TestGenMethod_VirtualFail;
|
||||||
procedure TestGenMethod_ClassInterfaceMethodFail;
|
procedure TestGenMethod_ClassInterfaceMethodFail;
|
||||||
// ToDo: parametrized method mismatch interface method
|
procedure TestGenMethod_ClassConstructorFail;
|
||||||
|
procedure TestGenMethod_TemplNameDifferFail;
|
||||||
|
procedure TestGenMethod_ImplConstraintFail;
|
||||||
|
procedure TestGenMethod_TypeParamCntOverload;
|
||||||
// ToDo: generic class method overload <T> <S,T>
|
// ToDo: generic class method overload <T> <S,T>
|
||||||
// ToDo: generic class method overload <T>(bool) <T>(word)
|
// ToDo: generic class method overload <T>(bool) <T>(word)
|
||||||
// ToDo: procedure TestGenMethod_ClassConstructorFail;
|
// ToDo: procedure TestGenMethod_ClassConstructorFail;
|
||||||
@ -2042,6 +2045,80 @@ begin
|
|||||||
CheckParserException('generic is not allowed in interface',nParserXNotAllowedInY);
|
CheckParserException('generic is not allowed in interface',nParserXNotAllowedInY);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolveGenerics.TestGenMethod_ClassConstructorFail;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TObject = class',
|
||||||
|
' generic class constructor Run<T>(a: T);',
|
||||||
|
' end;',
|
||||||
|
'generic class constructor TObject.Run<T>(a: T);',
|
||||||
|
'begin end;',
|
||||||
|
'begin',
|
||||||
|
'']);
|
||||||
|
CheckParserException('Expected "Procedure" or "Function" at token "constructor" in file afile.pp at line 4 column 19',
|
||||||
|
nParserExpectToken2Error);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolveGenerics.TestGenMethod_TemplNameDifferFail;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TObject = class',
|
||||||
|
' generic procedure Run<T>(a: T);',
|
||||||
|
' end;',
|
||||||
|
'generic procedure TObject.Run<S>(a: S);',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'begin',
|
||||||
|
'']);
|
||||||
|
CheckResolverException('Declaration of "TObject.Run<S>" differs from previous declaration at afile.pp(4,28)',
|
||||||
|
nDeclOfXDiffersFromPrevAtY);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolveGenerics.TestGenMethod_ImplConstraintFail;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TObject = class',
|
||||||
|
' generic procedure Run<T>(a: T);',
|
||||||
|
' end;',
|
||||||
|
'generic procedure TObject.Run<T: class>(a: T);',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'begin',
|
||||||
|
'']);
|
||||||
|
CheckResolverException(sImplMustNotRepeatConstraints,nImplMustNotRepeatConstraints);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolveGenerics.TestGenMethod_TypeParamCntOverload;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TObject = class',
|
||||||
|
' generic procedure {#A}Run<T>(a: T);',
|
||||||
|
' generic procedure {#B}Run<M,N>(a: M);',
|
||||||
|
' end;',
|
||||||
|
'generic procedure TObject.Run<T>(a: T);',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'generic procedure TObject.Run<M,N>(a: M);',
|
||||||
|
'begin',
|
||||||
|
' specialize {@A}Run<M>(a);',
|
||||||
|
' specialize {@B}Run<double,char>(1.3);',
|
||||||
|
'end;',
|
||||||
|
'var obj: TObject;',
|
||||||
|
'begin',
|
||||||
|
' obj.specialize {@A}Run<word>(3);',
|
||||||
|
' obj.specialize {@B}Run<word,char>(4);',
|
||||||
|
'']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
RegisterTests([TTestResolveGenerics]);
|
RegisterTests([TTestResolveGenerics]);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ type
|
|||||||
Procedure TestGen_ClassAncestor;
|
Procedure TestGen_ClassAncestor;
|
||||||
Procedure TestGen_TypeInfo;
|
Procedure TestGen_TypeInfo;
|
||||||
// ToDo: TBird, TBird<T>, TBird<S,T>
|
// ToDo: TBird, TBird<T>, TBird<S,T>
|
||||||
// ToDo: local const T
|
// ToDo: rename local const T
|
||||||
|
|
||||||
// generic external class
|
// generic external class
|
||||||
procedure TestGen_ExtClass_Array;
|
procedure TestGen_ExtClass_Array;
|
||||||
|
@ -2762,7 +2762,8 @@ End.
|
|||||||
<li>You can typecast function addresses and function references to JS
|
<li>You can typecast function addresses and function references to JS
|
||||||
function, e.g. <i>TJSFunction(@SomeProc)</i>, <i>TJSFunction(OnClick)</i>.
|
function, e.g. <i>TJSFunction(@SomeProc)</i>, <i>TJSFunction(OnClick)</i>.
|
||||||
Keep in mind that typecasting a method address creates a function wrapper
|
Keep in mind that typecasting a method address creates a function wrapper
|
||||||
to bind the Self argument.</li>
|
to bind the Self argument, except when typecasting to <i>TJSFunction</i>
|
||||||
|
(pas2js 1.5+).</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -3009,6 +3010,7 @@ End.
|
|||||||
<li>{$mode delphi} or {$mode objfpc}: Same as -Mdelphi or -Mobjfpc, but only for this unit. You can use units of both modes in a program. If present must be at the top of the unit, or after the module name.</li>
|
<li>{$mode delphi} or {$mode objfpc}: Same as -Mdelphi or -Mobjfpc, but only for this unit. You can use units of both modes in a program. If present must be at the top of the unit, or after the module name.</li>
|
||||||
<li>{$modeswitch externalclass}: allow declaring external classes</li>
|
<li>{$modeswitch externalclass}: allow declaring external classes</li>
|
||||||
<li>{$modeswitch arrayoperators}: allow + operator to concatenate arrays, default in mode delphi</li>
|
<li>{$modeswitch arrayoperators}: allow + operator to concatenate arrays, default in mode delphi</li>
|
||||||
|
<li>{$modeswitch OmitRTTI}: treat published sections as public</li>
|
||||||
<li>{$macro on|off} enables macro replacements. Only macros with a value are replaced. Macros are never replaced inside directives.</li>
|
<li>{$macro on|off} enables macro replacements. Only macros with a value are replaced. Macros are never replaced inside directives.</li>
|
||||||
<li>{$I filename} or {$include filename} - insert include file</li>
|
<li>{$I filename} or {$include filename} - insert include file</li>
|
||||||
<li>{$I %param%}:
|
<li>{$I %param%}:
|
||||||
@ -3072,6 +3074,8 @@ End.
|
|||||||
<li>Check type casts, e.g. <i>TBird(AnObject)</i> becomes <i>AnObject as TBird</i></li>
|
<li>Check type casts, e.g. <i>TBird(AnObject)</i> becomes <i>AnObject as TBird</i></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li>{$DispatchField Msg}: enable checking <i>message number</i> methods for record field name "Msg"</li>
|
||||||
|
<li>{$DispatchStrField MsgStr}: enable checking <i>message string</i> methods for record field name "Msg"</li>
|
||||||
</ul>
|
</ul>
|
||||||
Defines:
|
Defines:
|
||||||
<ul>
|
<ul>
|
||||||
|
Loading…
Reference in New Issue
Block a user