mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 09:49:35 +02:00
pastojs: create local record types in global scope
git-svn-id: trunk@40691 -
This commit is contained in:
parent
f465826ba9
commit
3c9a5e5602
@ -262,8 +262,7 @@ type
|
|||||||
procedure UseProcedure(Proc: TPasProcedure); virtual;
|
procedure UseProcedure(Proc: TPasProcedure); virtual;
|
||||||
procedure UseProcedureType(ProcType: TPasProcedureType; Mark: boolean); virtual;
|
procedure UseProcedureType(ProcType: TPasProcedureType; Mark: boolean); virtual;
|
||||||
procedure UseType(El: TPasType; Mode: TPAUseMode); virtual;
|
procedure UseType(El: TPasType; Mode: TPAUseMode); virtual;
|
||||||
procedure UseRecordType(El: TPasRecordType; Mode: TPAUseMode); virtual;
|
procedure UseClassOrRecType(El: TPasMembersType; Mode: TPAUseMode); virtual;
|
||||||
procedure UseClassType(El: TPasClassType; Mode: TPAUseMode); virtual;
|
|
||||||
procedure UseVariable(El: TPasVariable; Access: TResolvedRefAccess;
|
procedure UseVariable(El: TPasVariable; Access: TResolvedRefAccess;
|
||||||
UseFull: boolean); virtual;
|
UseFull: boolean); virtual;
|
||||||
procedure UseResourcestring(El: TPasResString); virtual;
|
procedure UseResourcestring(El: TPasResString); virtual;
|
||||||
@ -1178,7 +1177,7 @@ begin
|
|||||||
UseInitFinal(aModule.FinalizationSection);
|
UseInitFinal(aModule.FinalizationSection);
|
||||||
ModScope:=aModule.CustomData as TPasModuleScope;
|
ModScope:=aModule.CustomData as TPasModuleScope;
|
||||||
if ModScope.RangeErrorClass<>nil then
|
if ModScope.RangeErrorClass<>nil then
|
||||||
UseClassType(ModScope.RangeErrorClass,paumElement);
|
UseClassOrRecType(ModScope.RangeErrorClass,paumElement);
|
||||||
if ModScope.RangeErrorConstructor<>nil then
|
if ModScope.RangeErrorConstructor<>nil then
|
||||||
UseProcedure(ModScope.RangeErrorConstructor);
|
UseProcedure(ModScope.RangeErrorConstructor);
|
||||||
|
|
||||||
@ -1815,10 +1814,8 @@ begin
|
|||||||
{$IFDEF VerbosePasAnalyzer}
|
{$IFDEF VerbosePasAnalyzer}
|
||||||
writeln('TPasAnalyzer.UseType searching exports in ',GetElModName(El),' ...');
|
writeln('TPasAnalyzer.UseType searching exports in ',GetElModName(El),' ...');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
if C=TPasRecordType then
|
if (C=TPasRecordType) or (C=TPasClassType) then
|
||||||
UseRecordType(TPasRecordType(El),Mode)
|
UseClassOrRecType(TPasMembersType(El),Mode);
|
||||||
else if C=TPasClassType then
|
|
||||||
UseClassType(TPasClassType(El),Mode);
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@ -1848,10 +1845,8 @@ begin
|
|||||||
UseExpr(TPasArrayType(El).Ranges[i]);
|
UseExpr(TPasArrayType(El).Ranges[i]);
|
||||||
UseElType(El,TPasArrayType(El).ElType,Mode);
|
UseElType(El,TPasArrayType(El).ElType,Mode);
|
||||||
end
|
end
|
||||||
else if C=TPasRecordType then
|
else if (C=TPasRecordType) or (C=TPasClassType) then
|
||||||
UseRecordType(TPasRecordType(El),Mode)
|
UseClassOrRecType(TPasMembersType(El),Mode)
|
||||||
else if C=TPasClassType then
|
|
||||||
UseClassType(TPasClassType(El),Mode)
|
|
||||||
else if C=TPasEnumType then
|
else if C=TPasEnumType then
|
||||||
begin
|
begin
|
||||||
if not MarkElementAsUsed(El) then exit;
|
if not MarkElementAsUsed(El) then exit;
|
||||||
@ -1883,22 +1878,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasAnalyzer.UseRecordType(El: TPasRecordType; Mode: TPAUseMode);
|
procedure TPasAnalyzer.UseClassOrRecType(El: TPasMembersType; Mode: TPAUseMode);
|
||||||
// called by UseType
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
begin
|
|
||||||
if Mode=paumAllExports then exit;
|
|
||||||
MarkElementAsUsed(El);
|
|
||||||
if not ElementVisited(El,Mode) then
|
|
||||||
begin
|
|
||||||
if (Mode=paumAllPasUsable) or Resolver.IsTGUID(El) then
|
|
||||||
for i:=0 to El.Members.Count-1 do
|
|
||||||
UseVariable(TObject(El.Members[i]) as TPasVariable,rraNone,true);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TPasAnalyzer.UseClassType(El: TPasClassType; Mode: TPAUseMode);
|
|
||||||
// called by UseType
|
// called by UseType
|
||||||
|
|
||||||
procedure UseDelegations;
|
procedure UseDelegations;
|
||||||
@ -1936,7 +1916,7 @@ procedure TPasAnalyzer.UseClassType(El: TPasClassType; Mode: TPAUseMode);
|
|||||||
Map:=TPasClassIntfMap(o);
|
Map:=TPasClassIntfMap(o);
|
||||||
repeat
|
repeat
|
||||||
if Map.Intf<>nil then
|
if Map.Intf<>nil then
|
||||||
UseClassType(TPasClassType(Map.Intf),paumElement);
|
UseClassOrRecType(TPasClassType(Map.Intf),paumElement);
|
||||||
if Map.Procs<>nil then
|
if Map.Procs<>nil then
|
||||||
for j:=0 to Map.Procs.Count-1 do
|
for j:=0 to Map.Procs.Count-1 do
|
||||||
UseProcedure(TPasProcedure(Map.Procs[j]));
|
UseProcedure(TPasProcedure(Map.Procs[j]));
|
||||||
@ -1960,6 +1940,7 @@ var
|
|||||||
o: TObject;
|
o: TObject;
|
||||||
Map: TPasClassIntfMap;
|
Map: TPasClassIntfMap;
|
||||||
ImplProc, IntfProc: TPasProcedure;
|
ImplProc, IntfProc: TPasProcedure;
|
||||||
|
aClass: TPasClassType;
|
||||||
begin
|
begin
|
||||||
FirstTime:=true;
|
FirstTime:=true;
|
||||||
case Mode of
|
case Mode of
|
||||||
@ -1982,35 +1963,54 @@ begin
|
|||||||
{$IFDEF VerbosePasAnalyzer}
|
{$IFDEF VerbosePasAnalyzer}
|
||||||
writeln('TPasAnalyzer.UseClassType ',GetElModName(El),' ',Mode,' First=',FirstTime);
|
writeln('TPasAnalyzer.UseClassType ',GetElModName(El),' ',Mode,' First=',FirstTime);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
if El.IsForward then
|
aClass:=nil;
|
||||||
begin
|
ClassScope:=nil;
|
||||||
Ref:=El.CustomData as TResolvedReference;
|
|
||||||
UseClassType(Ref.Declaration as TPasClassType,Mode);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
ClassScope:=El.CustomData as TPasClassScope;
|
|
||||||
if ClassScope=nil then
|
|
||||||
exit; // ClassScope can be nil if msIgnoreInterfaces
|
|
||||||
|
|
||||||
IsCOMInterfaceRoot:=false;
|
IsCOMInterfaceRoot:=false;
|
||||||
if FirstTime then
|
|
||||||
|
if El is TPasClassType then
|
||||||
begin
|
begin
|
||||||
UseElType(El,ClassScope.DirectAncestor,paumElement);
|
aClass:=TPasClassType(El);
|
||||||
UseElType(El,El.HelperForType,paumElement);
|
if aClass.IsForward then
|
||||||
UseExpr(El.GUIDExpr);
|
|
||||||
// El.Interfaces: using a class does not use automatically the interfaces
|
|
||||||
if El.ObjKind=okInterface then
|
|
||||||
begin
|
begin
|
||||||
UseDelegations;
|
Ref:=aClass.CustomData as TResolvedReference;
|
||||||
if (El.InterfaceType=citCom) and (El.AncestorType=nil) then
|
UseClassOrRecType(Ref.Declaration as TPasClassType,Mode);
|
||||||
IsCOMInterfaceRoot:=true;
|
exit;
|
||||||
end;
|
end;
|
||||||
if (El.ObjKind=okClass) and (ScopeModule<>nil)
|
|
||||||
and (ClassScope.Interfaces<>nil) then
|
ClassScope:=aClass.CustomData as TPasClassScope;
|
||||||
// when checking a single unit, mark all method+properties implementing the interfaces
|
if ClassScope=nil then
|
||||||
MarkAllInterfaceImplementations(ClassScope);
|
exit; // ClassScope can be nil if msIgnoreInterfaces
|
||||||
end;
|
|
||||||
|
if FirstTime then
|
||||||
|
begin
|
||||||
|
UseElType(El,ClassScope.DirectAncestor,paumElement);
|
||||||
|
UseElType(El,aClass.HelperForType,paumElement);
|
||||||
|
UseExpr(aClass.GUIDExpr);
|
||||||
|
// aClass.Interfaces: using a class does not use automatically the interfaces
|
||||||
|
if aClass.ObjKind=okInterface then
|
||||||
|
begin
|
||||||
|
UseDelegations;
|
||||||
|
if (aClass.InterfaceType=citCom) and (aClass.AncestorType=nil) then
|
||||||
|
IsCOMInterfaceRoot:=true;
|
||||||
|
end;
|
||||||
|
if (aClass.ObjKind=okClass) and (ScopeModule<>nil)
|
||||||
|
and (ClassScope.Interfaces<>nil) then
|
||||||
|
// when checking a single unit, mark all method+properties implementing the interfaces
|
||||||
|
MarkAllInterfaceImplementations(ClassScope);
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else if El is TPasRecordType then
|
||||||
|
begin
|
||||||
|
if (Mode<>paumAllPasUsable) and Resolver.IsTGUID(TPasRecordType(El)) then
|
||||||
|
for i:=0 to El.Members.Count-1 do
|
||||||
|
begin
|
||||||
|
Member:=TPasElement(El.Members[i]);
|
||||||
|
if Member is TPasVariable then
|
||||||
|
UseVariable(TPasVariable(Member),rraNone,true);
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
RaiseNotSupported(20181229103139,El);
|
||||||
|
|
||||||
// members
|
// members
|
||||||
AllPublished:=(Mode<>paumAllExports);
|
AllPublished:=(Mode<>paumAllExports);
|
||||||
@ -2074,11 +2074,11 @@ begin
|
|||||||
UseTypeInfo(Member);
|
UseTypeInfo(Member);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
; // else: class is in unit interface, mark all non private members
|
; // else: class/record is in unit interface, mark all non private members
|
||||||
UseElement(Member,rraNone,true);
|
UseElement(Member,rraNone,true);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if FirstTime then
|
if FirstTime and (ClassScope<>nil) then
|
||||||
begin
|
begin
|
||||||
// method resolution
|
// method resolution
|
||||||
List:=ClassScope.Interfaces;
|
List:=ClassScope.Interfaces;
|
||||||
@ -2090,7 +2090,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
// interface delegation
|
// interface delegation
|
||||||
// Note: This class is used. When the intftype is used, this delegation is used.
|
// Note: This class is used. When the intftype is used, this delegation is used.
|
||||||
AddOverride(TPasType(El.Interfaces[i]),TPasProperty(o));
|
AddOverride(TPasType(aClass.Interfaces[i]),TPasProperty(o));
|
||||||
end
|
end
|
||||||
else if o is TPasClassIntfMap then
|
else if o is TPasClassIntfMap then
|
||||||
begin
|
begin
|
||||||
@ -2111,7 +2111,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
RaiseNotSupported(20180328224632,El,GetObjName(o));
|
RaiseNotSupported(20180328224632,aClass,GetObjName(o));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -1206,6 +1206,7 @@ type
|
|||||||
procedure InternalAdd(Item: TPasIdentifier);
|
procedure InternalAdd(Item: TPasIdentifier);
|
||||||
procedure OnClearHashItem(Item, Dummy: pointer);
|
procedure OnClearHashItem(Item, Dummy: pointer);
|
||||||
protected
|
protected
|
||||||
|
// overloads: fix name clashes in JS
|
||||||
FOverloadScopes: TFPList; // list of TPasIdentifierScope
|
FOverloadScopes: TFPList; // list of TPasIdentifierScope
|
||||||
function HasOverloadIndex(El: TPasElement; WithElevatedLocal: boolean = false): boolean; virtual;
|
function HasOverloadIndex(El: TPasElement; WithElevatedLocal: boolean = false): boolean; virtual;
|
||||||
function GetOverloadIndex(Identifier: TPasIdentifier;
|
function GetOverloadIndex(Identifier: TPasIdentifier;
|
||||||
@ -1219,7 +1220,8 @@ type
|
|||||||
procedure RenameSubOverloads(Declarations: TFPList);
|
procedure RenameSubOverloads(Declarations: TFPList);
|
||||||
procedure PushOverloadScope(Scope: TPasIdentifierScope);
|
procedure PushOverloadScope(Scope: TPasIdentifierScope);
|
||||||
procedure PopOverloadScope;
|
procedure PopOverloadScope;
|
||||||
procedure AddType(El: TPasType); override;
|
protected
|
||||||
|
procedure AddRecordType(El: TPasRecordType); override;
|
||||||
procedure ResolveImplAsm(El: TPasImplAsmStatement); override;
|
procedure ResolveImplAsm(El: TPasImplAsmStatement); override;
|
||||||
procedure ResolveNameExpr(El: TPasExpr; const aName: string;
|
procedure ResolveNameExpr(El: TPasExpr; const aName: string;
|
||||||
Access: TResolvedRefAccess); override;
|
Access: TResolvedRefAccess); override;
|
||||||
@ -1245,6 +1247,7 @@ type
|
|||||||
function AddExternalName(const aName: string; El: TPasElement): TPasIdentifier; virtual;
|
function AddExternalName(const aName: string; El: TPasElement): TPasIdentifier; virtual;
|
||||||
function FindExternalName(const aName: String): TPasIdentifier; virtual;
|
function FindExternalName(const aName: String): TPasIdentifier; virtual;
|
||||||
procedure AddExternalPath(aName: string; El: TPasElement);
|
procedure AddExternalPath(aName: string; El: TPasElement);
|
||||||
|
procedure AddElevatedLocal(El: TPasElement); virtual;
|
||||||
procedure ClearElementData; virtual;
|
procedure ClearElementData; virtual;
|
||||||
function GenerateGUID(El: TPasClassType): string; virtual;
|
function GenerateGUID(El: TPasClassType): string; virtual;
|
||||||
protected
|
protected
|
||||||
@ -1697,8 +1700,7 @@ type
|
|||||||
Function CreateRTTIClassField(V: TPasVariable; AContext: TConvertContext): TJSElement; virtual;
|
Function CreateRTTIClassField(V: TPasVariable; AContext: TConvertContext): TJSElement; virtual;
|
||||||
Function CreateRTTIClassMethod(Proc: TPasProcedure; AContext: TConvertContext): TJSElement; virtual;
|
Function CreateRTTIClassMethod(Proc: TPasProcedure; AContext: TConvertContext): TJSElement; virtual;
|
||||||
Function CreateRTTIClassProperty(Prop: TPasProperty; AContext: TConvertContext): TJSElement; virtual;
|
Function CreateRTTIClassProperty(Prop: TPasProperty; AContext: TConvertContext): TJSElement; virtual;
|
||||||
Procedure CreateRTTIAnonymous(El: TPasType; AContext: TConvertContext;
|
Procedure CreateRTTIAnonymous(El: TPasType; AContext: TConvertContext); virtual;
|
||||||
var First, Last: TJSStatementList); virtual;
|
|
||||||
// create elements for interfaces
|
// create elements for interfaces
|
||||||
Procedure AddIntfDelegations(ClassEl: TPasElement; Prop: TPasProperty;
|
Procedure AddIntfDelegations(ClassEl: TPasElement; Prop: TPasProperty;
|
||||||
FinishedGUIDs: TStringList; ObjLit: TJSObjectLiteral; aContext: TFunctionContext);
|
FinishedGUIDs: TStringList; ObjLit: TJSObjectLiteral; aContext: TFunctionContext);
|
||||||
@ -2499,6 +2501,11 @@ begin
|
|||||||
if TPasClassType(El).IsForward then
|
if TPasClassType(El).IsForward then
|
||||||
exit(false);
|
exit(false);
|
||||||
end
|
end
|
||||||
|
else if C=TPasRecordType then
|
||||||
|
begin
|
||||||
|
if (not WithElevatedLocal) and (El.Parent is TProcedureBody) then
|
||||||
|
exit(false); // local record counted via TPas2JSSectionScope.FElevatedLocals
|
||||||
|
end
|
||||||
else if C.InheritsFrom(TPasProcedure) then
|
else if C.InheritsFrom(TPasProcedure) then
|
||||||
begin
|
begin
|
||||||
if TPasProcedure(El).IsOverride then
|
if TPasProcedure(El).IsOverride then
|
||||||
@ -2592,7 +2599,8 @@ begin
|
|||||||
Scope:=TPasIdentifierScope(FOverloadScopes[i]);
|
Scope:=TPasIdentifierScope(FOverloadScopes[i]);
|
||||||
if (Scope.ClassType=TPas2JSSectionScope) and (i<FOverloadScopes.Count-1) then
|
if (Scope.ClassType=TPas2JSSectionScope) and (i<FOverloadScopes.Count-1) then
|
||||||
begin
|
begin
|
||||||
// Note: the elevated locals are after the section scope and before the next deeper scope
|
// Note: the elevated locals have their index after the section scope and
|
||||||
|
// before the next deeper scope
|
||||||
|
|
||||||
// check elevated locals
|
// check elevated locals
|
||||||
Identifier:=TPas2JSSectionScope(Scope).FindElevatedLocal(El.Name);
|
Identifier:=TPas2JSSectionScope(Scope).FindElevatedLocal(El.Name);
|
||||||
@ -2609,14 +2617,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
inc(Result,j);
|
inc(Result,j);
|
||||||
end;
|
end;
|
||||||
// find last added
|
// add count or index of this scope
|
||||||
Identifier:=Scope.FindLocalIdentifier(El.Name);
|
Identifier:=Scope.FindLocalIdentifier(El.Name);
|
||||||
// add count or index
|
|
||||||
inc(Result,GetOverloadIndex(Identifier,El));
|
inc(Result,GetOverloadIndex(Identifier,El));
|
||||||
end;
|
end;
|
||||||
// find in external names
|
// finally add count or index of the external scope
|
||||||
Identifier:=FindExternalName(El.Name);
|
Identifier:=FindExternalName(El.Name);
|
||||||
// add count or index
|
|
||||||
inc(Result,GetOverloadIndex(Identifier,El));
|
inc(Result,GetOverloadIndex(Identifier,El));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2734,13 +2740,15 @@ var
|
|||||||
El: TPasElement;
|
El: TPasElement;
|
||||||
Proc: TPasProcedure;
|
Proc: TPasProcedure;
|
||||||
ProcScope, OvrProcScope, ImplProcScope: TPas2JSProcedureScope;
|
ProcScope, OvrProcScope, ImplProcScope: TPas2JSProcedureScope;
|
||||||
|
C: TClass;
|
||||||
begin
|
begin
|
||||||
//IsExternalClass:=(DeclEl is TPasClassType) and (TPasClassType(DeclEl).IsExternal);
|
//IsExternalClass:=(DeclEl is TPasClassType) and (TPasClassType(DeclEl).IsExternal);
|
||||||
if DeclEl=nil then;
|
if DeclEl=nil then;
|
||||||
for i:=0 to Declarations.Count-1 do
|
for i:=0 to Declarations.Count-1 do
|
||||||
begin
|
begin
|
||||||
El:=TPasElement(Declarations[i]);
|
El:=TPasElement(Declarations[i]);
|
||||||
if (El is TPasProcedure) then
|
C:=El.ClassType;
|
||||||
|
if C.InheritsFrom(TPasProcedure) then
|
||||||
begin
|
begin
|
||||||
Proc:=TPasProcedure(El);
|
Proc:=TPasProcedure(El);
|
||||||
ProcScope:=Proc.CustomData as TPas2JSProcedureScope;
|
ProcScope:=Proc.CustomData as TPas2JSProcedureScope;
|
||||||
@ -2772,7 +2780,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
// proc declaration (header, not body)
|
// proc declaration (header, not body)
|
||||||
RenameOverload(Proc);
|
RenameOverload(Proc);
|
||||||
end;
|
end
|
||||||
|
else if (C=TPasClassType) or (C=TPasRecordType) then
|
||||||
|
begin
|
||||||
|
if El.Parent is TProcedureBody then
|
||||||
|
RenameOverload(El);
|
||||||
|
end
|
||||||
|
else if C=TPasConst then
|
||||||
|
RenameOverload(El)
|
||||||
|
else if C.InheritsFrom(TPasVariable) and (El.Parent.ClassType=TPasClassType) then
|
||||||
|
RenameOverload(El);
|
||||||
end;
|
end;
|
||||||
{$IFDEF VerbosePas2JS}
|
{$IFDEF VerbosePas2JS}
|
||||||
//writeln('TPas2JSResolver.RenameOverloads END ',GetObjName(DeclEl));
|
//writeln('TPas2JSResolver.RenameOverloads END ',GetObjName(DeclEl));
|
||||||
@ -2798,7 +2815,7 @@ begin
|
|||||||
Proc:=TPasProcedure(El);
|
Proc:=TPasProcedure(El);
|
||||||
ProcScope:=Proc.CustomData as TPasProcedureScope;
|
ProcScope:=Proc.CustomData as TPasProcedureScope;
|
||||||
{$IFDEF VerbosePas2JS}
|
{$IFDEF VerbosePas2JS}
|
||||||
writeln('TPas2JSResolver.RenameSubOverloads Proc=',Proc.Name,' DeclarationProc=',GetObjName(ProcScope.DeclarationProc),' ImplProc=',GetObjName(ProcScope.ImplProc),' ClassScope=',GetObjName(ProcScope.ClassScope));
|
//writeln('TPas2JSResolver.RenameSubOverloads Proc=',Proc.Name,' DeclarationProc=',GetObjName(ProcScope.DeclarationProc),' ImplProc=',GetObjName(ProcScope.ImplProc),' ClassScope=',GetObjName(ProcScope.ClassScope));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
if Proc.Body<>nil then
|
if Proc.Body<>nil then
|
||||||
begin
|
begin
|
||||||
@ -2810,32 +2827,36 @@ begin
|
|||||||
PopOverloadScope;
|
PopOverloadScope;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else if C=TPasClassType then
|
else if (C=TPasClassType) or (C=TPasRecordType) then
|
||||||
begin
|
begin
|
||||||
ClassEl:=TPasClassType(El);
|
|
||||||
if ClassEl.IsForward then continue;
|
|
||||||
ClassScope:=El.CustomData as TPas2JSClassScope;
|
|
||||||
OldScopeCount:=FOverloadScopes.Count;
|
OldScopeCount:=FOverloadScopes.Count;
|
||||||
|
if C=TPasClassType then
|
||||||
// add class and ancestor scopes
|
begin
|
||||||
aScope:=ClassScope;
|
ClassEl:=TPasClassType(El);
|
||||||
repeat
|
if ClassEl.IsForward then continue;
|
||||||
PushOverloadScope(aScope);
|
ClassScope:=El.CustomData as TPas2JSClassScope;
|
||||||
aScope:=aScope.AncestorScope;
|
// add class and ancestor scopes
|
||||||
until aScope=nil;
|
aScope:=ClassScope;
|
||||||
|
repeat
|
||||||
|
PushOverloadScope(aScope);
|
||||||
|
aScope:=aScope.AncestorScope;
|
||||||
|
until aScope=nil;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// add record scope
|
||||||
|
PushOverloadScope(TPasRecordType(El).CustomData as TPasRecordScope);
|
||||||
|
end;
|
||||||
|
|
||||||
// first rename all overloads on this level
|
// first rename all overloads on this level
|
||||||
RenameOverloads(ClassEl,ClassEl.Members);
|
RenameOverloads(El,TPasMembersType(El).Members);
|
||||||
// then process nested procedures
|
// then process nested procedures
|
||||||
RenameSubOverloads(ClassEl.Members);
|
RenameSubOverloads(TPasMembersType(El).Members);
|
||||||
|
|
||||||
|
// restore scope
|
||||||
while FOverloadScopes.Count>OldScopeCount do
|
while FOverloadScopes.Count>OldScopeCount do
|
||||||
PopOverloadScope;
|
PopOverloadScope;
|
||||||
end
|
end;
|
||||||
else if C=TPasConst then
|
|
||||||
RenameOverload(El)
|
|
||||||
else if C.InheritsFrom(TPasVariable) and (El.Parent.ClassType=TPasClassType) then
|
|
||||||
RenameOverload(El);
|
|
||||||
end;
|
end;
|
||||||
{$IFDEF VerbosePas2JS}
|
{$IFDEF VerbosePas2JS}
|
||||||
//writeln('TPas2JSResolver.RenameSubOverloads END');
|
//writeln('TPas2JSResolver.RenameSubOverloads END');
|
||||||
@ -2852,9 +2873,12 @@ begin
|
|||||||
FOverloadScopes.Delete(FOverloadScopes.Count-1);
|
FOverloadScopes.Delete(FOverloadScopes.Count-1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPas2JSResolver.AddType(El: TPasType);
|
procedure TPas2JSResolver.AddRecordType(El: TPasRecordType);
|
||||||
begin
|
begin
|
||||||
inherited AddType(El);
|
inherited;
|
||||||
|
if El.Parent is TProcedureBody then
|
||||||
|
// local record
|
||||||
|
AddElevatedLocal(El);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPas2JSResolver.ResolveImplAsm(El: TPasImplAsmStatement);
|
procedure TPas2JSResolver.ResolveImplAsm(El: TPasImplAsmStatement);
|
||||||
@ -3307,8 +3331,6 @@ var
|
|||||||
AbsIdent: TPasElement;
|
AbsIdent: TPasElement;
|
||||||
TypeEl, ElTypeEl: TPasType;
|
TypeEl, ElTypeEl: TPasType;
|
||||||
GUID: TGUID;
|
GUID: TGUID;
|
||||||
i: Integer;
|
|
||||||
SectionScope: TPas2JSSectionScope;
|
|
||||||
begin
|
begin
|
||||||
inherited FinishVariable(El);
|
inherited FinishVariable(El);
|
||||||
|
|
||||||
@ -3389,12 +3411,7 @@ begin
|
|||||||
if (El.ClassType=TPasConst) and TPasConst(El).IsConst then
|
if (El.ClassType=TPasConst) and TPasConst(El).IsConst then
|
||||||
begin
|
begin
|
||||||
// local const
|
// local const
|
||||||
i:=ScopeCount-1;
|
AddElevatedLocal(El);
|
||||||
while (i>=0) and not (Scopes[i] is TPas2JSSectionScope) do dec(i);
|
|
||||||
if i<0 then
|
|
||||||
RaiseNotYetImplemented(20180420131358,El);
|
|
||||||
SectionScope:=TPas2JSSectionScope(Scopes[i]);
|
|
||||||
SectionScope.AddElevatedLocal(El.Name,El);
|
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else if ParentC=TImplementationSection then
|
else if ParentC=TImplementationSection then
|
||||||
@ -3846,6 +3863,19 @@ begin
|
|||||||
AddExternalName(LeftStr(aName,p-1),El);
|
AddExternalName(LeftStr(aName,p-1),El);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPas2JSResolver.AddElevatedLocal(El: TPasElement);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
SectionScope: TPas2JSSectionScope;
|
||||||
|
begin
|
||||||
|
i:=ScopeCount-1;
|
||||||
|
while (i>=0) and not (Scopes[i] is TPas2JSSectionScope) do dec(i);
|
||||||
|
if i<0 then
|
||||||
|
RaiseNotYetImplemented(20180420131358,El);
|
||||||
|
SectionScope:=TPas2JSSectionScope(Scopes[i]);
|
||||||
|
SectionScope.AddElevatedLocal(El.Name,El);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TPas2JSResolver.ClearElementData;
|
procedure TPas2JSResolver.ClearElementData;
|
||||||
var
|
var
|
||||||
Data, Next: TPas2JsElementData;
|
Data, Next: TPas2JsElementData;
|
||||||
@ -7086,7 +7116,7 @@ var
|
|||||||
begin
|
begin
|
||||||
if PosEl=nil then PosEl:=El;
|
if PosEl=nil then PosEl:=El;
|
||||||
CurName:=TransformVariableName(El,Name,false,AContext);
|
CurName:=TransformVariableName(El,Name,false,AContext);
|
||||||
if not (El.Parent is TProcedureBody) then
|
if AContext.IsGlobal then
|
||||||
begin
|
begin
|
||||||
ParentName:=AContext.GetLocalName(El.Parent);
|
ParentName:=AContext.GetLocalName(El.Parent);
|
||||||
if ParentName='' then
|
if ParentName='' then
|
||||||
@ -15260,20 +15290,33 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasToJSConverter.CreateRTTIAnonymous(El: TPasType;
|
procedure TPasToJSConverter.CreateRTTIAnonymous(El: TPasType;
|
||||||
AContext: TConvertContext; var First, Last: TJSStatementList);
|
AContext: TConvertContext);
|
||||||
// if El has any anonymous types, create the RTTI
|
// if El has any anonymous types, create the RTTI
|
||||||
var
|
var
|
||||||
C: TClass;
|
C: TClass;
|
||||||
JS: TJSElement;
|
JS: TJSElement;
|
||||||
|
GlobalCtx: TFunctionContext;
|
||||||
|
Src: TJSSourceElements;
|
||||||
begin
|
begin
|
||||||
if El.Name<>'' then
|
if El.Name<>'' then
|
||||||
RaiseNotSupported(El,AContext,20170905162324,'inconsistency');
|
RaiseNotSupported(El,AContext,20170905162324,'inconsistency');
|
||||||
|
|
||||||
|
GlobalCtx:=AContext.GetGlobalFunc;
|
||||||
|
if GlobalCtx=nil then
|
||||||
|
RaiseNotSupported(El,AContext,20181229130835);
|
||||||
|
if not (GlobalCtx.JSElement is TJSSourceElements) then
|
||||||
|
begin
|
||||||
|
{$IFDEF VerbosePas2JS}
|
||||||
|
writeln('TPasToJSConverter.CreateRTTIAnonymous GlobalCtx=',GetObjName(GlobalCtx),' JSElement=',GetObjName(GlobalCtx.JSElement));
|
||||||
|
{$ENDIF}
|
||||||
|
RaiseNotSupported(El,AContext,20181229130926);
|
||||||
|
end;
|
||||||
|
Src:=TJSSourceElements(GlobalCtx.JSElement);
|
||||||
C:=El.ClassType;
|
C:=El.ClassType;
|
||||||
if C=TPasArrayType then
|
if C=TPasArrayType then
|
||||||
begin
|
begin
|
||||||
JS:=ConvertArrayType(TPasArrayType(El),AContext);
|
JS:=ConvertArrayType(TPasArrayType(El),AContext);
|
||||||
AddToStatementList(First,Last,JS,El);
|
AddToSourceElements(Src,JS);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -19219,7 +19262,7 @@ Var
|
|||||||
AssignSt: TJSSimpleAssignStatement;
|
AssignSt: TJSSimpleAssignStatement;
|
||||||
Obj: TJSObjectLiteral;
|
Obj: TJSObjectLiteral;
|
||||||
ObjLit: TJSObjectLiteralElement;
|
ObjLit: TJSObjectLiteralElement;
|
||||||
ConstContext: TFunctionContext;
|
GlobalCtx: TFunctionContext;
|
||||||
C: TJSElement;
|
C: TJSElement;
|
||||||
V: TJSVariableStatement;
|
V: TJSVariableStatement;
|
||||||
Src: TJSSourceElements;
|
Src: TJSSourceElements;
|
||||||
@ -19234,15 +19277,15 @@ begin
|
|||||||
if not AContext.IsGlobal then
|
if not AContext.IsGlobal then
|
||||||
begin
|
begin
|
||||||
// local const are stored in interface/implementation
|
// local const are stored in interface/implementation
|
||||||
ConstContext:=AContext.GetGlobalFunc;
|
GlobalCtx:=AContext.GetGlobalFunc;
|
||||||
if not (ConstContext.JSElement is TJSSourceElements) then
|
if not (GlobalCtx.JSElement is TJSSourceElements) then
|
||||||
begin
|
begin
|
||||||
{$IFDEF VerbosePas2JS}
|
{$IFDEF VerbosePas2JS}
|
||||||
writeln('TPasToJSConverter.CreateConstDecl ConstContext=',GetObjName(ConstContext),' JSElement=',GetObjName(ConstContext.JSElement));
|
writeln('TPasToJSConverter.CreateConstDecl GlobalCtx=',GetObjName(GlobalCtx),' JSElement=',GetObjName(GlobalCtx.JSElement));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
RaiseNotSupported(El,AContext,20170220153216);
|
RaiseNotSupported(El,AContext,20170220153216);
|
||||||
end;
|
end;
|
||||||
Src:=TJSSourceElements(ConstContext.JSElement);
|
Src:=TJSSourceElements(GlobalCtx.JSElement);
|
||||||
C:=ConvertVariable(El,AContext);
|
C:=ConvertVariable(El,AContext);
|
||||||
if C=nil then
|
if C=nil then
|
||||||
RaiseInconsistency(20180501114422,El);
|
RaiseInconsistency(20180501114422,El);
|
||||||
@ -19571,7 +19614,7 @@ const
|
|||||||
RetSt.Expr:=CreateLiteralBoolean(El,true);
|
RetSt.Expr:=CreateLiteralBoolean(El,true);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddRTTIFields(Args: TJSArguments; var First, Last: TJSStatementList);
|
procedure AddRTTIFields(Args: TJSArguments);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
PasVar: TPasVariable;
|
PasVar: TPasVariable;
|
||||||
@ -19583,7 +19626,7 @@ const
|
|||||||
if not IsElementUsed(PasVar) then continue;
|
if not IsElementUsed(PasVar) then continue;
|
||||||
VarType:=PasVar.VarType;
|
VarType:=PasVar.VarType;
|
||||||
if VarType.Name='' then
|
if VarType.Name='' then
|
||||||
CreateRTTIAnonymous(VarType,AContext,First,Last);
|
CreateRTTIAnonymous(VarType,AContext);
|
||||||
// add quoted "fieldname"
|
// add quoted "fieldname"
|
||||||
Args.AddElement(CreateLiteralString(PasVar,TransformVariableName(PasVar,AContext)));
|
Args.AddElement(CreateLiteralString(PasVar,TransformVariableName(PasVar,AContext)));
|
||||||
// add typeinfo ref
|
// add typeinfo ref
|
||||||
@ -19595,40 +19638,54 @@ var
|
|||||||
AssignSt: TJSSimpleAssignStatement;
|
AssignSt: TJSSimpleAssignStatement;
|
||||||
FDS: TJSFunctionDeclarationStatement;
|
FDS: TJSFunctionDeclarationStatement;
|
||||||
FD: TJSFuncDef;
|
FD: TJSFuncDef;
|
||||||
BodyFirst, BodyLast, ListFirst, ListLast: TJSStatementList;
|
BodyFirst, BodyLast, ListFirst: TJSStatementList;
|
||||||
FuncContext: TFunctionContext;
|
FuncContext: TFunctionContext;
|
||||||
|
GlobalCtx: TConvertContext;
|
||||||
ObjLit: TJSObjectLiteral;
|
ObjLit: TJSObjectLiteral;
|
||||||
IfSt: TJSIfStatement;
|
IfSt: TJSIfStatement;
|
||||||
Call, Call2: TJSCallExpression;
|
Call, Call2: TJSCallExpression;
|
||||||
ok: Boolean;
|
ok: Boolean;
|
||||||
|
Src: TJSSourceElements;
|
||||||
|
Proc: TPasProcedure;
|
||||||
|
ProcScope: TPas2JSProcedureScope;
|
||||||
begin
|
begin
|
||||||
|
if El.Name='' then
|
||||||
|
RaiseNotSupported(El,AContext,20181229133138,'anonymous record');
|
||||||
Result:=nil;
|
Result:=nil;
|
||||||
FuncContext:=nil;
|
FuncContext:=nil;
|
||||||
ListFirst:=nil;
|
ListFirst:=nil;
|
||||||
ListLast:=nil;
|
Src:=nil;
|
||||||
ok:=false;
|
ok:=false;
|
||||||
try
|
try
|
||||||
FDS:=CreateFunctionSt(El);
|
FDS:=CreateFunctionSt(El);
|
||||||
FD:=FDS.AFunction;
|
FD:=FDS.AFunction;
|
||||||
|
// records are stored in interface/implementation
|
||||||
|
GlobalCtx:=AContext;
|
||||||
if El.Parent is TProcedureBody then
|
if El.Parent is TProcedureBody then
|
||||||
begin
|
begin
|
||||||
// ToDo: elevate to non local scope
|
GlobalCtx:=AContext.GetGlobalFunc;
|
||||||
// add 'function TypeName(){}'
|
if not (GlobalCtx.JSElement is TJSSourceElements) then
|
||||||
Result:=FDS;
|
begin
|
||||||
FD.Name:=TJSString(TransformVariableName(El,AContext));
|
{$IFDEF VerbosePas2JS}
|
||||||
end
|
writeln('TPasToJSConverter.ConvertRecordType GlobalCtx=',GetObjName(GlobalCtx),' JSElement=',GetObjName(GlobalCtx.JSElement));
|
||||||
else
|
{$ENDIF}
|
||||||
begin
|
RaiseNotSupported(El,AContext,20181229142440);
|
||||||
// add 'this.TypeName = function(){}'
|
end;
|
||||||
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
|
Src:=TJSSourceElements(GlobalCtx.JSElement);
|
||||||
Result:=AssignSt;
|
|
||||||
AssignSt.LHS:=CreateSubDeclNameExpr(El,AContext);
|
|
||||||
AssignSt.Expr:=FDS;
|
|
||||||
end;
|
end;
|
||||||
|
// add 'this.TypeName = function(){}'
|
||||||
|
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
|
||||||
|
AssignSt.LHS:=CreateSubDeclNameExpr(El,GlobalCtx);
|
||||||
|
AssignSt.Expr:=FDS;
|
||||||
|
if Src<>nil then
|
||||||
|
AddToSourceElements(Src,AssignSt)
|
||||||
|
else
|
||||||
|
Result:=AssignSt;
|
||||||
|
|
||||||
// add param s
|
// add param s
|
||||||
FD.Params.Add(SrcParamName);
|
FD.Params.Add(SrcParamName);
|
||||||
// create function body
|
// create function body
|
||||||
FuncContext:=TFunctionContext.Create(El,FD.Body,AContext);
|
FuncContext:=TFunctionContext.Create(El,FD.Body,GlobalCtx);
|
||||||
FuncContext.ThisPas:=El;
|
FuncContext.ThisPas:=El;
|
||||||
FuncContext.IsGlobal:=true;
|
FuncContext.IsGlobal:=true;
|
||||||
BodyFirst:=nil;
|
BodyFirst:=nil;
|
||||||
@ -19650,16 +19707,14 @@ begin
|
|||||||
if FD.Body.A=nil then
|
if FD.Body.A=nil then
|
||||||
FD.Body.A:=BodyFirst;
|
FD.Body.A:=BodyFirst;
|
||||||
|
|
||||||
if HasTypeInfo(El,AContext) then
|
if HasTypeInfo(El,GlobalCtx) then
|
||||||
begin
|
begin
|
||||||
// add $rtti as second statement
|
// add $rtti as second statement
|
||||||
if not (AContext is TFunctionContext) then
|
if not (GlobalCtx is TFunctionContext) then
|
||||||
RaiseNotSupported(El,AContext,20170412120012);
|
RaiseNotSupported(El,GlobalCtx,20170412120012);
|
||||||
|
|
||||||
AddToStatementList(ListFirst,ListLast,Result,El);
|
|
||||||
Result:=nil;
|
|
||||||
// module.$rtti.$Record("typename",{});
|
// module.$rtti.$Record("typename",{});
|
||||||
Call:=CreateRTTINewType(El,GetBIName(pbifnRTTINewRecord),false,AContext,ObjLit);
|
Call:=CreateRTTINewType(El,GetBIName(pbifnRTTINewRecord),false,GlobalCtx,ObjLit);
|
||||||
if ObjLit=nil then
|
if ObjLit=nil then
|
||||||
RaiseInconsistency(20170412124804,El);
|
RaiseInconsistency(20170412124804,El);
|
||||||
if El.Members.Count>0 then
|
if El.Members.Count>0 then
|
||||||
@ -19671,19 +19726,37 @@ begin
|
|||||||
Call2.Expr:=CreateDotExpression(El,Call,
|
Call2.Expr:=CreateDotExpression(El,Call,
|
||||||
CreatePrimitiveDotExpr(GetBIName(pbifnRTTIAddFields),El));
|
CreatePrimitiveDotExpr(GetBIName(pbifnRTTIAddFields),El));
|
||||||
Call:=Call2;
|
Call:=Call2;
|
||||||
AddRTTIFields(Call.Args,ListFirst,ListLast);
|
AddRTTIFields(Call.Args);
|
||||||
|
end;
|
||||||
|
if Src<>nil then
|
||||||
|
// add Call to global statements
|
||||||
|
AddToSourceElements(Src,Call)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// combine Result and Call into a statement list
|
||||||
|
ListFirst:=TJSStatementList(CreateElement(TJSStatementList,El));
|
||||||
|
ListFirst.A:=Result;
|
||||||
|
ListFirst.B:=Call;
|
||||||
|
Result:=ListFirst;
|
||||||
|
ListFirst:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (GlobalCtx<>AContext) and (coStoreImplJS in Options)
|
||||||
|
and (AContext.Resolver<>nil) then
|
||||||
|
begin
|
||||||
|
// store precompiled record type in proc
|
||||||
|
Proc:=AContext.Resolver.GetTopLvlProc(AContext.PasElement);
|
||||||
|
if Proc<>nil then
|
||||||
|
begin
|
||||||
|
ProcScope:=TPas2JSProcedureScope(Proc.CustomData);
|
||||||
|
ProcScope.AddGlobalJS(CreatePrecompiledJS(AssignSt));
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
AddToStatementList(ListFirst,ListLast,Call,El);
|
|
||||||
Result:=ListFirst;
|
|
||||||
ListFirst:=nil;
|
|
||||||
ListLast:=nil;
|
|
||||||
end;
|
end;
|
||||||
ok:=true;
|
ok:=true;
|
||||||
finally
|
finally
|
||||||
FuncContext.Free;
|
FuncContext.Free;
|
||||||
if ListFirst<>nil then
|
if not ok then
|
||||||
FreeAndNil(ListFirst)
|
|
||||||
else if not ok then
|
|
||||||
FreeAndNil(Result);
|
FreeAndNil(Result);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -90,6 +90,7 @@ type
|
|||||||
procedure CheckRestoredPrimitiveExpr(const Path: string; Orig, Rest: TPrimitiveExpr); virtual;
|
procedure CheckRestoredPrimitiveExpr(const Path: string; Orig, Rest: TPrimitiveExpr); virtual;
|
||||||
procedure CheckRestoredBoolConstExpr(const Path: string; Orig, Rest: TBoolConstExpr); virtual;
|
procedure CheckRestoredBoolConstExpr(const Path: string; Orig, Rest: TBoolConstExpr); virtual;
|
||||||
procedure CheckRestoredParamsExpr(const Path: string; Orig, Rest: TParamsExpr); virtual;
|
procedure CheckRestoredParamsExpr(const Path: string; Orig, Rest: TParamsExpr); virtual;
|
||||||
|
procedure CheckRestoredProcedureExpr(const Path: string; Orig, Rest: TProcedureExpr); virtual;
|
||||||
procedure CheckRestoredRecordValues(const Path: string; Orig, Rest: TRecordValues); virtual;
|
procedure CheckRestoredRecordValues(const Path: string; Orig, Rest: TRecordValues); virtual;
|
||||||
procedure CheckRestoredPasExprArray(const Path: string; Orig, Rest: TPasExprArray); virtual;
|
procedure CheckRestoredPasExprArray(const Path: string; Orig, Rest: TPasExprArray); virtual;
|
||||||
procedure CheckRestoredArrayValues(const Path: string; Orig, Rest: TArrayValues); virtual;
|
procedure CheckRestoredArrayValues(const Path: string; Orig, Rest: TArrayValues); virtual;
|
||||||
@ -140,6 +141,7 @@ type
|
|||||||
procedure TestPC_Set;
|
procedure TestPC_Set;
|
||||||
procedure TestPC_SetOfAnonymousEnumType;
|
procedure TestPC_SetOfAnonymousEnumType;
|
||||||
procedure TestPC_Record;
|
procedure TestPC_Record;
|
||||||
|
procedure TestPC_Record_Local;
|
||||||
procedure TestPC_JSValue;
|
procedure TestPC_JSValue;
|
||||||
procedure TestPC_Array;
|
procedure TestPC_Array;
|
||||||
procedure TestPC_ArrayOfAnonymous;
|
procedure TestPC_ArrayOfAnonymous;
|
||||||
@ -149,6 +151,7 @@ type
|
|||||||
procedure TestPC_Proc_UTF8;
|
procedure TestPC_Proc_UTF8;
|
||||||
procedure TestPC_Proc_Arg;
|
procedure TestPC_Proc_Arg;
|
||||||
procedure TestPC_ProcType;
|
procedure TestPC_ProcType;
|
||||||
|
procedure TestPC_Proc_Anonymous;
|
||||||
procedure TestPC_Class;
|
procedure TestPC_Class;
|
||||||
procedure TestPC_ClassForward;
|
procedure TestPC_ClassForward;
|
||||||
procedure TestPC_ClassConstructor;
|
procedure TestPC_ClassConstructor;
|
||||||
@ -1078,6 +1081,8 @@ begin
|
|||||||
CheckRestoredPasExpr(Path,TPasExpr(Orig),TPasExpr(Rest))
|
CheckRestoredPasExpr(Path,TPasExpr(Orig),TPasExpr(Rest))
|
||||||
else if C=TParamsExpr then
|
else if C=TParamsExpr then
|
||||||
CheckRestoredParamsExpr(Path,TParamsExpr(Orig),TParamsExpr(Rest))
|
CheckRestoredParamsExpr(Path,TParamsExpr(Orig),TParamsExpr(Rest))
|
||||||
|
else if C=TProcedureExpr then
|
||||||
|
CheckRestoredProcedureExpr(Path,TProcedureExpr(Orig),TProcedureExpr(Rest))
|
||||||
else if C=TRecordValues then
|
else if C=TRecordValues then
|
||||||
CheckRestoredRecordValues(Path,TRecordValues(Orig),TRecordValues(Rest))
|
CheckRestoredRecordValues(Path,TRecordValues(Orig),TRecordValues(Rest))
|
||||||
else if C=TArrayValues then
|
else if C=TArrayValues then
|
||||||
@ -1259,6 +1264,13 @@ begin
|
|||||||
CheckRestoredPasExpr(Path,Orig,Rest);
|
CheckRestoredPasExpr(Path,Orig,Rest);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCustomTestPrecompile.CheckRestoredProcedureExpr(const Path: string;
|
||||||
|
Orig, Rest: TProcedureExpr);
|
||||||
|
begin
|
||||||
|
CheckRestoredProcedure(Path+'$Ano',Orig.Proc,Rest.Proc);
|
||||||
|
CheckRestoredPasExpr(Path,Orig,Rest);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCustomTestPrecompile.CheckRestoredRecordValues(const Path: string;
|
procedure TCustomTestPrecompile.CheckRestoredRecordValues(const Path: string;
|
||||||
Orig, Rest: TRecordValues);
|
Orig, Rest: TRecordValues);
|
||||||
var
|
var
|
||||||
@ -1691,6 +1703,28 @@ begin
|
|||||||
WriteReadUnit;
|
WriteReadUnit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestPrecompile.TestPC_Record_Local;
|
||||||
|
begin
|
||||||
|
StartUnit(false);
|
||||||
|
Add([
|
||||||
|
'interface',
|
||||||
|
'procedure DoIt;',
|
||||||
|
'implementation',
|
||||||
|
'procedure DoIt;',
|
||||||
|
'type',
|
||||||
|
' TRec = record',
|
||||||
|
' i: longint;',
|
||||||
|
' s: string;',
|
||||||
|
' end;',
|
||||||
|
' P = ^TRec;',
|
||||||
|
' TArrOfRec = array of TRec;',
|
||||||
|
'var',
|
||||||
|
' r: TRec;',
|
||||||
|
'begin',
|
||||||
|
'end;']);
|
||||||
|
WriteReadUnit;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestPrecompile.TestPC_JSValue;
|
procedure TTestPrecompile.TestPC_JSValue;
|
||||||
begin
|
begin
|
||||||
StartUnit(false);
|
StartUnit(false);
|
||||||
@ -1866,6 +1900,32 @@ begin
|
|||||||
WriteReadUnit;
|
WriteReadUnit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestPrecompile.TestPC_Proc_Anonymous;
|
||||||
|
begin
|
||||||
|
StartUnit(false);
|
||||||
|
Add([
|
||||||
|
'interface',
|
||||||
|
'type',
|
||||||
|
' TFunc = reference to function(w: word): word;',
|
||||||
|
' function GetIt(f: TFunc): longint;',
|
||||||
|
'implementation',
|
||||||
|
'var k: byte;',
|
||||||
|
'function GetIt(f: TFunc): longint;',
|
||||||
|
'begin',
|
||||||
|
' f:=function(w: word): word',
|
||||||
|
' var j: byte;',
|
||||||
|
' function GetMul(a,b: longint): longint; ',
|
||||||
|
' begin',
|
||||||
|
' Result:=a*b;',
|
||||||
|
' end;',
|
||||||
|
' begin',
|
||||||
|
' Result:=j*GetMul(1,2)*k;',
|
||||||
|
' end;',
|
||||||
|
'end;',
|
||||||
|
'']);
|
||||||
|
WriteReadUnit;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestPrecompile.TestPC_Class;
|
procedure TTestPrecompile.TestPC_Class;
|
||||||
begin
|
begin
|
||||||
StartUnit(false);
|
StartUnit(false);
|
||||||
|
@ -431,7 +431,7 @@ type
|
|||||||
Procedure TestRecord_Empty;
|
Procedure TestRecord_Empty;
|
||||||
Procedure TestRecord_Var;
|
Procedure TestRecord_Var;
|
||||||
Procedure TestRecord_VarExternal;
|
Procedure TestRecord_VarExternal;
|
||||||
Procedure TestWithRecordDo;
|
Procedure TestRecord_WithDo;
|
||||||
Procedure TestRecord_Assign;
|
Procedure TestRecord_Assign;
|
||||||
Procedure TestRecord_PassAsArgClone;
|
Procedure TestRecord_PassAsArgClone;
|
||||||
Procedure TestRecord_AsParams;
|
Procedure TestRecord_AsParams;
|
||||||
@ -445,6 +445,12 @@ type
|
|||||||
Procedure TestRecord_Const;
|
Procedure TestRecord_Const;
|
||||||
Procedure TestRecord_TypecastFail;
|
Procedure TestRecord_TypecastFail;
|
||||||
Procedure TestRecord_InFunction;
|
Procedure TestRecord_InFunction;
|
||||||
|
// Test name clash const and local record
|
||||||
|
// Test RTTI of local record
|
||||||
|
// Test pcu local record, name clash and rtti
|
||||||
|
|
||||||
|
// advanced record
|
||||||
|
// ToDo: TestRecord_InFunction;
|
||||||
|
|
||||||
// classes
|
// classes
|
||||||
Procedure TestClass_TObjectDefaultConstructor;
|
Procedure TestClass_TObjectDefaultConstructor;
|
||||||
@ -9127,7 +9133,7 @@ begin
|
|||||||
]));
|
]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestWithRecordDo;
|
procedure TTestModule.TestRecord_WithDo;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
Add('type');
|
Add('type');
|
||||||
@ -9760,6 +9766,7 @@ procedure TTestModule.TestRecord_InFunction;
|
|||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
Add([
|
Add([
|
||||||
|
'var TPoint: longint = 3;',
|
||||||
'procedure DoIt;',
|
'procedure DoIt;',
|
||||||
'type',
|
'type',
|
||||||
' TPoint = record x,y: longint; end;',
|
' TPoint = record x,y: longint; end;',
|
||||||
@ -9774,22 +9781,23 @@ begin
|
|||||||
ConvertProgram;
|
ConvertProgram;
|
||||||
CheckSource('TestRecord_InFunction',
|
CheckSource('TestRecord_InFunction',
|
||||||
LinesToStr([ // statements
|
LinesToStr([ // statements
|
||||||
'this.DoIt = function () {',
|
'this.TPoint = 3;',
|
||||||
' function TPoint(s) {',
|
'this.TPoint$1 = function (s) {',
|
||||||
' if (s) {',
|
' if (s) {',
|
||||||
' this.x = s.x;',
|
' this.x = s.x;',
|
||||||
' this.y = s.y;',
|
' this.y = s.y;',
|
||||||
' } else {',
|
' } else {',
|
||||||
' this.x = 0;',
|
' this.x = 0;',
|
||||||
' this.y = 0;',
|
' this.y = 0;',
|
||||||
' };',
|
|
||||||
' this.$equal = function (b) {',
|
|
||||||
' return (this.x === b.x) && (this.y === b.y);',
|
|
||||||
' };',
|
|
||||||
' };',
|
' };',
|
||||||
' var r = new TPoint();',
|
' this.$equal = function (b) {',
|
||||||
|
' return (this.x === b.x) && (this.y === b.y);',
|
||||||
|
' };',
|
||||||
|
'};',
|
||||||
|
'this.DoIt = function () {',
|
||||||
|
' var r = new TPoint$1();',
|
||||||
' var p = [];',
|
' var p = [];',
|
||||||
' p = rtl.arraySetLength(p, TPoint, 2);',
|
' p = rtl.arraySetLength(p, TPoint$1, 2);',
|
||||||
'};',
|
'};',
|
||||||
'']),
|
'']),
|
||||||
LinesToStr([ // $mod.$main
|
LinesToStr([ // $mod.$main
|
||||||
@ -21857,6 +21865,9 @@ begin
|
|||||||
ConvertProgram;
|
ConvertProgram;
|
||||||
CheckSource('TestRTTI_Record',
|
CheckSource('TestRTTI_Record',
|
||||||
LinesToStr([ // statements
|
LinesToStr([ // statements
|
||||||
|
'$mod.$rtti.$DynArray("TFloatRec.d$a", {',
|
||||||
|
' eltype: rtl.char',
|
||||||
|
'});',
|
||||||
'this.TFloatRec = function (s) {',
|
'this.TFloatRec = function (s) {',
|
||||||
' if (s) {',
|
' if (s) {',
|
||||||
' this.d = s.d;',
|
' this.d = s.d;',
|
||||||
@ -21867,9 +21878,6 @@ begin
|
|||||||
' return this.d === b.d;',
|
' return this.d === b.d;',
|
||||||
' };',
|
' };',
|
||||||
'};',
|
'};',
|
||||||
'$mod.$rtti.$DynArray("TFloatRec.d$a", {',
|
|
||||||
' eltype: rtl.char',
|
|
||||||
'});',
|
|
||||||
'$mod.$rtti.$Record("TFloatRec", {}).addFields("d", $mod.$rtti["TFloatRec.d$a"]);',
|
'$mod.$rtti.$Record("TFloatRec", {}).addFields("d", $mod.$rtti["TFloatRec.d$a"]);',
|
||||||
'this.p = null;',
|
'this.p = null;',
|
||||||
'this.r = new $mod.TFloatRec();',
|
'this.r = new $mod.TFloatRec();',
|
||||||
@ -21898,19 +21906,19 @@ begin
|
|||||||
ConvertProgram;
|
ConvertProgram;
|
||||||
CheckSource('TestRTTI_LocalTypes',
|
CheckSource('TestRTTI_LocalTypes',
|
||||||
LinesToStr([ // statements
|
LinesToStr([ // statements
|
||||||
'this.DoIt = function () {',
|
'this.TPoint = function(s) {',
|
||||||
' function TPoint(s) {',
|
' if (s) {',
|
||||||
' if (s) {',
|
' this.x = s.x;',
|
||||||
' this.x = s.x;',
|
' this.y = s.y;',
|
||||||
' this.y = s.y;',
|
' } else {',
|
||||||
' } else {',
|
' this.x = 0;',
|
||||||
' this.x = 0;',
|
' this.y = 0;',
|
||||||
' this.y = 0;',
|
|
||||||
' };',
|
|
||||||
' this.$equal = function (b) {',
|
|
||||||
' return (this.x === b.x) && (this.y === b.y);',
|
|
||||||
' };',
|
|
||||||
' };',
|
' };',
|
||||||
|
' this.$equal = function (b) {',
|
||||||
|
' return (this.x === b.x) && (this.y === b.y);',
|
||||||
|
' };',
|
||||||
|
'};',
|
||||||
|
'this.DoIt = function () {',
|
||||||
'};',
|
'};',
|
||||||
'']),
|
'']),
|
||||||
LinesToStr([ // $mod.$main
|
LinesToStr([ // $mod.$main
|
||||||
|
Loading…
Reference in New Issue
Block a user