mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 09:46:12 +02:00
fcl-passrc: replace method impl arguments with intf arguments
git-svn-id: trunk@42690 -
This commit is contained in:
parent
55b1f676dc
commit
35d7fade97
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user