Browse Source

* Advanced records structure changed, fixed fpdoc

git-svn-id: trunk@47510 -
(cherry picked from commit 5354cf2a619e306e6779b5e5d4853ed62c58a467)
michael 4 years ago
parent
commit
373721ee36

+ 7 - 4
packages/fcl-passrc/src/pastree.pp

@@ -1169,7 +1169,8 @@ type
     otBitwiseAnd, otbitwiseXor,
     otBitwiseAnd, otbitwiseXor,
     otLogicalAnd, otLogicalNot, otLogicalXor,
     otLogicalAnd, otLogicalNot, otLogicalXor,
     otRightShift,
     otRightShift,
-    otEnumerator, otIn
+    otEnumerator, otIn,
+    otInitialize // Management operator
     );
     );
   TOperatorTypes = set of TOperatorType;
   TOperatorTypes = set of TOperatorType;
 
 
@@ -1751,13 +1752,13 @@ const
            '>',':=','<>','<=','>=','**',
            '>',':=','<>','<=','>=','**',
            '><','Inc','Dec','mod','-','+','Or','div',
            '><','Inc','Dec','mod','-','+','Or','div',
            'shl','or','and','xor','and','not','xor',
            'shl','or','and','xor','and','not','xor',
-           'shr','enumerator','in');
+           'shr','enumerator','in','');
   OperatorNames : Array[TOperatorType] of string
   OperatorNames : Array[TOperatorType] of string
        =  ('','implicit','explicit','multiply','add','subtract','divide','lessthan','equal',
        =  ('','implicit','explicit','multiply','add','subtract','divide','lessthan','equal',
            'greaterthan','assign','notequal','lessthanorequal','greaterthanorequal','power',
            'greaterthan','assign','notequal','lessthanorequal','greaterthanorequal','power',
            'symmetricaldifference','inc','dec','modulus','negative','positive','bitwiseor','intdivide',
            'symmetricaldifference','inc','dec','modulus','negative','positive','bitwiseor','intdivide',
            'leftshift','logicalor','bitwiseand','bitwisexor','logicaland','logicalnot','logicalxor',
            'leftshift','logicalor','bitwiseand','bitwisexor','logicaland','logicalnot','logicalxor',
-           'rightshift','enumerator','in');
+           'rightshift','enumerator','in','initialize');
 
 
   AssignKindNames : Array[TAssignKind] of string = (':=','+=','-=','*=','/=' );
   AssignKindNames : Array[TAssignKind] of string = (':=','+=','-=','*=','/=' );
 
 
@@ -2836,7 +2837,9 @@ begin
         Result := Result + ', ';
         Result := Result + ', ';
       Result := Result + TPasArgument(ProcType.Args[i]).ArgType.Name;
       Result := Result + TPasArgument(ProcType.Args[i]).ArgType.Name;
       end;
       end;
-    Result := Result + '): ' + TPasFunctionType(ProcType).ResultEl.ResultType.Name;
+    Result := Result + ')';
+    if (OperatorType<>otInitialize) and Assigned(TPasFunctionType(ProcType).ResultEl.ResultType) then
+       Result:=Result+': ' + TPasFunctionType(ProcType).ResultEl.ResultType.Name;
     If WithPath then
     If WithPath then
       begin
       begin
       S:=Self.ParentPath;
       S:=Self.ParentPath;

+ 29 - 8
packages/fcl-passrc/src/pparser.pp

@@ -5356,13 +5356,17 @@ begin
         begin
         begin
         ResultEl.Name := CurTokenName;
         ResultEl.Name := CurTokenName;
         ExpectToken(tkColon);
         ExpectToken(tkColon);
-        end
-      else
-        if (CurToken=tkColon) then
-          ResultEl.Name := 'Result'
-        else
-          ParseExc(nParserExpectedColonID,SParserExpectedColonID);
         ResultEl.ResultType := ParseType(ResultEl,CurSourcePos);
         ResultEl.ResultType := ParseType(ResultEl,CurSourcePos);
+        end
+      else if not ((Parent is TPasOperator) and (TPasOperator(Parent).OperatorType=otInitialize)) then
+        // Initialize operator has no result
+        begin
+         if (CurToken=tkColon) then
+            ResultEl.Name := 'Result'
+          else
+            ParseExc(nParserExpectedColonID,SParserExpectedColonID);
+         ResultEl.ResultType := ParseType(ResultEl,CurSourcePos);
+         end;
       end;
       end;
   else
   else
     ResultEl:=Nil;
     ResultEl:=Nil;
@@ -6883,7 +6887,10 @@ Var
   CurEl: TPasElement;
   CurEl: TPasElement;
   LastToken: TToken;
   LastToken: TToken;
   AllowVisibility: Boolean;
   AllowVisibility: Boolean;
+  IsGeneric : Boolean;
+
 begin
 begin
+  IsGeneric:=False;
   AllowVisibility:=msAdvancedRecords in CurrentModeswitches;
   AllowVisibility:=msAdvancedRecords in CurrentModeswitches;
   if AllowVisibility then
   if AllowVisibility then
     v:=visPublic
     v:=visPublic
@@ -6969,7 +6976,7 @@ begin
         if Not AllowMethods then
         if Not AllowMethods then
           ParseExc(nErrRecordMethodsNotAllowed,SErrRecordMethodsNotAllowed);
           ParseExc(nErrRecordMethodsNotAllowed,SErrRecordMethodsNotAllowed);
         ProcType:=GetProcTypeFromToken(CurToken,LastToken=tkclass);
         ProcType:=GetProcTypeFromToken(CurToken,LastToken=tkclass);
-        Proc:=ParseProcedureOrFunctionDecl(ARec,ProcType,false,v);
+        Proc:=ParseProcedureOrFunctionDecl(ARec,ProcType,IsGeneric,v);
         if Proc.Parent is TPasOverloadedProc then
         if Proc.Parent is TPasOverloadedProc then
           TPasOverloadedProc(Proc.Parent).Overloads.Add(Proc)
           TPasOverloadedProc(Proc.Parent).Overloads.Add(Proc)
         else
         else
@@ -6978,9 +6985,21 @@ begin
         end;
         end;
       tkDestructor:
       tkDestructor:
         ParseExc(nParserNoConstructorAllowed,SParserNoConstructorAllowed);
         ParseExc(nParserNoConstructorAllowed,SParserNoConstructorAllowed);
-      tkabsolute,tkGeneric,tkSelf, // Counts as field name
+      tkGeneric, // Can count as field name
+      tkabsolute,
+      tkSelf, // Count as field name
       tkIdentifier :
       tkIdentifier :
         begin
         begin
+        if (Curtoken=tkGeneric) and AllowVisibility then
+          begin
+          NextToken;
+          if CurToken in [tkClass,tkOperator,tkFunction,tkProcedure] then
+            begin
+            IsGeneric:=True;
+            Continue;
+            end;
+          UnGetToken;
+          end;
         If AllowVisibility and CheckVisibility(CurTokenString,v) then
         If AllowVisibility and CheckVisibility(CurTokenString,v) then
           begin
           begin
           if not (v in [visPrivate,visPublic,visStrictPrivate]) then
           if not (v in [visPrivate,visPublic,visStrictPrivate]) then
@@ -7034,6 +7053,8 @@ begin
       break;
       break;
     LastToken:=CurToken;
     LastToken:=CurToken;
     NextToken;
     NextToken;
+    if not IsClass then
+      IsGeneric:=False;
     end;
     end;
 end;
 end;
 
 

+ 8 - 0
packages/fcl-passrc/tests/tcprocfunc.pas

@@ -178,6 +178,7 @@ type
     Procedure TestProcedureCdeclExternalName;
     Procedure TestProcedureCdeclExternalName;
     Procedure TestFunctionCdeclExternalName;
     Procedure TestFunctionCdeclExternalName;
     Procedure TestFunctionAlias;
     Procedure TestFunctionAlias;
+    Procedure TestOperatorNamedResult;
     Procedure TestOperatorTokens;
     Procedure TestOperatorTokens;
     procedure TestOperatorNames;
     procedure TestOperatorNames;
     Procedure TestAssignOperatorAfterObject;
     Procedure TestAssignOperatorAfterObject;
@@ -1312,6 +1313,13 @@ begin
   AssertEquals('Alias name','''myalias''',Func.AliasName);
   AssertEquals('Alias name','''myalias''',Func.AliasName);
 end;
 end;
 
 
+procedure TTestProcedureFunction.TestOperatorNamedResult;
+begin
+  AddDeclaration('operator = (a,b : T) z : Integer;');
+  ParseOperator;
+  AssertEquals('Correct operator type',otEqual,FOperator.OperatorType);
+end;
+
 procedure TTestProcedureFunction.TestProcedureAlias;
 procedure TTestProcedureFunction.TestProcedureAlias;
 begin
 begin
   AddDeclaration('Procedure A; Alias : ''myalias''');
   AddDeclaration('Procedure A; Alias : ''myalias''');

+ 47 - 0
packages/fcl-passrc/tests/tctypeparser.pas

@@ -368,6 +368,8 @@ type
     Procedure TestAdvRecordInFunction;
     Procedure TestAdvRecordInFunction;
     Procedure TestAdvRecordInAnonFunction;
     Procedure TestAdvRecordInAnonFunction;
     Procedure TestAdvRecordClassOperator;
     Procedure TestAdvRecordClassOperator;
+    Procedure TestAdvRecordInitOperator;
+    Procedure TestAdvRecordGenericFunction;
   end;
   end;
 
 
   { TTestProcedureTypeParser }
   { TTestProcedureTypeParser }
@@ -2715,6 +2717,51 @@ begin
   ParseModule;   // We're just interested in that it parses.
   ParseModule;   // We're just interested in that it parses.
 end;
 end;
 
 
+procedure TTestRecordTypeParser.TestAdvRecordInitOperator;
+// Source from bug id 36180
+
+Const
+   SRC =
+    '{$mode objfpc}'+sLineBreak+
+    '{$modeswitch advancedrecords}'+sLineBreak+
+    'program afile;'+sLineBreak+
+    'type'+sLineBreak+
+    '  TMyRecord = record'+sLineBreak+
+    '    class operator initialize (var self: TMyRecord);'+sLineBreak+
+    '  end;'+sLineBreak+
+    'class operator TMyRecord.initialize (a, b: TMyRecord);'+sLineBreak+
+    'begin'+sLineBreak+
+    '  result := (@a = @b);'+sLineBreak+
+    'end;'+sLineBreak+
+    'begin'+sLineBreak+
+    'end.';
+
+begin
+  Source.Text:=Src;
+  ParseModule;   // We're just interested in that it parses.
+end;
+
+procedure TTestRecordTypeParser.TestAdvRecordGenericFunction;
+
+Const
+   SRC =
+    '{$mode objfpc}'+sLineBreak+
+    '{$modeswitch advancedrecords}'+sLineBreak+
+    'program afile;'+sLineBreak+
+    'type'+sLineBreak+
+    '  TMyRecord = record'+sLineBreak+
+    '    generic class procedure doit<T> (a: T);'+sLineBreak+
+    '  end;'+sLineBreak+
+    'generic class procedure TMyRecord.DoIt<T>(a: T);'+sLineBreak+
+    'begin'+sLineBreak+
+    'end;'+sLineBreak+
+    'begin'+sLineBreak+
+    'end.';
+begin
+  Source.Text:=Src;
+  ParseModule;   // We're just interested in that it parses.
+end;
+
 { TBaseTestTypeParser }
 { TBaseTestTypeParser }
 
 
 Function TBaseTestTypeParser.ParseType(ASource: String; ATypeClass: TClass;
 Function TBaseTestTypeParser.ParseType(ASource: String; ATypeClass: TClass;

+ 2 - 1
packages/pastojs/src/pas2jsfiler.pp

@@ -485,7 +485,8 @@ const
     'LogicalXor',
     'LogicalXor',
     'RightShift',
     'RightShift',
     'Enumerator',
     'Enumerator',
-    'In'
+    'In',
+    'Initialize'
     );
     );
 
 
   PCUProcedureModifierNames: array[TProcedureModifier] of string = (
   PCUProcedureModifierNames: array[TProcedureModifier] of string = (

+ 32 - 24
utils/fpdoc/dglobals.pp

@@ -1056,7 +1056,8 @@ var
   i, j, k: Integer;
   i, j, k: Integer;
   Module: TPasModule;
   Module: TPasModule;
   Alias : TPasAliasType;
   Alias : TPasAliasType;
-  ClassDecl: TPasClassType;
+  MemberDecl: TPasMembersType;
+  ClassLikeDecl : TPasClassType;
   Member: TPasElement;
   Member: TPasElement;
   s: String;
   s: String;
   Buf : TBufType;
   Buf : TBufType;
@@ -1089,41 +1090,48 @@ begin
       if not assigned(Module.InterfaceSection) then
       if not assigned(Module.InterfaceSection) then
         continue;
         continue;
       for j := 0 to Module.InterfaceSection.Classes.Count - 1 do
       for j := 0 to Module.InterfaceSection.Classes.Count - 1 do
-      begin
-        ClassDecl := TPasClassType(Module.InterfaceSection.Classes[j]);
-        Write(ContentFile, CheckImplicitInterfaceLink(ClassDecl.PathName), ' ');
-        if Assigned(ClassDecl.AncestorType) then 
+        begin
+        MemberDecl := TPasClassType(Module.InterfaceSection.Classes[j]);
+        if MemberDecl is TPasClassType then
+          ClassLikeDecl:=MemberDecl as TPasClassType
+        else
+          ClassLikeDecl:=nil;
+        Write(ContentFile, CheckImplicitInterfaceLink(MemberDecl.PathName), ' ');
+        if Assigned(ClassLikeDecl) then
           begin
           begin
-             // simple aliases to class types are coded as "alias(classtype)"
-             Write(ContentFile, CheckImplicitInterfaceLink(ClassDecl.AncestorType.PathName));
-             if ClassDecl.AncestorType is TPasAliasType then
+          if Assigned(ClassLikeDecl.AncestorType) then
+            begin
+            // simple aliases to class types are coded as "alias(classtype)"
+            Write(ContentFile, CheckImplicitInterfaceLink(ClassLikeDecl.AncestorType.PathName));
+            if ClassLikeDecl.AncestorType is TPasAliasType then
                begin
                begin
-                 alias:= TPasAliasType(ClassDecl.AncestorType);
-                 if assigned(alias.desttype) and (alias.desttype is TPasClassType) then
-                   write(ContentFile,'(',alias.desttype.PathName,')');   
+               alias:= TPasAliasType(ClassLikeDecl.AncestorType);
+               if assigned(alias.desttype) and (alias.desttype is TPasClassType) then
+                  write(ContentFile,'(',alias.desttype.PathName,')');
                end;
                end;
-          end
-        else if ClassDecl.ObjKind = okClass then
-          Write(ContentFile, '#rtl.System.TObject')
-        else if ClassDecl.ObjKind = okInterface then
-          Write(ContentFile, '#rtl.System.IUnknown');
-        if ClassDecl.Interfaces.Count>0 then
-          begin
-            for k:=0 to ClassDecl.Interfaces.count-1 do
+            end
+          else if ClassLikeDecl.ObjKind = okClass then
+            Write(ContentFile, '#rtl.System.TObject')
+          else if ClassLikeDecl.ObjKind = okInterface then
+           Write(ContentFile, '#rtl.System.IUnknown');
+          if ClassLikeDecl.Interfaces.Count>0 then
+            begin
+            for k:=0 to ClassLikeDecl.Interfaces.count-1 do
               begin
               begin
-                write(contentfile,',',CheckImplicitInterfaceLink(TPasClassType(ClassDecl.Interfaces[k]).PathName));
-                if TPasElement(ClassDecl.Interfaces[k]) is TPasAliasType then
+                write(contentfile,',',CheckImplicitInterfaceLink(TPasClassType(ClassLikeDecl.Interfaces[k]).PathName));
+                if TPasElement(ClassLikeDecl.Interfaces[k]) is TPasAliasType then
                   begin
                   begin
-                    alias:= TPasAliasType(ClassDecl.Interfaces[k]);
+                    alias:= TPasAliasType(ClassLikeDecl.Interfaces[k]);
                     if assigned(alias.desttype) and (alias.desttype is TPasClassType) then
                     if assigned(alias.desttype) and (alias.desttype is TPasClassType) then
                       write(ContentFile,'(',CheckImplicitInterfaceLink(alias.desttype.PathName),')');   
                       write(ContentFile,'(',CheckImplicitInterfaceLink(alias.desttype.PathName),')');   
                   end;
                   end;
               end;
               end;
+            end;
           end;
           end;
         writeln(contentfile);
         writeln(contentfile);
-        for k := 0 to ClassDecl.Members.Count - 1 do
+        for k := 0 to MemberDecl.Members.Count - 1 do
         begin
         begin
-          Member := TPasElement(ClassDecl.Members[k]);
+          Member := TPasElement(MemberDecl.Members[k]);
           Write(ContentFile, Chr(Ord(Member.Visibility) + Ord('0')));
           Write(ContentFile, Chr(Ord(Member.Visibility) + Ord('0')));
           S:='';
           S:='';
           if Member.ClassType = TPasVariable then
           if Member.ClassType = TPasVariable then