mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 16:09:25 +02:00
fcl-passrc: specialize procedure type
git-svn-id: trunk@42678 -
This commit is contained in:
parent
5d8078f666
commit
3ddefe999e
@ -952,6 +952,12 @@ type
|
|||||||
public
|
public
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TPasProcTypeScope }
|
||||||
|
|
||||||
|
TPasProcTypeScope = Class(TPasGenericScope)
|
||||||
|
public
|
||||||
|
end;
|
||||||
|
|
||||||
{ TPasClassOrRecordScope }
|
{ TPasClassOrRecordScope }
|
||||||
|
|
||||||
TPasClassOrRecordScope = Class(TPasGenericScope)
|
TPasClassOrRecordScope = Class(TPasGenericScope)
|
||||||
@ -1540,6 +1546,7 @@ type
|
|||||||
procedure AddEnumType(El: TPasEnumType); virtual;
|
procedure AddEnumType(El: TPasEnumType); virtual;
|
||||||
procedure AddEnumValue(El: TPasEnumValue); virtual;
|
procedure AddEnumValue(El: TPasEnumValue); virtual;
|
||||||
procedure AddProperty(El: TPasProperty); virtual;
|
procedure AddProperty(El: TPasProperty); virtual;
|
||||||
|
procedure AddProcedureType(El: TPasProcedureType; TypeParams: TFPList); virtual;
|
||||||
procedure AddProcedure(El: TPasProcedure); virtual;
|
procedure AddProcedure(El: TPasProcedure); virtual;
|
||||||
procedure AddProcedureBody(El: TProcedureBody); virtual;
|
procedure AddProcedureBody(El: TProcedureBody); virtual;
|
||||||
procedure AddArgument(El: TPasArgument); virtual;
|
procedure AddArgument(El: TPasArgument); virtual;
|
||||||
@ -1748,7 +1755,7 @@ type
|
|||||||
{$IFDEF CheckPasTreeRefCount}; const RefId: string{$ENDIF});
|
{$IFDEF CheckPasTreeRefCount}; const RefId: string{$ENDIF});
|
||||||
procedure SpecializeProcedure(GenEl, SpecEl: TPasProcedure);
|
procedure SpecializeProcedure(GenEl, SpecEl: TPasProcedure);
|
||||||
procedure SpecializeOperator(GenEl, SpecEl: TPasOperator);
|
procedure SpecializeOperator(GenEl, SpecEl: TPasOperator);
|
||||||
procedure SpecializeProcedureType(GenEl, SpecEl: TPasProcedureType);
|
procedure SpecializeProcedureType(GenEl, SpecEl: TPasProcedureType; SpecializedItem: TPSSpecializedItem);
|
||||||
procedure SpecializeProcedureBody(GenEl, SpecEl: TProcedureBody);
|
procedure SpecializeProcedureBody(GenEl, SpecEl: TProcedureBody);
|
||||||
procedure SpecializeDeclarations(GenEl, SpecEl: TPasDeclarations);
|
procedure SpecializeDeclarations(GenEl, SpecEl: TPasDeclarations);
|
||||||
procedure SpecializeSpecializeType(GenEl, SpecEl: TPasSpecializeType);
|
procedure SpecializeSpecializeType(GenEl, SpecEl: TPasSpecializeType);
|
||||||
@ -6174,7 +6181,6 @@ begin
|
|||||||
else if C=TPasArrayType then
|
else if C=TPasArrayType then
|
||||||
else if (C=TPasProcedureType)
|
else if (C=TPasProcedureType)
|
||||||
or (C=TPasFunctionType) then
|
or (C=TPasFunctionType) then
|
||||||
RaiseNotYetImplemented(20190812220555,aType,GetObjName(aType))
|
|
||||||
else
|
else
|
||||||
RaiseNotYetImplemented(20190726150359,aType,GetObjName(aType));
|
RaiseNotYetImplemented(20190726150359,aType,GetObjName(aType));
|
||||||
end;
|
end;
|
||||||
@ -6431,7 +6437,14 @@ var
|
|||||||
HelperForType: TPasType;
|
HelperForType: TPasType;
|
||||||
Args: TFPList;
|
Args: TFPList;
|
||||||
Arg: TPasArgument;
|
Arg: TPasArgument;
|
||||||
|
ProcTypeScope: TPasProcTypeScope;
|
||||||
begin
|
begin
|
||||||
|
if TopScope.Element=El then
|
||||||
|
begin
|
||||||
|
ProcTypeScope:=El.CustomData as TPasProcTypeScope;
|
||||||
|
ProcTypeScope.GenericStep:=psgsImplementationParsed;
|
||||||
|
PopScope;
|
||||||
|
end;
|
||||||
if El.Parent is TPasProcedure then
|
if El.Parent is TPasProcedure then
|
||||||
Proc:=TPasProcedure(El.Parent)
|
Proc:=TPasProcedure(El.Parent)
|
||||||
else
|
else
|
||||||
@ -11279,6 +11292,29 @@ begin
|
|||||||
PushScope(El,TPasPropertyScope);
|
PushScope(El,TPasPropertyScope);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPasResolver.AddProcedureType(El: TPasProcedureType;
|
||||||
|
TypeParams: TFPList);
|
||||||
|
var
|
||||||
|
Scope: TPasProcTypeScope;
|
||||||
|
begin
|
||||||
|
if El.Name<>'' then begin
|
||||||
|
{$IFDEF VerbosePasResolver}
|
||||||
|
writeln('TPasResolver.AddProcedureType ',GetObjName(El),' Parent=',GetObjName(El.Parent));
|
||||||
|
{$ENDIF}
|
||||||
|
if not (TopScope is TPasIdentifierScope) then
|
||||||
|
RaiseInvalidScopeForElement(20190813193703,El);
|
||||||
|
AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
|
||||||
|
end;
|
||||||
|
if TypeParams<>nil then
|
||||||
|
begin
|
||||||
|
// generic procedure type
|
||||||
|
if El.Name='' then
|
||||||
|
RaiseNotYetImplemented(20190813193745,El);
|
||||||
|
Scope:=TPasProcTypeScope(PushScope(El,TPasProcTypeScope));
|
||||||
|
AddGenericTemplateIdentifiers(TypeParams,Scope);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TPasResolver.AddProcedure(El: TPasProcedure);
|
procedure TPasResolver.AddProcedure(El: TPasProcedure);
|
||||||
|
|
||||||
procedure AddClassConDestructor(ClassOrRecordScope: TPasClassOrRecordScope;
|
procedure AddClassConDestructor(ClassOrRecordScope: TPasClassOrRecordScope;
|
||||||
@ -14744,6 +14780,7 @@ var
|
|||||||
NewArrayType, GenArrayType: TPasArrayType;
|
NewArrayType, GenArrayType: TPasArrayType;
|
||||||
NewRecordType, GenRecordType: TPasRecordType;
|
NewRecordType, GenRecordType: TPasRecordType;
|
||||||
HeaderScope: TPasClassHeaderScope;
|
HeaderScope: TPasClassHeaderScope;
|
||||||
|
GenProcType, NewProcType: TPasProcedureType;
|
||||||
begin
|
begin
|
||||||
if SpecializedItem.Step<>psssNone then
|
if SpecializedItem.Step<>psssNone then
|
||||||
exit;
|
exit;
|
||||||
@ -14830,6 +14867,14 @@ begin
|
|||||||
SpecializeArrayType(GenArrayType,NewArrayType,SpecializedItem);
|
SpecializeArrayType(GenArrayType,NewArrayType,SpecializedItem);
|
||||||
SpecializedItem.Step:=psssImplementationFinished;
|
SpecializedItem.Step:=psssImplementationFinished;
|
||||||
end
|
end
|
||||||
|
else if (C=TPasProcedureType)
|
||||||
|
or (C=TPasFunctionType) then
|
||||||
|
begin
|
||||||
|
GenProcType:=TPasProcedureType(GenericType);
|
||||||
|
NewProcType:=TPasProcedureType(SpecType);
|
||||||
|
SpecializeProcedureType(GenProcType,NewProcType,SpecializedItem);
|
||||||
|
SpecializedItem.Step:=psssImplementationFinished;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
RaiseNotYetImplemented(20190728134933,GenericType);
|
RaiseNotYetImplemented(20190728134933,GenericType);
|
||||||
end;
|
end;
|
||||||
@ -15128,8 +15173,8 @@ begin
|
|||||||
end
|
end
|
||||||
else if C.InheritsFrom(TPasProcedureType) then
|
else if C.InheritsFrom(TPasProcedureType) then
|
||||||
begin
|
begin
|
||||||
AddType(TPasProcedureType(SpecEl));
|
AddProcedureType(TPasProcedureType(SpecEl),nil);
|
||||||
SpecializeProcedureType(TPasProcedureType(GenEl),TPasProcedureType(SpecEl));
|
SpecializeProcedureType(TPasProcedureType(GenEl),TPasProcedureType(SpecEl),nil);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
RaiseNotYetImplemented(20190728151215,GenEl);
|
RaiseNotYetImplemented(20190728151215,GenEl);
|
||||||
@ -15352,13 +15397,30 @@ begin
|
|||||||
SpecializeProcedure(GenEl,SpecEl);
|
SpecializeProcedure(GenEl,SpecEl);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasResolver.SpecializeProcedureType(GenEl, SpecEl: TPasProcedureType
|
procedure TPasResolver.SpecializeProcedureType(GenEl,
|
||||||
);
|
SpecEl: TPasProcedureType; SpecializedItem: TPSSpecializedItem);
|
||||||
var
|
var
|
||||||
GenResultEl, NewResultEl: TPasResultElement;
|
GenResultEl, NewResultEl: TPasResultElement;
|
||||||
NewClass: TPTreeElement;
|
NewClass: TPTreeElement;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
GenScope: TPasGenericScope;
|
||||||
begin
|
begin
|
||||||
|
if GenEl.GenericTemplateTypes<>nil then
|
||||||
|
begin
|
||||||
|
GenScope:=TPasGenericScope(PushScope(SpecEl,TPasProcTypeScope));
|
||||||
|
if SpecializedItem<>nil then
|
||||||
|
begin
|
||||||
|
// specialized procedure type
|
||||||
|
GenScope.SpecializedItem:=SpecializedItem;
|
||||||
|
AddSpecializedTemplateIdentifiers(GenEl.GenericTemplateTypes,
|
||||||
|
SpecializedItem.Params,GenScope);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// generic procedure type inside a generic type
|
||||||
|
RaiseNotYetImplemented(20190813194550,GenEl);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
// Args
|
// Args
|
||||||
SpecializeElList(GenEl,SpecEl,GenEl.Args,SpecEl.Args,false
|
SpecializeElList(GenEl,SpecEl,GenEl.Args,SpecEl.Args,false
|
||||||
{$IFDEF CheckPasTreeRefCount},'TPasProcedureType.Args'{$ENDIF});
|
{$IFDEF CheckPasTreeRefCount},'TPasProcedureType.Args'{$ENDIF});
|
||||||
@ -18071,7 +18133,7 @@ begin
|
|||||||
AddArrayType(TPasArrayType(El),TypeParams)
|
AddArrayType(TPasArrayType(El),TypeParams)
|
||||||
else if (AClass=TPasProcedureType)
|
else if (AClass=TPasProcedureType)
|
||||||
or (AClass=TPasFunctionType) then
|
or (AClass=TPasFunctionType) then
|
||||||
AddType(TPasType(El)) // ToDo: TypeParams
|
AddProcedureType(TPasProcedureType(El),TypeParams)
|
||||||
else if AClass=TPasGenericTemplateType then
|
else if AClass=TPasGenericTemplateType then
|
||||||
// TPasParser first collects template types and later adds them as a list
|
// TPasParser first collects template types and later adds them as a list
|
||||||
// they are not real types
|
// they are not real types
|
||||||
|
@ -68,7 +68,8 @@ type
|
|||||||
// generic array
|
// generic array
|
||||||
procedure TestGen_Array;
|
procedure TestGen_Array;
|
||||||
|
|
||||||
// ToDo: generic procedure type
|
// generic procedure type
|
||||||
|
procedure TestGen_ProcType;
|
||||||
|
|
||||||
// ToDo: pointer of generic
|
// ToDo: pointer of generic
|
||||||
|
|
||||||
@ -608,12 +609,40 @@ begin
|
|||||||
' a[1]:=2;',
|
' a[1]:=2;',
|
||||||
' b[2]:=a[3]+b[4];',
|
' b[2]:=a[3]+b[4];',
|
||||||
' a:=b;',
|
' a:=b;',
|
||||||
|
' b:=a;',
|
||||||
' SetLength(a,5);',
|
' SetLength(a,5);',
|
||||||
' SetLength(b,6);',
|
' SetLength(b,6);',
|
||||||
'']);
|
'']);
|
||||||
ParseProgram;
|
ParseProgram;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolveGenerics.TestGen_ProcType;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' generic TFunc<T> = function(v: T): T;',
|
||||||
|
' TWordFunc = specialize TFunc<word>;',
|
||||||
|
'function GetIt(w: word): word;',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'var',
|
||||||
|
' a: specialize TFunc<word>;',
|
||||||
|
' b: TWordFunc;',
|
||||||
|
' w: word;',
|
||||||
|
'begin',
|
||||||
|
' a:=nil;',
|
||||||
|
' b:=nil;',
|
||||||
|
' a:=b;',
|
||||||
|
' b:=a;',
|
||||||
|
' w:=a(w);',
|
||||||
|
' w:=b(w);',
|
||||||
|
' a:=@GetIt;',
|
||||||
|
' b:=@GetIt;',
|
||||||
|
'']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestResolveGenerics.TestGen_GenericFunction;
|
procedure TTestResolveGenerics.TestGen_GenericFunction;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user