summaryrefslogtreecommitdiff
path: root/avx512-0037785/packages/pastojs/tests/tcfiler.pas
diff options
context:
space:
mode:
Diffstat (limited to 'avx512-0037785/packages/pastojs/tests/tcfiler.pas')
-rw-r--r--avx512-0037785/packages/pastojs/tests/tcfiler.pas559
1 files changed, 507 insertions, 52 deletions
diff --git a/avx512-0037785/packages/pastojs/tests/tcfiler.pas b/avx512-0037785/packages/pastojs/tests/tcfiler.pas
index 7b347f96ca..e08cbfc904 100644
--- a/avx512-0037785/packages/pastojs/tests/tcfiler.pas
+++ b/avx512-0037785/packages/pastojs/tests/tcfiler.pas
@@ -35,6 +35,11 @@ type
);
TPCCheckFlags = set of TPCCheckFlag;
+ TPCCheckedElementPair = class
+ public
+ Orig, Rest: TPasElement;
+ end;
+
{ TCustomTestPrecompile }
TCustomTestPrecompile = Class(TCustomTestModule)
@@ -44,6 +49,7 @@ type
FPCUReader: TPCUReader;
FPCUWriter: TPCUWriter;
FRestAnalyzer: TPas2JSAnalyzer;
+ FCheckedElements: TPasAnalyzerKeySet; // keyset of TPCCheckedElementPair, key is Orig
procedure OnFilerGetSrc(Sender: TObject; aFilename: string; out p: PChar;
out Count: integer);
function OnConverterIsElementUsed(Sender: TObject; El: TPasElement): boolean;
@@ -70,6 +76,7 @@ type
procedure CheckRestoredElementBase(const Path: string; Orig, Rest: TPasElementBase; Flags: TPCCheckFlags); virtual;
procedure CheckRestoredResolveData(const Path: string; Orig, Rest: TResolveData; Flags: TPCCheckFlags); virtual;
procedure CheckRestoredPasScope(const Path: string; Orig, Rest: TPasScope; Flags: TPCCheckFlags); virtual;
+ procedure CheckRestoredLocalVar(const Path: string; Orig, Rest: TPas2JSStoredLocalVar); virtual;
procedure CheckRestoredModuleScope(const Path: string; Orig, Rest: TPas2JSModuleScope; Flags: TPCCheckFlags); virtual;
procedure CheckRestoredIdentifierScope(const Path: string; Orig, Rest: TPasIdentifierScope; Flags: TPCCheckFlags); virtual;
procedure CheckRestoredSectionScope(const Path: string; Orig, Rest: TPas2JSSectionScope; Flags: TPCCheckFlags); virtual;
@@ -78,6 +85,9 @@ type
procedure CheckRestoredRecordScope(const Path: string; Orig, Rest: TPas2jsRecordScope; Flags: TPCCheckFlags); virtual;
procedure CheckRestoredClassScope(const Path: string; Orig, Rest: TPas2JSClassScope; Flags: TPCCheckFlags); virtual;
procedure CheckRestoredProcScope(const Path: string; Orig, Rest: TPas2JSProcedureScope; Flags: TPCCheckFlags); virtual;
+ procedure CheckRestoredProcTypeScope(const Path: string; Orig, Rest: TPas2JSProcTypeScope; Flags: TPCCheckFlags); virtual;
+ procedure CheckRestoredArrayScope(const Path: string; Orig, Rest: TPas2JSArrayScope; Flags: TPCCheckFlags); virtual;
+ procedure CheckRestoredPrecompiledJS(const Path: string; OrigEl: TPasElement; Orig: TPas2JSPrecompiledJS; RestEl: TPasElement; Rest: TPas2JSPrecompiledJS; Flags: TPCCheckFlags); virtual;
procedure CheckRestoredScopeRefs(const Path: string; Orig, Rest: TPasScopeReferences; Flags: TPCCheckFlags); virtual;
procedure CheckRestoredPropertyScope(const Path: string; Orig, Rest: TPasPropertyScope; Flags: TPCCheckFlags); virtual;
procedure CheckRestoredGenericParamScope(const Path: string; Orig, Rest: TPasGenericParamsScope; Flags: TPCCheckFlags); virtual;
@@ -211,26 +221,19 @@ type
procedure TestPC_GenericFunction_AnonymousProc;
procedure TestPC_GenericClass;
procedure TestPC_GenericMethod;
- procedure TestPC_SpecializeClassSameUnit; // ToDo
- // ToDo: specialize local generic type in unit interface
- // ToDo: specialize local generic type in unit implementation
- // ToDo: specialize local generic type in proc decl
- // ToDo: specialize local generic type in proc body
- // ToDo: inline specialize local generic type in unit interface
- // ToDo: inline specialize local generic type in unit implementation
- // ToDo: inline specialize local generic type in proc decl
- // ToDo: inline specialize local generic type in proc body
- // ToDo: specialize extern generic type in unit interface
- // ToDo: specialize extern generic type in unit implementation
- // ToDo: specialize extern generic type in proc decl
- // ToDo: specialize extern generic type in proc body
- // ToDo: inline specialize extern generic type in unit interface
- // ToDo: inline specialize extern generic type in unit implementation
- // ToDo: inline specialize extern generic type in proc decl
- // ToDo: inline specialize extern generic type in proc body
+ // ToDo: GenericMethod Calls, ProcTypes
+ procedure TestPC_SpecializeClassSameUnit;
+ procedure TestPC_Specialize_LocalTypeInUnit;
+ procedure TestPC_Specialize_ClassForward;
+ procedure TestPC_InlineSpecialize_LocalTypeInUnit;
+ procedure TestPC_Specialize_Array;
+ procedure TestPC_Specialize_ProcType;
// ToDo: half specialize TBird<T> = class a: TAnt<word,T>; end;
// ToDo: no specialize: TBird<T> = class a: TBird<T>; end;
+ procedure TestPC_Constraints;
// ToDo: constraints
+ // ToDo: unit impl declarations used by generics
+ procedure TestPC_GenericClass_InlineSpecialize;
procedure TestPC_UseUnit;
procedure TestPC_UseUnit_Class;
@@ -238,6 +241,8 @@ type
end;
function CompareListOfProcScopeRef(Item1, Item2: Pointer): integer;
+function CompareCheckedElementPairs(Item1, Item2: Pointer): integer;
+function CompareElWithCheckedElementPair(Key, Item: Pointer): integer;
implementation
@@ -246,11 +251,27 @@ var
Ref1: TPasScopeReference absolute Item1;
Ref2: TPasScopeReference absolute Item2;
begin
- Result:=CompareText(Ref1.Element.Name,Ref2.Element.Name);
+ Result:=CompareText(GetObjPath(Ref1.Element),GetObjPath(Ref2.Element));
if Result<>0 then exit;
Result:=ComparePointer(Ref1.Element,Ref2.Element);
end;
+function CompareCheckedElementPairs(Item1, Item2: Pointer): integer;
+var
+ Pair1: TPCCheckedElementPair absolute Item1;
+ Pair2: TPCCheckedElementPair absolute Item2;
+begin
+ Result:=ComparePointer(Pair1.Orig,Pair2.Orig);
+end;
+
+function CompareElWithCheckedElementPair(Key, Item: Pointer): integer;
+var
+ El: TPasElement absolute Key;
+ Pair: TPCCheckedElementPair absolute Item;
+begin
+ Result:=ComparePointer(El,Pair.Orig);
+end;
+
{ TCustomTestPrecompile }
procedure TCustomTestPrecompile.OnFilerGetSrc(Sender: TObject;
@@ -348,6 +369,7 @@ begin
inherited SetUp;
FInitialFlags:=TPCUInitialFlags.Create;
FAnalyzer:=TPas2JSAnalyzer.Create;
+ FCheckedElements:=TPasAnalyzerKeySet.Create(@CompareCheckedElementPairs,@CompareElWithCheckedElementPair);
Analyzer.Resolver:=Engine;
Analyzer.Options:=Analyzer.Options+[paoImplReferences];
Converter.OnIsElementUsed:=@OnConverterIsElementUsed;
@@ -356,6 +378,11 @@ end;
procedure TCustomTestPrecompile.TearDown;
begin
+ if FCheckedElements<>nil then
+ begin
+ FCheckedElements.FreeItems;
+ FreeAndNil(FCheckedElements);
+ end;
FreeAndNil(FAnalyzer);
FreeAndNil(FPCUWriter);
FreeAndNil(FPCUReader);
@@ -390,6 +417,7 @@ var
begin
InitialParserOptions:=Parser.Options;
Analyzer.Options:=Analyzer.Options+[paoSkipGenericProc];
+ Converter.Options:=Converter.Options+[coShortRefGlobals];
ConvertUnit;
FPCUWriter:=TPCUWriter.Create;
@@ -534,13 +562,13 @@ begin
if Orig=nil then
begin
if Rest<>nil then
- Fail(Path+': Orig=nil Rest='+GetObjName(Rest));
+ Fail(Path+': Orig=nil Rest='+GetObjPath(Rest));
exit(false);
end
else if Rest=nil then
- Fail(Path+': Orig='+GetObjName(Orig)+' Rest=nil');
+ Fail(Path+': Orig='+GetObjPath(Orig)+' Rest=nil');
if Orig.ClassType<>Rest.ClassType then
- Fail(Path+': Orig='+GetObjName(Orig)+' Rest='+GetObjName(Rest));
+ Fail(Path+': Orig='+GetObjPath(Orig)+' Rest='+GetObjPath(Rest));
Result:=true;
end;
@@ -607,25 +635,107 @@ end;
procedure TCustomTestPrecompile.CheckRestoredDeclarations(const Path: string;
Orig, Rest: TPasDeclarations; Flags: TPCCheckFlags);
+
+ function IsSpecialization(El: TPasElement): boolean;
+ begin
+ Result:=(El.CustomData is TPasGenericScope)
+ and (TPasGenericScope(El.CustomData).SpecializedFromItem<>nil);
+ end;
+
+ function GetSubPath(const Path: string; OrigIndex: integer; OrigDecl: TPasElement): string;
+ begin
+ Result:=Path+'['+IntToStr(OrigIndex)+']';
+ if OrigDecl.Name<>'' then
+ Result:=Result+'"'+OrigDecl.Name+'"'
+ else
+ Result:=Result+'?noname?';
+ end;
+
+{ procedure WriteList;
+ var
+ i: Integer;
+ begin
+ writeln('CheckRestoredDeclarations.WriteList');
+ for i:=0 to Orig.Declarations.Count-1 do
+ if i<Rest.Declarations.Count then
+ writeln(' ',i,' Orig=',TPasElement(Orig.Declarations[i]).Name,' Rest=',TPasElement(Rest.Declarations[i]).Name);
+ end;}
+
var
- i: Integer;
+ OrigIndex, RestIndex: Integer;
OrigDecl, RestDecl: TPasElement;
SubPath: String;
begin
- for i:=0 to Orig.Declarations.Count-1 do
+ //WriteList;
+ // check non specializations
+ RestIndex:=0;
+ for OrigIndex:=0 to Orig.Declarations.Count-1 do
begin
- OrigDecl:=TPasElement(Orig.Declarations[i]);
- if i>=Rest.Declarations.Count then
- AssertEquals(Path+'.Declarations.Count',Orig.Declarations.Count,Rest.Declarations.Count);
- RestDecl:=TPasElement(Rest.Declarations[i]);
- SubPath:=Path+'['+IntToStr(i)+']';
- if OrigDecl.Name<>'' then
- SubPath:=SubPath+'"'+OrigDecl.Name+'"'
- else
- SubPath:=SubPath+'?noname?';
+ OrigDecl:=TPasElement(Orig.Declarations[OrigIndex]);
+ if IsSpecialization(OrigDecl) then
+ continue;
+ SubPath:=GetSubPath(Path,OrigIndex,OrigDecl);
+ // skip to next non specialization in restored declarations
+ while RestIndex<Rest.Declarations.Count do
+ begin
+ RestDecl:=TPasElement(Rest.Declarations[RestIndex]);
+ if not IsSpecialization(RestDecl) then
+ break;
+ inc(RestIndex)
+ end;
+ if RestIndex=Rest.Declarations.Count then
+ Fail(SubPath+' missing in restored Declarations');
+ // check
+ CheckRestoredElement(SubPath,OrigDecl,RestDecl,Flags);
+ inc(RestIndex);
+ end;
+
+ // check specializations
+ for OrigIndex:=0 to Orig.Declarations.Count-1 do
+ begin
+ OrigDecl:=TPasElement(Orig.Declarations[OrigIndex]);
+ if not IsSpecialization(OrigDecl) then
+ continue;
+ SubPath:=GetSubPath(Path,OrigIndex,OrigDecl);
+ // search specialization with same name
+ RestIndex:=0;
+ repeat
+ if RestIndex=Rest.Declarations.Count then
+ Fail(SubPath+' missing in restored Declarations');
+ RestDecl:=TPasElement(Rest.Declarations[RestIndex]);
+ if IsSpecialization(RestDecl) and (OrigDecl.Name=RestDecl.Name) then
+ break;
+ inc(RestIndex);
+ until false;
+
+ if (OrigIndex<Rest.Declarations.Count) and (OrigIndex<>RestIndex) then
+ begin
+ // move restored element to original place to generate the same JS
+ //writeln('TCustomTestPrecompile.CheckRestoredDeclarations Orig[',OrigIndex,']=',GetObjName(OrigDecl),' Rest[',RestIndex,']=',GetObjName(RestDecl));
+ if RestIndex>OrigIndex then
+ Rest.Declarations.Move(RestIndex,OrigIndex)
+ else
+ Rest.Declarations.Exchange(RestIndex,OrigIndex);
+ //writeln('TCustomTestPrecompile.CheckRestoredDeclarations RestIndex=',RestIndex,' ->',OrigIndex);
+ //WriteList;
+ end;
+
+ // check
CheckRestoredElement(SubPath,OrigDecl,RestDecl,Flags);
end;
AssertEquals(Path+'.Declarations.Count',Orig.Declarations.Count,Rest.Declarations.Count);
+
+ //WriteList;
+ for OrigIndex:=0 to Orig.Declarations.Count-1 do
+ begin
+ OrigDecl:=TPasElement(Orig.Declarations[OrigIndex]);
+ RestDecl:=TPasElement(Rest.Declarations[OrigIndex]);
+ if OrigDecl.Name<>RestDecl.Name then
+ begin
+ SubPath:=GetSubPath(Path,OrigIndex,OrigDecl);
+ AssertEquals(SubPath+'.Name',GetObjPath(OrigDecl),GetObjPath(RestDecl));
+ end;
+ end;
end;
procedure TCustomTestPrecompile.CheckRestoredSection(const Path: string; Orig,
@@ -689,8 +799,19 @@ begin
CheckRestoredResolveData(Path,Orig,Rest,Flags);
end;
+procedure TCustomTestPrecompile.CheckRestoredLocalVar(const Path: string; Orig,
+ Rest: TPas2JSStoredLocalVar);
+begin
+ AssertEquals(Path+'.Name',Orig.Name,Rest.Name);
+ CheckRestoredReference(Path+'.Id',Orig.Element,Rest.Element);
+end;
+
procedure TCustomTestPrecompile.CheckRestoredModuleScope(const Path: string;
Orig, Rest: TPas2JSModuleScope; Flags: TPCCheckFlags);
+var
+ OrigLocalVars, RestLocalVars: TPas2JSStoredLocalVarArray;
+ i, j: Integer;
+ OrigLocalVar, RestLocalVar: TPas2JSStoredLocalVar;
begin
AssertEquals(Path+'.FirstName',Orig.FirstName,Rest.FirstName);
if Orig.Flags<>Rest.Flags then
@@ -704,6 +825,32 @@ begin
CheckRestoredReference(Path+'.RangeErrorConstructor',Orig.RangeErrorConstructor,Rest.RangeErrorConstructor);
CheckRestoredReference(Path+'.SystemTVarRec',Orig.SystemTVarRec,Rest.SystemTVarRec);
CheckRestoredReference(Path+'.SystemVarRecs',Orig.SystemVarRecs,Rest.SystemVarRecs);
+
+ // StoreJSLocalVars
+ OrigLocalVars:=Orig.StoreJSLocalVars;
+ RestLocalVars:=Rest.StoreJSLocalVars;
+ //for i:=0 to length(RestLocalVars)-1 do
+ // writeln('TCustomTestPrecompile.CheckRestoredModuleScope Rest ',i,'/',length(RestLocalVars),' ',RestLocalVars[i].Name);
+ for i:=0 to length(OrigLocalVars)-1 do
+ begin
+ OrigLocalVar:=OrigLocalVars[i];
+ //writeln('TCustomTestPrecompile.CheckRestoredModuleScope Orig ',i,'/',length(OrigLocalVars),' ',OrigLocalVar.Name);
+ j:=length(OrigLocalVars)-1;
+ while (j>=0) do
+ begin
+ RestLocalVar:=RestLocalVars[j];
+ if OrigLocalVar.Name=RestLocalVar.Name then
+ begin
+ CheckRestoredLocalVar(Path+'.LocalVars['+IntToStr(i)+']',OrigLocalVar,RestLocalVar);
+ break;
+ end;
+ dec(j);
+ end;
+ if j<0 then
+ Fail(Path+'.LocalVars['+IntToStr(i)+'] Name="'+OrigLocalVar.Name+'" missing in Rest');
+ end;
+ AssertEquals('LocalVars.Count',length(OrigLocalVars),length(RestLocalVars));
+
CheckRestoredPasScope(Path,Orig,Rest,Flags);
end;
@@ -793,8 +940,7 @@ procedure TCustomTestPrecompile.CheckRestoredInitialFinalizationScope(
Flags: TPCCheckFlags);
begin
CheckRestoredScopeRefs(Path+'.References',Orig.References,Rest.References,Flags);
- if Orig.JS<>Rest.JS then
- CheckRestoredJS(Path+'.JS',Orig.JS,Rest.JS);
+ CheckRestoredPrecompiledJS(Path+'.ImplJS',Orig.Element,Orig.ImplJS,Rest.Element,Rest.ImplJS,Flags);
end;
procedure TCustomTestPrecompile.CheckRestoredEnumTypeScope(const Path: string;
@@ -809,6 +955,8 @@ procedure TCustomTestPrecompile.CheckRestoredRecordScope(const Path: string;
begin
CheckRestoredReference(Path+'.DefaultProperty',Orig.DefaultProperty,Rest.DefaultProperty);
CheckRestoredIdentifierScope(Path,Orig,Rest,Flags);
+ // ok -> use same JSName
+ Rest.JSName:=Orig.JSName;
end;
procedure TCustomTestPrecompile.CheckRestoredClassScope(const Path: string;
@@ -882,6 +1030,9 @@ begin
end;
CheckRestoredIdentifierScope(Path,Orig,Rest,Flags);
+
+ // ok -> use same JSName
+ Rest.JSName:=Orig.JSName;
end;
procedure TCustomTestPrecompile.CheckRestoredProcScope(const Path: string;
@@ -891,10 +1042,7 @@ var
begin
CheckRestoredReference(Path+'.DeclarationProc',Orig.DeclarationProc,Rest.DeclarationProc);
CheckRestoredReference(Path+'.ImplProc',Orig.ImplProc,Rest.ImplProc);
- if Orig.BodyJS<>Rest.BodyJS then
- CheckRestoredJS(Path+'.BodyJS',Orig.BodyJS,Rest.BodyJS);
-
- CheckRestoredStringList(Path+'.GlobalJS',Orig.GlobalJS,Rest.GlobalJS);
+ CheckRestoredPrecompiledJS(Path+'.ImplJS',Orig.Element,Orig.ImplJS,Rest.Element,Rest.ImplJS,Flags);
if Rest.DeclarationProc=nil then
begin
@@ -921,6 +1069,47 @@ begin
begin
// ImplProc
end;
+
+ // ok -> use same JSName
+ Rest.JSName:=Orig.JSName;
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredProcTypeScope(const Path: string;
+ Orig, Rest: TPas2JSProcTypeScope; Flags: TPCCheckFlags);
+begin
+ if Path='' then ;
+ if Flags=[] then ;
+
+ // ok -> use same JSName
+ Rest.JSName:=Orig.JSName;
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredArrayScope(const Path: string;
+ Orig, Rest: TPas2JSArrayScope; Flags: TPCCheckFlags);
+begin
+ if Path='' then ;
+ if Flags=[] then ;
+
+ // ok -> use same JSName
+ Rest.JSName:=Orig.JSName;
+end;
+
+procedure TCustomTestPrecompile.CheckRestoredPrecompiledJS(const Path: string;
+ OrigEl: TPasElement; Orig: TPas2JSPrecompiledJS; RestEl: TPasElement;
+ Rest: TPas2JSPrecompiledJS; Flags: TPCCheckFlags);
+begin
+ CheckRestoredObject(Path,Orig,Rest);
+ if Orig=nil then exit;
+ if Flags=[] then ;
+
+ AssertEquals(Path+'.EmptyJS',Orig.EmptyJS,Rest.EmptyJS);
+ if Orig.BodyJS<>Rest.BodyJS then
+ CheckRestoredJS(Path+'.BodyJS',Orig.BodyJS,Rest.BodyJS);
+ if Orig.BodyJS<>'' then
+ begin
+ CheckRestoredStringList(Path+'.GlobalJS',Orig.GlobalJS,Rest.GlobalJS);
+ CheckRestoredElRefList(Path+'.ShortRefs',OrigEl,Orig.ShortRefs,RestEl,Rest.ShortRefs,false,Flags);
+ end;
end;
procedure TCustomTestPrecompile.CheckRestoredScopeRefs(const Path: string;
@@ -929,12 +1118,14 @@ var
OrigList, RestList: TFPList;
i: Integer;
OrigRef, RestRef: TPasScopeReference;
+ ok: Boolean;
begin
if Flags=[] then ;
CheckRestoredObject(Path,Orig,Rest);
if Orig=nil then exit;
OrigList:=nil;
RestList:=nil;
+ ok:=false;
try
OrigList:=Orig.GetList;
RestList:=Rest.GetList;
@@ -957,7 +1148,21 @@ begin
RestRef:=TPasScopeReference(RestList[i]);
Fail(Path+'['+IntToStr(i)+'] Too many in Rest: "'+RestRef.Element.Name+'"');
end;
+ ok:=true;
finally
+ if not ok then
+ begin
+ for i:=0 to OrigList.Count-1 do
+ begin
+ OrigRef:=TPasScopeReference(OrigList[i]);
+ writeln('TCustomTestPrecompile.CheckRestoredScopeRefs Orig[',i,']=',GetObjPath(OrigRef.Element));
+ end;
+ for i:=0 to RestList.Count-1 do
+ begin
+ RestRef:=TPasScopeReference(RestList[i]);
+ writeln('TCustomTestPrecompile.CheckRestoredScopeRefs Rest[',i,']=',GetObjPath(RestRef.Element));
+ end;
+ end;
OrigList.Free;
RestList.Free;
end;
@@ -1113,6 +1318,10 @@ begin
CheckRestoredClassScope(Path+'[TPas2JSClassScope]',TPas2JSClassScope(Orig),TPas2JSClassScope(Rest),Flags)
else if C=TPas2JSProcedureScope then
CheckRestoredProcScope(Path+'[TPas2JSProcedureScope]',TPas2JSProcedureScope(Orig),TPas2JSProcedureScope(Rest),Flags)
+ else if C=TPas2JSArrayScope then
+ CheckRestoredArrayScope(Path+'[TPas2JSArrayScope]',TPas2JSArrayScope(Orig),TPas2JSArrayScope(Rest),Flags)
+ else if C=TPas2JSProcTypeScope then
+ CheckRestoredProcTypeScope(Path+'[TPas2JSProcTypeScope]',TPas2JSProcTypeScope(Orig),TPas2JSProcTypeScope(Rest),Flags)
else if C=TPasPropertyScope then
CheckRestoredPropertyScope(Path+'[TPasPropertyScope]',TPasPropertyScope(Orig),TPasPropertyScope(Rest),Flags)
else if C=TPasGenericParamsScope then
@@ -1167,7 +1376,14 @@ begin
if RestUsed=nil then
Fail(Path+': used in OrigAnalyzer, but not used in RestAnalyzer');
if OrigUsed.Access<>RestUsed.Access then
- AssertEquals(Path+'->Analyzer.Access',dbgs(OrigUsed.Access),dbgs(RestUsed.Access));
+ begin
+ if (OrigUsed.Access in [paiaReadWrite,paiaWriteRead])
+ and (RestUsed.Access in [paiaReadWrite,paiaWriteRead])
+ and not (Orig.Parent is TProcedureBody) then
+ // readwrite or writeread is irrelevant for globals
+ else
+ AssertEquals(Path+'->Analyzer.Access',dbgs(OrigUsed.Access),dbgs(RestUsed.Access));
+ end;
end
else if RestAnalyzer.IsUsed(Rest) then
begin
@@ -1180,11 +1396,27 @@ procedure TCustomTestPrecompile.CheckRestoredElement(const Path: string; Orig,
var
C: TClass;
AModule: TPasModule;
+ Pair: TPCCheckedElementPair;
begin
//writeln('TCustomTestPrecompile.CheckRestoredElement START Orig=',GetObjName(Orig),' Rest=',GetObjName(Rest));
if not CheckRestoredObject(Path,Orig,Rest) then exit;
//writeln('TCustomTestPrecompile.CheckRestoredElement CheckRestoredObject Orig=',GetObjName(Orig),' Rest=',GetObjName(Rest));
+ Pair:=TPCCheckedElementPair(FCheckedElements.FindKey(Orig));
+ if Pair<>nil then
+ begin
+ if Pair.Rest<>Rest then
+ Fail(Path+': Orig='+GetObjPath(Orig)+' Rest='+GetObjPath(Rest));
+ exit;
+ end
+ else
+ begin
+ Pair:=TPCCheckedElementPair.Create;
+ Pair.Orig:=Orig;
+ Pair.Rest:=Rest;
+ FCheckedElements.Add(Pair,false);
+ end;
+
AModule:=Orig.GetModule;
if AModule<>Module then
begin
@@ -1703,6 +1935,7 @@ end;
procedure TCustomTestPrecompile.CheckRestoredExportSymbol(const Path: string;
Orig, Rest: TPasExportSymbol; Flags: TPCCheckFlags);
begin
+ CheckRestoredElement(Path+'.NameExpr',Orig.NameExpr,Rest.NameExpr,Flags);
CheckRestoredElement(Path+'.ExportName',Orig.ExportName,Rest.ExportName,Flags);
CheckRestoredElement(Path+'.ExportIndex',Orig.ExportIndex,Rest.ExportIndex,Flags);
end;
@@ -1779,9 +2012,9 @@ begin
RestScope:=Rest.CustomData as TPas2JSProcedureScope;
if OrigScope=nil then
exit; // msIgnoreInterfaces
- CheckRestoredReference(Path+'.CustomData[TPas2JSProcedureScope].DeclarationProc',
+ CheckRestoredReference(Path+'.CustomData[TPas2JSProcedureScope].DeclarationProc [20201018123102]',
OrigScope.DeclarationProc,RestScope.DeclarationProc);
- AssertEquals(Path+'.CustomData[TPas2JSProcedureScope].ResultVarName',OrigScope.ResultVarName,RestScope.ResultVarName);
+ AssertEquals(Path+'.CustomData[TPas2JSProcedureScope].ResultVarName [20201018123057]',OrigScope.ResultVarName,RestScope.ResultVarName);
DeclProc:=RestScope.DeclarationProc;
if DeclProc=nil then
begin
@@ -1808,15 +2041,13 @@ begin
// Body
if Orig.Body<>nil then
begin
- if Engine.ProcCanBePrecompiled(DeclProc) then
- begin
- AssertEquals(Path+'.EmptyJS',OrigScope.EmptyJS,RestScope.EmptyJS);
- CheckRestoredJS(Path+'.BodyJS',OrigScope.BodyJS,RestScope.BodyJS);
- CheckRestoredStringList(Path+'.GlobalJS',OrigScope.GlobalJS,RestScope.GlobalJS);
- end
- else
+ if not Engine.ProcCanBePrecompiled(DeclProc) then
begin
// generic body
+ if OrigScope.ImplJS<>nil then
+ Fail(Path+'.CustomData[TPas2JSProcedureScope].ImplJS [20201018123049] OrigScope.ImplJS<>nil');
+ if RestScope.ImplJS<>nil then
+ Fail(Path+'.CustomData[TPas2JSProcedureScope].ImplJS [20201018123139] RestScope.ImplJS<>nil');
CheckRestoredProcedureBody(Path+'.Body',Orig.Body,Rest.Body,Flags+[PCCGeneric]);
end;
end
@@ -2730,7 +2961,7 @@ begin
'implementation',
'generic function Run<T>(a: T): T;',
'var b: T;',
- ' var i: word;',
+ ' i: word;',
'begin',
' b:=a;',
' Result:=b;',
@@ -3077,8 +3308,6 @@ end;
procedure TTestPrecompile.TestPC_SpecializeClassSameUnit;
begin
- exit;
-
StartUnit(false);
Add([
'{$mode delphi}',
@@ -3095,7 +3324,233 @@ begin
'implementation',
'begin',
' b.a:=1.3;',
- 'end.',
+ '']);
+ WriteReadUnit;
+end;
+
+procedure TTestPrecompile.TestPC_Specialize_LocalTypeInUnit;
+begin
+ StartUnit(false);
+ Add([
+ '{$mode delphi}',
+ 'interface',
+ 'type',
+ ' TObject = class',
+ ' end;',
+ ' TBird<T> = class',
+ ' a: T;',
+ ' end;',
+ ' TDoubleBird = TBIrd<double>;',
+ 'var',
+ ' db: TDoubleBird;',
+ 'procedure Fly;',
+ 'implementation',
+ 'type',
+ ' TWordBird = TBird<word>;',
+ 'procedure Run;',
+ 'type TShortIntBird = TBird<shortint>;',
+ 'var',
+ ' shb: TShortIntBird;',
+ ' wb: TWordBird;',
+ 'begin',
+ ' shb.a:=3;',
+ ' wb.a:=4;',
+ 'end;',
+ 'procedure Fly;',
+ 'type TByteBird = TBird<byte>;',
+ 'var bb: TByteBird;',
+ 'begin',
+ ' bb.a:=5;',
+ ' Run;',
+ 'end;',
+ 'begin',
+ '']);
+ WriteReadUnit;
+end;
+
+procedure TTestPrecompile.TestPC_Specialize_ClassForward;
+begin
+ StartUnit(false);
+ Add([
+ '{$mode delphi}',
+ 'interface',
+ 'type',
+ ' TObject = class',
+ ' end;',
+ ' TBird<T> = class;',
+ ' TAnt = class',
+ ' b: TBird<word>;',
+ ' end;',
+ ' TBird<T> = class',
+ ' a: TAnt;',
+ ' end;',
+ 'procedure Fly;',
+ 'implementation',
+ 'procedure Fly;',
+ 'var b: TBird<Double>;',
+ 'begin',
+ ' b.a:=nil;',
+ 'end;',
+ 'begin',
+ '']);
+ WriteReadUnit;
+end;
+
+procedure TTestPrecompile.TestPC_InlineSpecialize_LocalTypeInUnit;
+begin
+ StartUnit(false);
+ Add([
+ '{$mode delphi}',
+ 'interface',
+ 'type',
+ ' TObject = class',
+ ' constructor Create;',
+ ' end;',
+ ' TBird<T> = class',
+ ' a: T;',
+ ' end;',
+ 'var',
+ ' db: TBIrd<double>;',
+ 'procedure Fly;',
+ 'implementation',
+ 'constructor TObject.Create;',
+ 'begin',
+ 'end;',
+ 'var wb: TBird<word>;',
+ 'procedure Run;',
+ 'var',
+ ' shb: TBird<shortint>;',
+ ' bb: TBird<boolean>;',
+ 'begin',
+ ' shb.a:=3;',
+ ' wb.a:=4;',
+ ' bb.a:=true;',
+ ' TBird<string>.Create;',
+ 'end;',
+ 'procedure Fly;',
+ 'var lb: TBird<longint>;',
+ 'begin',
+ ' lb.a:=5;',
+ ' Run;',
+ 'end;',
+ 'begin',
+ '']);
+ WriteReadUnit;
+end;
+
+procedure TTestPrecompile.TestPC_Specialize_Array;
+begin
+ StartUnit(false);
+ Add([
+ '{$mode delphi}',
+ 'interface',
+ 'type',
+ ' TArray<T> = array of T;',
+ 'var',
+ ' da: TArray<double>;',
+ 'procedure Fly;',
+ 'implementation',
+ 'var wa: TArray<word>;',
+ 'procedure Run;',
+ 'var',
+ ' sha: TArray<shortint>;',
+ ' ba: TArray<boolean>;',
+ 'begin',
+ ' sha[1]:=3;',
+ ' wa[2]:=4;',
+ ' ba[3]:=true;',
+ 'end;',
+ 'procedure Fly;',
+ 'var la: TArray<longint>;',
+ 'begin',
+ ' la[4]:=5;',
+ ' Run;',
+ 'end;',
+ 'begin',
+ '']);
+ WriteReadUnit;
+end;
+
+procedure TTestPrecompile.TestPC_Specialize_ProcType;
+begin
+ StartUnit(false);
+ Add([
+ '{$mode delphi}',
+ 'interface',
+ 'type',
+ ' TFunc<R,P> = function(a: P): R;',
+ 'var',
+ ' a: TFunc<word,double>;',
+ 'procedure Fly;',
+ 'implementation',
+ 'var b: TFunc<byte,word>;',
+ 'procedure Run;',
+ 'var',
+ ' c: TFunc<shortint,string>;',
+ 'begin',
+ ' a(3.3);',
+ ' b(4);',
+ ' c(''abc'');',
+ 'end;',
+ 'procedure Fly;',
+ 'var d: TFunc<longint,boolean>;',
+ 'begin',
+ ' d(true);',
+ ' Run;',
+ 'end;',
+ 'begin',
+ '']);
+ WriteReadUnit;
+end;
+
+procedure TTestPrecompile.TestPC_Constraints;
+begin
+ StartUnit(true,[supTObject]);
+ Add([
+ '{$mode delphi}',
+ 'interface',
+ 'type',
+ ' TBird<T: class> = class',
+ ' end;',
+ ' TEagle<T: record> = class',
+ ' end;',
+ ' TAnt<T: constructor> = class',
+ ' end;',
+ ' TFish = class end;',
+ ' TBirdFish = TBird<TFish>;',
+ ' TAntFish = TAnt<TFish>;',
+ ' TWater<T: TFish> = class',
+ ' end;',
+ ' TRec = record end;',
+ 'var',
+ ' bf: TBirdFish;',
+ ' af: TAntFish;',
+ ' er: TEagle<TRec>;',
+ ' wf: TWater<TFish>;',
+ 'implementation',
+ '']);
+ WriteReadUnit;
+end;
+
+procedure TTestPrecompile.TestPC_GenericClass_InlineSpecialize;
+begin
+ StartUnit(true,[supTObject]);
+ Add([
+ '{$mode delphi}',
+ 'interface',
+ 'type',
+ ' TBird<T: class> = class',
+ ' end;',
+ ' TEagle<T: class> = class(TBird<T>)',
+ ' type',
+ ' TMyEagle = TEagle<T>;',
+ ' function Fly(v: T): T;',
+ ' end;',
+ 'implementation',
+ 'function TEagle<T>.Fly(v: T): T;',
+ 'begin',
+ ' TEagle<T>.Create;',
+ 'end;',
'']);
WriteReadUnit;
end;