fcl-passrc: specialize procedure type

git-svn-id: trunk@42678 -
This commit is contained in:
Mattias Gaertner 2019-08-13 17:47:31 +00:00
parent 5d8078f666
commit 3ddefe999e
2 changed files with 99 additions and 8 deletions

View File

@ -952,6 +952,12 @@ type
public
end;
{ TPasProcTypeScope }
TPasProcTypeScope = Class(TPasGenericScope)
public
end;
{ TPasClassOrRecordScope }
TPasClassOrRecordScope = Class(TPasGenericScope)
@ -1540,6 +1546,7 @@ type
procedure AddEnumType(El: TPasEnumType); virtual;
procedure AddEnumValue(El: TPasEnumValue); virtual;
procedure AddProperty(El: TPasProperty); virtual;
procedure AddProcedureType(El: TPasProcedureType; TypeParams: TFPList); virtual;
procedure AddProcedure(El: TPasProcedure); virtual;
procedure AddProcedureBody(El: TProcedureBody); virtual;
procedure AddArgument(El: TPasArgument); virtual;
@ -1748,7 +1755,7 @@ type
{$IFDEF CheckPasTreeRefCount}; const RefId: string{$ENDIF});
procedure SpecializeProcedure(GenEl, SpecEl: TPasProcedure);
procedure SpecializeOperator(GenEl, SpecEl: TPasOperator);
procedure SpecializeProcedureType(GenEl, SpecEl: TPasProcedureType);
procedure SpecializeProcedureType(GenEl, SpecEl: TPasProcedureType; SpecializedItem: TPSSpecializedItem);
procedure SpecializeProcedureBody(GenEl, SpecEl: TProcedureBody);
procedure SpecializeDeclarations(GenEl, SpecEl: TPasDeclarations);
procedure SpecializeSpecializeType(GenEl, SpecEl: TPasSpecializeType);
@ -6174,7 +6181,6 @@ begin
else if C=TPasArrayType then
else if (C=TPasProcedureType)
or (C=TPasFunctionType) then
RaiseNotYetImplemented(20190812220555,aType,GetObjName(aType))
else
RaiseNotYetImplemented(20190726150359,aType,GetObjName(aType));
end;
@ -6431,7 +6437,14 @@ var
HelperForType: TPasType;
Args: TFPList;
Arg: TPasArgument;
ProcTypeScope: TPasProcTypeScope;
begin
if TopScope.Element=El then
begin
ProcTypeScope:=El.CustomData as TPasProcTypeScope;
ProcTypeScope.GenericStep:=psgsImplementationParsed;
PopScope;
end;
if El.Parent is TPasProcedure then
Proc:=TPasProcedure(El.Parent)
else
@ -11279,6 +11292,29 @@ begin
PushScope(El,TPasPropertyScope);
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 AddClassConDestructor(ClassOrRecordScope: TPasClassOrRecordScope;
@ -14744,6 +14780,7 @@ var
NewArrayType, GenArrayType: TPasArrayType;
NewRecordType, GenRecordType: TPasRecordType;
HeaderScope: TPasClassHeaderScope;
GenProcType, NewProcType: TPasProcedureType;
begin
if SpecializedItem.Step<>psssNone then
exit;
@ -14830,6 +14867,14 @@ begin
SpecializeArrayType(GenArrayType,NewArrayType,SpecializedItem);
SpecializedItem.Step:=psssImplementationFinished;
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
RaiseNotYetImplemented(20190728134933,GenericType);
end;
@ -15128,8 +15173,8 @@ begin
end
else if C.InheritsFrom(TPasProcedureType) then
begin
AddType(TPasProcedureType(SpecEl));
SpecializeProcedureType(TPasProcedureType(GenEl),TPasProcedureType(SpecEl));
AddProcedureType(TPasProcedureType(SpecEl),nil);
SpecializeProcedureType(TPasProcedureType(GenEl),TPasProcedureType(SpecEl),nil);
end
else
RaiseNotYetImplemented(20190728151215,GenEl);
@ -15352,13 +15397,30 @@ begin
SpecializeProcedure(GenEl,SpecEl);
end;
procedure TPasResolver.SpecializeProcedureType(GenEl, SpecEl: TPasProcedureType
);
procedure TPasResolver.SpecializeProcedureType(GenEl,
SpecEl: TPasProcedureType; SpecializedItem: TPSSpecializedItem);
var
GenResultEl, NewResultEl: TPasResultElement;
NewClass: TPTreeElement;
i: Integer;
GenScope: TPasGenericScope;
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
SpecializeElList(GenEl,SpecEl,GenEl.Args,SpecEl.Args,false
{$IFDEF CheckPasTreeRefCount},'TPasProcedureType.Args'{$ENDIF});
@ -18071,7 +18133,7 @@ begin
AddArrayType(TPasArrayType(El),TypeParams)
else if (AClass=TPasProcedureType)
or (AClass=TPasFunctionType) then
AddType(TPasType(El)) // ToDo: TypeParams
AddProcedureType(TPasProcedureType(El),TypeParams)
else if AClass=TPasGenericTemplateType then
// TPasParser first collects template types and later adds them as a list
// they are not real types

View File

@ -68,7 +68,8 @@ type
// generic array
procedure TestGen_Array;
// ToDo: generic procedure type
// generic procedure type
procedure TestGen_ProcType;
// ToDo: pointer of generic
@ -608,12 +609,40 @@ begin
' a[1]:=2;',
' b[2]:=a[3]+b[4];',
' a:=b;',
' b:=a;',
' SetLength(a,5);',
' SetLength(b,6);',
'']);
ParseProgram;
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;
begin
StartProgram(false);