pastojs: store proc scope OverloadName

git-svn-id: trunk@38609 -
This commit is contained in:
Mattias Gaertner 2018-03-23 09:41:13 +00:00
parent 3c5bbd06a6
commit 2f455a7320
2 changed files with 116 additions and 49 deletions

View File

@ -842,6 +842,7 @@ type
TPas2JSProcedureScope = class(TPasProcedureScope)
public
OverloadName: string;
ResultVarName: string; // valid in implementation ProcScope, empty means use ResolverResultVar
BodyJS: string; // Option coStoreProcJS: stored in ImplScope
GlobalJS: TStringList; // Option coStoreProcJS: stored in ImplScope
@ -1047,6 +1048,7 @@ type
function CreateElementData(DataClass: TPas2JsElementDataClass;
El: TPasElement): TPas2JsElementData; virtual;
// utility
function GetOverloadName(El: TPasElement): string;
function GetBaseDescription(const R: TPasResolverResult; AddPath: boolean=
false): string; override;
function HasTypeInfo(El: TPasType): boolean; override;
@ -1100,15 +1102,15 @@ type
ResourceStrings: TJSVarDeclaration;
end;
{ TFCLocalVar }
{ TFCLocalIdentifier }
TFCLocalVar = class
TFCLocalIdentifier = class
public
Element: TPasElement;
Name: string;
constructor Create(const aName: string; TheEl: TPasElement);
end;
TFCLocalVars = array of TFCLocalVar;
TFCLocalVars = array of TFCLocalIdentifier;
{ TFunctionContext
Module Function: PasElement is TPasProcedure, ThisPas=nil
@ -1124,8 +1126,8 @@ type
function GetLocalName(El: TPasElement): string; override;
function IndexOfLocalVar(const aName: string): integer;
function IndexOfLocalVar(El: TPasElement): integer;
function FindLocalVar(const aName: string): TFCLocalVar;
function FindLocalVar(El: TPasElement): TFCLocalVar;
function FindLocalVar(const aName: string): TFCLocalIdentifier;
function FindLocalIdentifier(El: TPasElement): TFCLocalIdentifier;
procedure DoWriteStack(Index: integer); override;
end;
@ -1260,6 +1262,8 @@ type
Function CreatePrimitiveDotExpr(AName: string; Src: TPasElement): TJSElement;
Function CreateSubDeclNameExpr(El: TPasElement; const Name: string;
AContext: TConvertContext; PosEl: TPasElement = nil): TJSElement;
Function CreateSubDeclNameExpr(El: TPasElement;
AContext: TConvertContext; PosEl: TPasElement = nil): TJSElement;
Function CreateIdentifierExpr(El: TPasElement; AContext: TConvertContext): TJSElement;
Function CreateIdentifierExpr(AName: string; El: TPasElement; AContext: TConvertContext): TJSElement;
Function CreateSwitchStatement(El: TPasImplCaseOf; AContext: TConvertContext): TJSElement;
@ -1289,6 +1293,7 @@ type
Function IsExternalClassConstructor(El: TPasElement): boolean;
Function IsLiteralInteger(El: TJSElement; out Number: MaxPrecInt): boolean;
// Name mangling
Function GetOverloadName(El: TPasElement; AContext: TConvertContext): string;
Function TransformVariableName(El: TPasElement; Const AName: String; AContext : TConvertContext): String; virtual;
Function TransformVariableName(El: TPasElement; AContext : TConvertContext) : String; virtual;
Function TransformModuleName(El: TPasModule; AddModulesPrefix: boolean; AContext : TConvertContext) : String; virtual;
@ -1584,9 +1589,9 @@ begin
inherited Destroy;
end;
{ TFCLocalVar }
{ TFCLocalIdentifier }
constructor TFCLocalVar.Create(const aName: string; TheEl: TPasElement);
constructor TFCLocalIdentifier.Create(const aName: string; TheEl: TPasElement);
begin
Name:=aName;
Element:=TheEl;
@ -1799,6 +1804,7 @@ var
var
NewName: String;
Duplicate: TPasElement;
ProcScope: TPas2JSProcedureScope;
begin
// => count overloads in this section
OverloadIndex:=GetOverloadIndex(El);
@ -1823,7 +1829,17 @@ begin
{$IFDEF VerbosePas2JS}
writeln('TPas2JSResolver.RenameOverload "',El.Name,'" has overload. NewName="',NewName,'"');
{$ENDIF}
El.Name:=NewName;
if (El.CustomData is TPas2JSProcedureScope) then
begin
ProcScope:=TPas2JSProcedureScope(El.CustomData);
ProcScope.OverloadName:=NewName;
if ProcScope.DeclarationProc<>nil then
RaiseInternalError(20180322233222,El.FullPath);
if ProcScope.ImplProc<>nil then
TPas2JSProcedureScope(ProcScope.ImplProc.CustomData).OverloadName:=NewName;
end
else
El.Name:=NewName;
Result:=true;
end;
@ -1855,7 +1871,7 @@ var
i: Integer;
El: TPasElement;
Proc: TPasProcedure;
ProcScope: TPasProcedureScope;
ProcScope, OvrProcScope, ImplProcScope: TPas2JSProcedureScope;
begin
//IsExternalClass:=(DeclEl is TPasClassType) and (TPasClassType(DeclEl).IsExternal);
if DeclEl=nil then;
@ -1865,25 +1881,24 @@ begin
if (El is TPasProcedure) then
begin
Proc:=TPasProcedure(El);
ProcScope:=Proc.CustomData as TPasProcedureScope;
ProcScope:=Proc.CustomData as TPas2JSProcedureScope;
//writeln('TPas2JSResolver.RenameOverloads Proc=',Proc.Name,' DeclarationProc=',GetObjName(ProcScope.DeclarationProc),' ImplProc=',GetObjName(ProcScope.ImplProc),' ClassScope=',GetObjName(ProcScope.ClassScope));
if ProcScope.DeclarationProc<>nil then
continue
else if Proc.IsOverride then
begin
if ProcScope.ImplProc<>nil then
RaiseInternalError(20170221110853);
// proc implementation (not forward) -> skip
Proc.Name:=ProcScope.DeclarationProc.Name;
continue;
end;
if Proc.IsOverride then
begin
// override -> copy name from overridden proc
if ProcScope.OverriddenProc=nil then
RaiseInternalError(20171205183502);
if Proc.Name<>ProcScope.OverriddenProc.Name then
OvrProcScope:=TPas2JSProcedureScope(ProcScope.OverriddenProc.CustomData);
if OvrProcScope.OverloadName<>'' then
begin
Proc.Name:=ProcScope.OverriddenProc.Name;
ProcScope.OverloadName:=OvrProcScope.OverloadName;
if ProcScope.ImplProc<>nil then
ProcScope.ImplProc.Name:=Proc.Name;
begin
ImplProcScope:=TPas2JSProcedureScope(ProcScope.ImplProc.CustomData);
ImplProcScope.OverloadName:=ProcScope.OverloadName;
end;
end;
continue;
end
@ -1894,9 +1909,7 @@ begin
continue;
end;
// proc declaration (header, not body)
if RenameOverload(Proc) then
if ProcScope.ImplProc<>nil then
ProcScope.ImplProc.Name:=Proc.Name;
RenameOverload(Proc);
end;
end;
{$IFDEF VerbosePas2JS}
@ -3481,6 +3494,19 @@ begin
AddElementData(Result);
end;
function TPas2JSResolver.GetOverloadName(El: TPasElement): string;
var
Data: TObject;
begin
Data:=El.CustomData;
if Data is TPas2JSProcedureScope then
begin
Result:=TPas2JSProcedureScope(Data).OverloadName;
if Result<>'' then exit;
end;
Result:=El.Name;
end;
function TPas2JSResolver.GetBaseDescription(const R: TPasResolverResult;
AddPath: boolean): string;
begin
@ -3633,18 +3659,18 @@ var
begin
l:=length(LocalVars);
SetLength(LocalVars,l+1);
LocalVars[l]:=TFCLocalVar.Create(aName,El);
LocalVars[l]:=TFCLocalIdentifier.Create(aName,El);
end;
function TFunctionContext.ToString: string;
var
V: TFCLocalVar;
V: TFCLocalIdentifier;
begin
Result:=inherited ToString;
if ThisPas<>nil then
begin
Result:=Result+' this';
V:=FindLocalVar(ThisPas);
V:=FindLocalIdentifier(ThisPas);
if V<>nil then
Result:=Result+'="'+V.Name+'"';
Result:=Result+'='+GetObjName(ThisPas);
@ -3653,10 +3679,10 @@ end;
function TFunctionContext.GetLocalName(El: TPasElement): string;
var
V: TFCLocalVar;
V: TFCLocalIdentifier;
begin
if El=nil then exit('');
V:=FindLocalVar(El);
V:=FindLocalIdentifier(El);
if V<>nil then
Result:=V.Name
else if ThisPas=El then
@ -3684,7 +3710,7 @@ begin
Result:=-1;
end;
function TFunctionContext.FindLocalVar(const aName: string): TFCLocalVar;
function TFunctionContext.FindLocalVar(const aName: string): TFCLocalIdentifier;
var
i: Integer;
begin
@ -3695,7 +3721,7 @@ begin
Result:=nil;
end;
function TFunctionContext.FindLocalVar(El: TPasElement): TFCLocalVar;
function TFunctionContext.FindLocalIdentifier(El: TPasElement): TFCLocalIdentifier;
var
i: Integer;
begin
@ -4355,6 +4381,15 @@ begin
end;
end;
function TPasToJSConverter.GetOverloadName(El: TPasElement;
AContext: TConvertContext): string;
begin
if AContext.Resolver<>nil then
Result:=AContext.Resolver.GetOverloadName(El)
else
Result:=El.Name;
end;
function TPasToJSConverter.ConvertBinaryExpression(El: TBinaryExpr;
AContext: TConvertContext): TJSElement;
Const
@ -4854,6 +4889,18 @@ begin
Result:=CreatePrimitiveDotExpr(CurName,PosEl);
end;
function TPasToJSConverter.CreateSubDeclNameExpr(El: TPasElement;
AContext: TConvertContext; PosEl: TPasElement): TJSElement;
var
Name: String;
begin
if AContext.Resolver<>nil then
Name:=AContext.Resolver.GetOverloadName(El)
else
Name:=El.Name;
Result:=CreateSubDeclNameExpr(El,Name,AContext,PosEl);
end;
function TPasToJSConverter.ConvertPrimitiveExpression(El: TPrimitiveExpr;
AContext: TConvertContext): TJSElement;
@ -7976,17 +8023,17 @@ function TPasToJSConverter.ConvertRecordValues(El: TRecordValues;
Var
R : TJSObjectLiteral;
I : Integer;
It : TRecordValuesItem;
RVI : TRecordValuesItem;
rel : TJSObjectLiteralElement;
begin
R:=TJSObjectLiteral(CreateElement(TJSObjectLiteral,El));
For I:=0 to Length(El.Fields)-1 do
begin
it:=El.Fields[i];
RVI:=El.Fields[i];
Rel:=R.Elements.AddElement;
Rel.Name:=TJSString(it.Name);
Rel.Expr:=ConvertElement(it.ValueExp,AContext);
Rel.Name:=TJSString(RVI.Name);
Rel.Expr:=ConvertElement(RVI.ValueExp,AContext);
end;
Result:=R;
end;
@ -8132,7 +8179,7 @@ begin
// create 'this.A=initvalue'
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
Result:=AssignSt;
AssignSt.LHS:=CreateSubDeclNameExpr(El,El.Name,AContext);
AssignSt.LHS:=CreateSubDeclNameExpr(El,AContext);
AssignSt.Expr:=CreateVarInit(El,AContext);
end
else
@ -8528,7 +8575,7 @@ var
begin
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
NewEl:=AssignSt;
AssignSt.LHS:=CreateSubDeclNameExpr(P,P.Name,New_FuncContext);
AssignSt.LHS:=CreateSubDeclNameExpr(P,New_FuncContext);
AssignSt.Expr:=CreateLiteralUndefined(El);
end;
end;
@ -8942,7 +8989,7 @@ begin
begin
// add 'this.TypeName = function(){}'
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
AssignSt.LHS:=CreateSubDeclNameExpr(El,El.Name,AContext);
AssignSt.LHS:=CreateSubDeclNameExpr(El,AContext);
AssignSt.Expr:=Obj;
Result:=AssignSt;
end;
@ -8990,7 +9037,7 @@ begin
// add enumtype: this.TypeName
TIProp:=TIObj.Elements.AddElement;
TIProp.Name:=TJSString(FBuiltInNames[pbivnRTTIEnum_EnumType]);
TIProp.Expr:=CreateSubDeclNameExpr(El,El.Name,AContext);
TIProp.Expr:=CreateSubDeclNameExpr(El,AContext);
end;
ok:=true;
@ -9544,7 +9591,7 @@ begin
exit;
{$IFDEF VerbosePas2JS}
writeln('TPasToJSConverter.ConvertProcedure "',El.Name,'" ',El.Parent.ClassName);
writeln('TPasToJSConverter.ConvertProcedure "',El.Name,'" Overload="',ProcScope.OverloadName,'" ',El.Parent.ClassName);
{$ENDIF}
ImplProc:=El;
@ -9587,7 +9634,7 @@ begin
begin
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,ImplProc));
Result:=AssignSt;
AssignSt.LHS:=CreateSubDeclNameExpr(El,El.Name,AContext,ImplProc);
AssignSt.LHS:=CreateSubDeclNameExpr(El,AContext,ImplProc);
end;
FS:=CreateFunctionSt(ImplProc,ImplProc.Body<>nil);
@ -13967,7 +14014,7 @@ begin
// create 'this.A=initvalue'
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
Result:=AssignSt;
AssignSt.LHS:=CreateSubDeclNameExpr(El,El.Name,AContext);
AssignSt.LHS:=CreateSubDeclNameExpr(El,AContext);
AssignSt.Expr:=CreateVarInit(El,AContext);
end;
end;
@ -14304,7 +14351,7 @@ begin
// add 'this.TypeName = function(){}'
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
Result:=AssignSt;
AssignSt.LHS:=CreateSubDeclNameExpr(El,El.Name,AContext);
AssignSt.LHS:=CreateSubDeclNameExpr(El,AContext);
AssignSt.Expr:=FDS;
end;
FD:=FDS.AFunction;
@ -14494,15 +14541,23 @@ end;
function TPasToJSConverter.TransformVariableName(El: TPasElement;
AContext: TConvertContext): String;
var
aType: TPasType;
begin
if (El is TPasProcedure) and (TPasProcedure(El).LibrarySymbolName<>nil) then
Result:=ComputeConstString(TPasProcedure(El).LibrarySymbolName,AContext,true)
else if (El is TPasVariable) and (TPasVariable(El).ExportName<>nil) then
Result:=ComputeConstString(TPasVariable(El).ExportName,AContext,true)
else if (El is TPasType) then
Result:=TransformVariableName(El,AContext.Resolver.ResolveAliasType(TPasType(El)).Name,AContext)
begin
if AContext.Resolver<>nil then
aType:=AContext.Resolver.ResolveAliasType(TPasType(El))
else
aType:=TPasType(El);
Result:=TransformVariableName(El,aType.Name,AContext);
end
else
Result:=TransformVariableName(El,El.Name,AContext);
Result:=TransformVariableName(El,GetOverloadName(El,AContext),AContext);
end;
function TPasToJSConverter.TransformModuleName(El: TPasModule;

View File

@ -68,6 +68,8 @@ uses
const
PCUMagic = 'Pas2JSCache';
PCUVersion = 1;
// Version Changes:
// 1: initial version
BuiltInNodeName = 'BuiltIn';
@ -2169,7 +2171,7 @@ begin
writeln('TPCUWriter.WritePasElement ',GetObjName(El));
{$ENDIF}
if El.Name<>'' then
Obj.Add('Name',El.Name);
Obj.Add('Name',Resolver.GetOverloadName(El));
// Id
Ref:=GetElementReference(El);
@ -3504,6 +3506,7 @@ begin
// Not needed, contains only local stuff: WriteIdentifierScope(Obj,Scope,aContext);
if Scope.ResultVarName<>'' then
Obj.Add('ResultVarName',Scope.ResultVarName);
// Scope.OverloadName is stored as 'Name' and ReadProcedureScope reverts it
if Scope.DeclarationProc<>nil then
RaiseMsg(20180219135933,Scope.Element);
@ -3666,7 +3669,7 @@ begin
if not (El is TPasModule) then
RaiseMsg(20180308174440,El,GetObjName(El));
// check name
Name:=El.Name;
Name:=Resolver.GetOverloadName(El);
if Name='' then
if El is TInterfaceSection then
Name:='Interface'
@ -4945,8 +4948,8 @@ begin
if (Index<0) or (Index>=Members.Count) then
RaiseMsg(20180309184718,El,IntToStr(Index)+' out of bounds 0-'+IntToStr(Members.Count));
ChildEl:=TPasElement(Members[Index]);
if ChildEl.Name<>Name then
RaiseMsg(20180309200800,El,'Expected="'+Name+'", but found "'+ChildEl.Name+'"');
if Resolver.GetOverloadName(ChildEl)<>Name then
RaiseMsg(20180309200800,El,'Expected="'+Name+'", but found "'+Resolver.GetOverloadName(ChildEl)+'" ('+ChildEl.Name+')');
// read child declarations
ReadExternalReferences(SubObj,ChildEl);
@ -6787,6 +6790,7 @@ var
begin
Proc:=Scope.Element as TPasProcedure;
ReadString(Obj,'ResultVarName',Scope.ResultVarName,Proc);
// Scope.OverloadName is already set in ReadProcedure
ReadElementReference(Obj,Scope,'ImplProc',@Set_ProcedureScope_ImplProc);
ReadElementReference(Obj,Scope,'Overridden',@Set_ProcedureScope_Overridden);
if Proc.Parent is TPasClassType then
@ -6868,6 +6872,7 @@ var
DeclProcId: integer;
Ref: TPCUFilerElementRef;
DeclProc: TPasProcedure;
p: SizeInt;
begin
if Obj.Find('Scope') is TJSONBoolean then
Scope:=nil // msIgnoreInterfaces
@ -6875,6 +6880,13 @@ begin
begin
Scope:=TPas2JSProcedureScope(Resolver.CreateScope(El,Resolver.ScopeClass_Procedure));
El.CustomData:=Scope;
p:=Pos('$',El.Name);
if p>0 then
begin
// overload proc name$2 was stored in 'Name'
Scope.OverloadName:=El.Name;
El.Name:=LeftStr(El.Name,p-1);
end;
end;
ReadPasElement(Obj,El,aContext);