Browse Source

pastojs: store proc scope OverloadName

git-svn-id: trunk@38609 -
Mattias Gaertner 7 years ago
parent
commit
2f455a7320
2 changed files with 116 additions and 49 deletions
  1. 100 45
      packages/pastojs/src/fppas2js.pp
  2. 16 4
      packages/pastojs/src/pas2jsfiler.pp

+ 100 - 45
packages/pastojs/src/fppas2js.pp

@@ -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;

+ 16 - 4
packages/pastojs/src/pas2jsfiler.pp

@@ -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);