fcl-passrc: replace method impl arguments with intf arguments

git-svn-id: trunk@42690 -
This commit is contained in:
Mattias Gaertner 2019-08-14 12:38:06 +00:00
parent 55b1f676dc
commit 35d7fade97
3 changed files with 138 additions and 12 deletions

View File

@ -778,6 +778,7 @@ function CodePointToString(CodePoint: longword): String;
function CodePointToUnicodeString(u: longword): UnicodeString; function CodePointToUnicodeString(u: longword): UnicodeString;
function GetObjName(o: TObject): string; function GetObjName(o: TObject): string;
function GetObjPath(o: TObject): string;
function dbgs(const Flags: TResEvalFlags): string; overload; function dbgs(const Flags: TResEvalFlags): string; overload;
function dbgs(v: TResEvalValue): string; overload; function dbgs(v: TResEvalValue): string; overload;
@ -1004,6 +1005,34 @@ begin
Result:=o.ClassName; Result:=o.ClassName;
end; end;
function GetObjPath(o: TObject): string;
var
El: TPasElement;
begin
if o is TPasElement then
begin
El:=TPasElement(o);
Result:=':'+El.ClassName;
while El<>nil do
begin
if El<>o then
Result:='.'+Result;
if El.Name<>'' then
begin
if IsValidIdent(El.Name) then
Result:=El.Name+Result
else
Result:='"'+El.Name+'"'+Result;
end
else
Result:='['+El.ClassName+']'+Result;
El:=El.Parent;
end;
end
else
Result:=GetObjName(o);
end;
function dbgs(const Flags: TResEvalFlags): string; function dbgs(const Flags: TResEvalFlags): string;
var var
s: string; s: string;

View File

@ -6673,7 +6673,12 @@ begin
// finish interface/implementation/nested procedure // finish interface/implementation/nested procedure
if (ProcName<>'') and ProcNeedsBody(Proc) then if (ProcName<>'') and ProcNeedsBody(Proc) then
begin begin
if not (ppsfIsSpecialized in ProcScope.Flags) then if ppsfIsSpecialized in ProcScope.Flags then
begin
if ProcScope.DeclarationProc<>nil then
ReplaceProcScopeImplArgsWithDeclArgs(ProcScope);
end
else
begin begin
// check if there is a forward declaration // check if there is a forward declaration
//writeln('TPasResolver.FinishProcedureType ',GetObjName(TopScope),' ',GetObjName(Scopes[ScopeCount-2])); //writeln('TPasResolver.FinishProcedureType ',GetObjName(TopScope),' ',GetObjName(Scopes[ScopeCount-2]));
@ -6943,6 +6948,8 @@ begin
DeclProcScope:=DeclProc.CustomData as TPasProcedureScope; DeclProcScope:=DeclProc.CustomData as TPasProcedureScope;
if DeclProcScope.ImplProc<>ImplProc then if DeclProcScope.ImplProc<>ImplProc then
RaiseNotYetImplemented(20190804182220,ImplProc); RaiseNotYetImplemented(20190804182220,ImplProc);
// replace arguments in scope with declaration arguments
ReplaceProcScopeImplArgsWithDeclArgs(ImplProcScope);
end end
else else
RaiseNotYetImplemented(20190804181222,ImplProc); RaiseNotYetImplemented(20190804181222,ImplProc);
@ -14938,9 +14945,10 @@ var
GenIntfProcScope, SpecIntfProcScope, GenImplProcScope, GenIntfProcScope, SpecIntfProcScope, GenImplProcScope,
SpecImplProcScope: TPasProcedureScope; SpecImplProcScope: TPasProcedureScope;
NewClass: TPTreeElement; NewClass: TPTreeElement;
OldStashCount, i: Integer; OldStashCount, i, p, LastDotP: Integer;
SpecClassOrRecScope: TPasClassOrRecordScope; 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);
@ -15006,7 +15014,17 @@ begin
RaiseNotYetImplemented(20190804130322,GenImplProc,GetObjName(ImplParent)); RaiseNotYetImplemented(20190804130322,GenImplProc,GetObjName(ImplParent));
// create impl proc // create impl proc
SpecImplProc:=TPasProcedure(NewClass.Create(GenImplProc.Name,GenImplProc.Parent)); 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; SpecIntfProcScope.ImplProc:=SpecImplProc;
if SpecializedItem.ImplProcs=nil then if SpecializedItem.ImplProcs=nil then
SpecializedItem.ImplProcs:=TFPList.Create; SpecializedItem.ImplProcs:=TFPList.Create;

View File

@ -15,11 +15,12 @@ type
TTestGenerics = class(TCustomTestModule) TTestGenerics = class(TCustomTestModule)
Published Published
// generic record // generic record
Procedure TestGeneric_RecordEmpty; Procedure TestGen_RecordEmpty;
// generic class // generic class
Procedure TestGeneric_ClassEmpty; Procedure TestGen_ClassEmpty;
Procedure TestGeneric_Class_EmptyMethod; Procedure TestGen_Class_EmptyMethod;
Procedure TestGen_Class_TList;
// generic external class // generic external class
procedure TestGen_ExtClass_Array; procedure TestGen_ExtClass_Array;
@ -29,7 +30,7 @@ implementation
{ TTestGenerics } { TTestGenerics }
procedure TTestGenerics.TestGeneric_RecordEmpty; procedure TTestGenerics.TestGen_RecordEmpty;
begin begin
StartProgram(false); StartProgram(false);
Add([ Add([
@ -40,7 +41,7 @@ begin
'begin', 'begin',
' if a=b then ;']); ' if a=b then ;']);
ConvertProgram; ConvertProgram;
CheckSource('TestGeneric_RecordEmpty', CheckSource('TestGen_RecordEmpty',
LinesToStr([ // statements LinesToStr([ // statements
'rtl.recNewT($mod, "TRecA$G1", function () {', 'rtl.recNewT($mod, "TRecA$G1", function () {',
' this.$eq = function (b) {', ' this.$eq = function (b) {',
@ -58,7 +59,7 @@ begin
])); ]));
end; end;
procedure TTestGenerics.TestGeneric_ClassEmpty; procedure TTestGenerics.TestGen_ClassEmpty;
begin begin
StartProgram(false); StartProgram(false);
Add([ Add([
@ -70,7 +71,7 @@ begin
'begin', 'begin',
' if a=b then ;']); ' if a=b then ;']);
ConvertProgram; ConvertProgram;
CheckSource('TestGeneric_ClassEmpty', CheckSource('TestGen_ClassEmpty',
LinesToStr([ // statements LinesToStr([ // statements
'rtl.createClass($mod, "TObject", null, function () {', 'rtl.createClass($mod, "TObject", null, function () {',
' this.$init = function () {', ' this.$init = function () {',
@ -88,7 +89,7 @@ begin
])); ]));
end; end;
procedure TTestGenerics.TestGeneric_Class_EmptyMethod; procedure TTestGenerics.TestGen_Class_EmptyMethod;
begin begin
StartProgram(false); StartProgram(false);
Add([ Add([
@ -104,7 +105,7 @@ begin
'begin', 'begin',
' if a.Fly(3)=4 then ;']); ' if a.Fly(3)=4 then ;']);
ConvertProgram; ConvertProgram;
CheckSource('TestGeneric_Class_EmptyMethod', CheckSource('TestGen_Class_EmptyMethod',
LinesToStr([ // statements LinesToStr([ // statements
'rtl.createClass($mod, "TObject", null, function () {', 'rtl.createClass($mod, "TObject", null, function () {',
' this.$init = function () {', ' this.$init = function () {',
@ -125,6 +126,84 @@ begin
])); ]));
end; end;
procedure TTestGenerics.TestGen_Class_TList;
begin
StartProgram(false);
Add([
'{$mode objfpc}',
'type',
' TObject = class end;',
' generic TList<T> = class',
' strict private',
' FItems: array of T;',
' function GetItems(Index: longint): T;',
' procedure SetItems(Index: longint; Value: T);',
' public',
' procedure Alter(w: T);',
' property Items[Index: longint]: T read GetItems write SetItems; default;',
' end;',
' TWordList = specialize TList<word>;',
'function TList.GetItems(Index: longint): T;',
'begin',
' Result:=FItems[Index];',
'end;',
'procedure TList.SetItems(Index: longint; Value: T);',
'begin',
' FItems[Index]:=Value;',
'end;',
'procedure TList.Alter(w: T);',
'begin',
' SetLength(FItems,length(FItems)+1);',
' Insert(w,FItems,2);',
' Delete(FItems,2,3);',
'end;',
'var l: TWordList;',
' w: word;',
'begin',
' l[1]:=w;',
' w:=l[2];',
'']);
ConvertProgram;
CheckSource('TestGen_Class_TList',
LinesToStr([ // statements
'rtl.createClass($mod, "TObject", null, function () {',
' this.$init = function () {',
' };',
' this.$final = function () {',
' };',
'});',
'rtl.createClass($mod, "TList$G1", $mod.TObject, function () {',
' this.$init = function () {',
' $mod.TObject.$init.call(this);',
' this.FItems = [];',
' };',
' this.$final = function () {',
' this.FItems = undefined;',
' $mod.TObject.$final.call(this);',
' };',
' this.GetItems = function (Index) {',
' var Result = 0;',
' Result = this.FItems[Index];',
' return Result;',
' };',
' this.SetItems = function (Index, Value) {',
' this.FItems[Index] = Value;',
' };',
' this.Alter = function (w) {',
' this.FItems = rtl.arraySetLength(this.FItems, 0, rtl.length(this.FItems) + 1);',
' this.FItems.splice(2, 0, w);',
' this.FItems.splice(2, 3);',
' };',
'});',
'this.l = null;',
'this.w = 0;',
'']),
LinesToStr([ // $mod.$main
'$mod.l.SetItems(1, $mod.w);',
'$mod.w = $mod.l.GetItems(2);',
'']));
end;
procedure TTestGenerics.TestGen_ExtClass_Array; procedure TTestGenerics.TestGen_ExtClass_Array;
begin begin
StartProgram(false); StartProgram(false);