mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 05:39:29 +01:00 
			
		
		
		
	fcl-passrc: parse delphi generic arrays
git-svn-id: trunk@42529 -
This commit is contained in:
		
							parent
							
								
									92f085fdd9
								
							
						
					
					
						commit
						a84eae8c2e
					
				@ -2080,6 +2080,7 @@ type
 | 
				
			|||||||
    function IsArrayExpr(Expr: TParamsExpr): TPasArrayType;
 | 
					    function IsArrayExpr(Expr: TParamsExpr): TPasArrayType;
 | 
				
			||||||
    function IsArrayOperatorAdd(Expr: TPasExpr): boolean;
 | 
					    function IsArrayOperatorAdd(Expr: TPasExpr): boolean;
 | 
				
			||||||
    function IsTypeCast(Params: TParamsExpr): boolean;
 | 
					    function IsTypeCast(Params: TParamsExpr): boolean;
 | 
				
			||||||
 | 
					    function GetTypeParameterCount(aType: TPasGenericType): integer;
 | 
				
			||||||
    function IsInterfaceType(const ResolvedEl: TPasResolverResult;
 | 
					    function IsInterfaceType(const ResolvedEl: TPasResolverResult;
 | 
				
			||||||
      IntfType: TPasClassInterfaceType): boolean; overload;
 | 
					      IntfType: TPasClassInterfaceType): boolean; overload;
 | 
				
			||||||
    function IsInterfaceType(TypeEl: TPasType; IntfType: TPasClassInterfaceType): boolean; overload;
 | 
					    function IsInterfaceType(TypeEl: TPasType; IntfType: TPasClassInterfaceType): boolean; overload;
 | 
				
			||||||
@ -7729,10 +7730,13 @@ begin
 | 
				
			|||||||
    for i:=0 to Members.Count-1 do
 | 
					    for i:=0 to Members.Count-1 do
 | 
				
			||||||
      begin
 | 
					      begin
 | 
				
			||||||
      Decl:=TPasElement(Members[i]);
 | 
					      Decl:=TPasElement(Members[i]);
 | 
				
			||||||
      if (CompareText(Decl.Name,aClass.Name)=0)
 | 
					      if (CompareText(Decl.Name,aClass.Name)<>0)
 | 
				
			||||||
          and (Decl<>aClass) then
 | 
					          or (Decl=aClass) then continue;
 | 
				
			||||||
        RaiseMsg(20180212144132,nDuplicateIdentifier,sDuplicateIdentifier,
 | 
					      if (Decl is TPasGenericType)
 | 
				
			||||||
          [Decl.Name,GetElementSourcePosStr(Decl)],aClass);
 | 
					          and (GetTypeParameterCount(TPasGenericType(Decl))<>GetTypeParameterCount(aClass)) then
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      RaiseMsg(20180212144132,nDuplicateIdentifier,sDuplicateIdentifier,
 | 
				
			||||||
 | 
					        [Decl.Name,GetElementSourcePosStr(Decl)],aClass);
 | 
				
			||||||
      end;
 | 
					      end;
 | 
				
			||||||
    exit;
 | 
					    exit;
 | 
				
			||||||
    end;
 | 
					    end;
 | 
				
			||||||
@ -13971,7 +13975,8 @@ begin
 | 
				
			|||||||
    begin
 | 
					    begin
 | 
				
			||||||
    Item:=TPSSpecializedItem(SpecializedTypes[i]);
 | 
					    Item:=TPSSpecializedItem(SpecializedTypes[i]);
 | 
				
			||||||
    j:=length(Item.Params)-1;
 | 
					    j:=length(Item.Params)-1;
 | 
				
			||||||
    while (j>=0) and (Item.Params[j]=ParamsResolved[j]) do dec(j);
 | 
					    while (j>=0) and IsSameType(Item.Params[j],ParamsResolved[j],prraNone) do
 | 
				
			||||||
 | 
					      dec(j);
 | 
				
			||||||
    if j<0 then
 | 
					    if j<0 then
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    Item:=nil;
 | 
					    Item:=nil;
 | 
				
			||||||
@ -14162,6 +14167,12 @@ begin
 | 
				
			|||||||
      Scope:=TPasGenericScope(PushScope(NewEl,TPasRecordScope));
 | 
					      Scope:=TPasGenericScope(PushScope(NewEl,TPasRecordScope));
 | 
				
			||||||
      Scope.VisibilityContext:=NewEl;
 | 
					      Scope.VisibilityContext:=NewEl;
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					    else if NewEl is TPasClassType then
 | 
				
			||||||
 | 
					      begin
 | 
				
			||||||
 | 
					      //AddClassType();
 | 
				
			||||||
 | 
					      //FinishAncestors();
 | 
				
			||||||
 | 
					        RaiseNotYetImplemented(20190728134934,El);
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      RaiseNotYetImplemented(20190728134933,El);
 | 
					      RaiseNotYetImplemented(20190728134933,El);
 | 
				
			||||||
    Scope.SpecializedFrom:=GenericType;
 | 
					    Scope.SpecializedFrom:=GenericType;
 | 
				
			||||||
@ -23498,6 +23509,13 @@ begin
 | 
				
			|||||||
    exit(true);
 | 
					    exit(true);
 | 
				
			||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function TPasResolver.GetTypeParameterCount(aType: TPasGenericType): integer;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  if aType=nil then exit(0);
 | 
				
			||||||
 | 
					  if aType.GenericTemplateTypes=nil then exit(0);
 | 
				
			||||||
 | 
					  Result:=aType.GenericTemplateTypes.Count;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function TPasResolver.IsInterfaceType(const ResolvedEl: TPasResolverResult;
 | 
					function TPasResolver.IsInterfaceType(const ResolvedEl: TPasResolverResult;
 | 
				
			||||||
  IntfType: TPasClassInterfaceType): boolean;
 | 
					  IntfType: TPasClassInterfaceType): boolean;
 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
 | 
				
			|||||||
@ -88,7 +88,7 @@ const
 | 
				
			|||||||
  nParserDefaultPropertyMustBeArray = 2042;
 | 
					  nParserDefaultPropertyMustBeArray = 2042;
 | 
				
			||||||
  nParserUnknownProcedureType = 2043;
 | 
					  nParserUnknownProcedureType = 2043;
 | 
				
			||||||
  nParserGenericArray1Element = 2044;
 | 
					  nParserGenericArray1Element = 2044;
 | 
				
			||||||
  nParserGenericClassOrArray = 2045;
 | 
					  nParserTypeParamsNotAllowedOnType = 2045;
 | 
				
			||||||
  nParserDuplicateIdentifier = 2046;
 | 
					  nParserDuplicateIdentifier = 2046;
 | 
				
			||||||
  nParserDefaultParameterRequiredFor = 2047;
 | 
					  nParserDefaultParameterRequiredFor = 2047;
 | 
				
			||||||
  nParserOnlyOneVariableCanBeInitialized = 2048;
 | 
					  nParserOnlyOneVariableCanBeInitialized = 2048;
 | 
				
			||||||
@ -149,7 +149,7 @@ resourcestring
 | 
				
			|||||||
  SParserDefaultPropertyMustBeArray = 'The default property must be an array property';
 | 
					  SParserDefaultPropertyMustBeArray = 'The default property must be an array property';
 | 
				
			||||||
  SParserUnknownProcedureType = 'Unknown procedure type "%d"';
 | 
					  SParserUnknownProcedureType = 'Unknown procedure type "%d"';
 | 
				
			||||||
  SParserGenericArray1Element = 'Generic arrays can have only 1 template element';
 | 
					  SParserGenericArray1Element = 'Generic arrays can have only 1 template element';
 | 
				
			||||||
  SParserGenericClassOrArray = 'Generic can only be used with classes or arrays';
 | 
					  SParserTypeParamsNotAllowedOnType = 'Type parameters not allowed on this type';
 | 
				
			||||||
  SParserDuplicateIdentifier = 'Duplicate identifier "%s"';
 | 
					  SParserDuplicateIdentifier = 'Duplicate identifier "%s"';
 | 
				
			||||||
  SParserDefaultParameterRequiredFor = 'Default parameter required for "%s"';
 | 
					  SParserDefaultParameterRequiredFor = 'Default parameter required for "%s"';
 | 
				
			||||||
  SParserOnlyOneVariableCanBeInitialized = 'Only one variable can be initialized';
 | 
					  SParserOnlyOneVariableCanBeInitialized = 'Only one variable can be initialized';
 | 
				
			||||||
@ -331,6 +331,7 @@ type
 | 
				
			|||||||
    procedure ParseExcExpectedIdentifier;
 | 
					    procedure ParseExcExpectedIdentifier;
 | 
				
			||||||
    procedure ParseExcSyntaxError;
 | 
					    procedure ParseExcSyntaxError;
 | 
				
			||||||
    procedure ParseExcTokenError(const Arg: string);
 | 
					    procedure ParseExcTokenError(const Arg: string);
 | 
				
			||||||
 | 
					    procedure ParseTypeParamsNotAllowed;
 | 
				
			||||||
    function OpLevel(t: TToken): Integer;
 | 
					    function OpLevel(t: TToken): Integer;
 | 
				
			||||||
    Function TokenToExprOp (AToken : TToken) : TExprOpCode;
 | 
					    Function TokenToExprOp (AToken : TToken) : TExprOpCode;
 | 
				
			||||||
    function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement): TPasElement;overload;
 | 
					    function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement): TPasElement;overload;
 | 
				
			||||||
@ -408,7 +409,8 @@ type
 | 
				
			|||||||
    function ResolveTypeReference(Name: string; Parent: TPasElement): TPasType;
 | 
					    function ResolveTypeReference(Name: string; Parent: TPasElement): TPasType;
 | 
				
			||||||
    function ParseComplexType(Parent : TPasElement = Nil): TPasType;
 | 
					    function ParseComplexType(Parent : TPasElement = Nil): TPasType;
 | 
				
			||||||
    function ParseTypeDecl(Parent: TPasElement): TPasType;
 | 
					    function ParseTypeDecl(Parent: TPasElement): TPasType;
 | 
				
			||||||
    function ParseType(Parent: TPasElement; const NamePos: TPasSourcePos; const TypeName: String = ''; Full: Boolean = false; GenericArgs: TFPList = nil): TPasType;
 | 
					    function ParseGenericTypeDecl(Parent: TPasElement; AddToParent: boolean): TPasGenericType;
 | 
				
			||||||
 | 
					    function ParseType(Parent: TPasElement; const NamePos: TPasSourcePos; const TypeName: String = ''; Full: Boolean = false): TPasType;
 | 
				
			||||||
    function ParseReferenceToProcedureType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasProcedureType;
 | 
					    function ParseReferenceToProcedureType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasProcedureType;
 | 
				
			||||||
    function ParseProcedureType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String; const PT: TProcType): TPasProcedureType;
 | 
					    function ParseProcedureType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String; const PT: TProcType): TPasProcedureType;
 | 
				
			||||||
    function ParseStringType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasAliasType;
 | 
					    function ParseStringType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasAliasType;
 | 
				
			||||||
@ -422,7 +424,7 @@ type
 | 
				
			|||||||
    function ParseEnumType(Parent: TPasElement; Const NamePos: TPasSourcePos; const TypeName: String): TPasEnumType;
 | 
					    function ParseEnumType(Parent: TPasElement; Const NamePos: TPasSourcePos; const TypeName: String): TPasEnumType;
 | 
				
			||||||
    function ParseSetType(Parent: TPasElement; Const NamePos: TPasSourcePos; const TypeName: String; AIsPacked : Boolean = False): TPasSetType;
 | 
					    function ParseSetType(Parent: TPasElement; Const NamePos: TPasSourcePos; const TypeName: String; AIsPacked : Boolean = False): TPasSetType;
 | 
				
			||||||
    function ParseSpecializeType(Parent: TPasElement; Const TypeName: String): TPasSpecializeType;
 | 
					    function ParseSpecializeType(Parent: TPasElement; Const TypeName: String): TPasSpecializeType;
 | 
				
			||||||
    Function ParseClassDecl(Parent: TPasElement; Const NamePos: TPasSourcePos; Const AClassName: String; AObjKind: TPasObjKind; PackMode : TPackMode= pmNone; GenericArgs: TFPList = nil): TPasType;
 | 
					    Function ParseClassDecl(Parent: TPasElement; Const NamePos: TPasSourcePos; Const AClassName: String; AObjKind: TPasObjKind; PackMode : TPackMode= pmNone): TPasType;
 | 
				
			||||||
    Function ParseProperty(Parent : TPasElement; Const AName : String; AVisibility : TPasMemberVisibility; IsClassField: boolean) : TPasProperty;
 | 
					    Function ParseProperty(Parent : TPasElement; Const AName : String; AVisibility : TPasMemberVisibility; IsClassField: boolean) : TPasProperty;
 | 
				
			||||||
    function ParseRangeType(AParent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String; Full: Boolean = True): TPasRangeType;
 | 
					    function ParseRangeType(AParent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String; Full: Boolean = True): TPasRangeType;
 | 
				
			||||||
    procedure ParseExportDecl(Parent: TPasElement; List: TFPList);
 | 
					    procedure ParseExportDecl(Parent: TPasElement; List: TFPList);
 | 
				
			||||||
@ -1016,6 +1018,11 @@ begin
 | 
				
			|||||||
  ParseExc(nParserExpectTokenError,SParserExpectTokenError,[Arg]);
 | 
					  ParseExc(nParserExpectTokenError,SParserExpectTokenError,[Arg]);
 | 
				
			||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					procedure TPasParser.ParseTypeParamsNotAllowed;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  ParseExc(nParserTypeParamsNotAllowedOnType,sParserTypeParamsNotAllowedOnType,[]);
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
constructor TPasParser.Create(AScanner: TPascalScanner;
 | 
					constructor TPasParser.Create(AScanner: TPascalScanner;
 | 
				
			||||||
  AFileResolver: TBaseFileResolver; AEngine: TPasTreeContainer);
 | 
					  AFileResolver: TBaseFileResolver; AEngine: TPasTreeContainer);
 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
@ -1785,7 +1792,7 @@ begin
 | 
				
			|||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function TPasParser.ParseType(Parent: TPasElement;
 | 
					function TPasParser.ParseType(Parent: TPasElement;
 | 
				
			||||||
  const NamePos: TPasSourcePos; const TypeName: String = ''; Full: Boolean = false; GenericArgs : TFPList = Nil
 | 
					  const NamePos: TPasSourcePos; const TypeName: String; Full: Boolean
 | 
				
			||||||
  ): TPasType;
 | 
					  ): TPasType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Const
 | 
					Const
 | 
				
			||||||
@ -1814,9 +1821,9 @@ begin
 | 
				
			|||||||
      // types only allowed when full
 | 
					      // types only allowed when full
 | 
				
			||||||
      tkObject: Result := ParseClassDecl(Parent, NamePos, TypeName, okObject,PM);
 | 
					      tkObject: Result := ParseClassDecl(Parent, NamePos, TypeName, okObject,PM);
 | 
				
			||||||
      tkDispInterface:
 | 
					      tkDispInterface:
 | 
				
			||||||
        Result := ParseClassDecl(Parent, NamePos, TypeName, okDispInterface);
 | 
					        Result := ParseClassDecl(Parent, NamePos, TypeName, okDispInterface,PM);
 | 
				
			||||||
      tkInterface:
 | 
					      tkInterface:
 | 
				
			||||||
        Result := ParseClassDecl(Parent, NamePos, TypeName, okInterface);
 | 
					        Result := ParseClassDecl(Parent, NamePos, TypeName, okInterface,PM);
 | 
				
			||||||
      tkSpecialize:
 | 
					      tkSpecialize:
 | 
				
			||||||
        Result:=ParseSpecializeType(Parent,TypeName);
 | 
					        Result:=ParseSpecializeType(Parent,TypeName);
 | 
				
			||||||
      tkClass:
 | 
					      tkClass:
 | 
				
			||||||
@ -1833,9 +1840,9 @@ begin
 | 
				
			|||||||
          end;
 | 
					          end;
 | 
				
			||||||
        UngetToken;
 | 
					        UngetToken;
 | 
				
			||||||
        if isHelper then
 | 
					        if isHelper then
 | 
				
			||||||
          Result:=ParseClassDecl(Parent,NamePos,TypeName,okClassHelper,PM, GenericArgs)
 | 
					          Result:=ParseClassDecl(Parent,NamePos,TypeName,okClassHelper, PM)
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
          Result:=ParseClassDecl(Parent, NamePos, TypeName, okClass, PM, GenericArgs);
 | 
					          Result:=ParseClassDecl(Parent, NamePos, TypeName, okClass, PM);
 | 
				
			||||||
        end;
 | 
					        end;
 | 
				
			||||||
      tkType:
 | 
					      tkType:
 | 
				
			||||||
        begin
 | 
					        begin
 | 
				
			||||||
@ -3355,33 +3362,20 @@ var
 | 
				
			|||||||
    Scanner.SetForceCaret(NewBlock=declType);
 | 
					    Scanner.SetForceCaret(NewBlock=declType);
 | 
				
			||||||
  end;
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  procedure InitGenericType(NewEl: TPasGenericType; GenericTemplateTypes: TFPList);
 | 
					 | 
				
			||||||
  begin
 | 
					 | 
				
			||||||
    Declarations.Declarations.Add(NewEl);
 | 
					 | 
				
			||||||
    {$IFDEF CheckPasTreeRefCount}NewEl.ChangeRefId('CreateElement','TPasDeclarations.Children');{$ENDIF}
 | 
					 | 
				
			||||||
    NewEl.SetGenericTemplates(GenericTemplateTypes);
 | 
					 | 
				
			||||||
    Engine.FinishScope(stGenericTypeTemplates,NewEl);
 | 
					 | 
				
			||||||
  end;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var
 | 
					var
 | 
				
			||||||
  ConstEl: TPasConst;
 | 
					  ConstEl: TPasConst;
 | 
				
			||||||
  ResStrEl: TPasResString;
 | 
					  ResStrEl: TPasResString;
 | 
				
			||||||
  TypeEl: TPasType;
 | 
					  TypeEl: TPasType;
 | 
				
			||||||
  ClassEl: TPasClassType;
 | 
					  ClassEl: TPasClassType;
 | 
				
			||||||
  ArrEl : TPasArrayType;
 | 
					 | 
				
			||||||
  List: TFPList;
 | 
					  List: TFPList;
 | 
				
			||||||
  i,j: Integer;
 | 
					  i,j: Integer;
 | 
				
			||||||
  ExpEl: TPasExportSymbol;
 | 
					  ExpEl: TPasExportSymbol;
 | 
				
			||||||
  PropEl : TPasProperty;
 | 
					  PropEl : TPasProperty;
 | 
				
			||||||
  TypeName: String;
 | 
					  PT : TProcType;
 | 
				
			||||||
  PT , ProcType: TProcType;
 | 
					 | 
				
			||||||
  NamePos: TPasSourcePos;
 | 
					 | 
				
			||||||
  ok: Boolean;
 | 
					  ok: Boolean;
 | 
				
			||||||
  Proc: TPasProcedure;
 | 
					  Proc: TPasProcedure;
 | 
				
			||||||
  RecordEl: TPasRecordType;
 | 
					 | 
				
			||||||
  Attr: TPasAttributes;
 | 
					  Attr: TPasAttributes;
 | 
				
			||||||
  CurEl: TPasElement;
 | 
					  CurEl: TPasElement;
 | 
				
			||||||
  ProcTypeEl: TPasProcedureType;
 | 
					 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
  CurBlock := declNone;
 | 
					  CurBlock := declNone;
 | 
				
			||||||
  HadTypeSection:=false;
 | 
					  HadTypeSection:=false;
 | 
				
			||||||
@ -3600,73 +3594,7 @@ begin
 | 
				
			|||||||
      if CurBlock = declType then
 | 
					      if CurBlock = declType then
 | 
				
			||||||
        begin
 | 
					        begin
 | 
				
			||||||
        CheckToken(tkIdentifier);
 | 
					        CheckToken(tkIdentifier);
 | 
				
			||||||
        TypeName := CurTokenString;
 | 
					        ParseGenericTypeDecl(Declarations,true);
 | 
				
			||||||
        NamePos:=CurSourcePos;
 | 
					 | 
				
			||||||
        List:=TFPList.Create;
 | 
					 | 
				
			||||||
        try
 | 
					 | 
				
			||||||
          ReadGenericArguments(List,Declarations);
 | 
					 | 
				
			||||||
          ExpectToken(tkEqual);
 | 
					 | 
				
			||||||
          NextToken;
 | 
					 | 
				
			||||||
          Case CurToken of
 | 
					 | 
				
			||||||
            tkObject,
 | 
					 | 
				
			||||||
            tkClass :
 | 
					 | 
				
			||||||
              begin
 | 
					 | 
				
			||||||
              ClassEl := TPasClassType(CreateElement(TPasClassType,
 | 
					 | 
				
			||||||
                TypeName, Declarations, NamePos));
 | 
					 | 
				
			||||||
              Declarations.Classes.Add(ClassEl);
 | 
					 | 
				
			||||||
              InitGenericType(ClassEl,List);
 | 
					 | 
				
			||||||
              NextToken;
 | 
					 | 
				
			||||||
              DoParseClassType(ClassEl);
 | 
					 | 
				
			||||||
              CheckHint(ClassEl,True);
 | 
					 | 
				
			||||||
              Engine.FinishScope(stTypeDef,ClassEl);
 | 
					 | 
				
			||||||
              end;
 | 
					 | 
				
			||||||
           tkRecord:
 | 
					 | 
				
			||||||
             begin
 | 
					 | 
				
			||||||
             RecordEl := TPasRecordType(CreateElement(TPasRecordType,
 | 
					 | 
				
			||||||
               TypeName, Declarations, NamePos));
 | 
					 | 
				
			||||||
             Declarations.Classes.Add(RecordEl);
 | 
					 | 
				
			||||||
             InitGenericType(RecordEl,List);
 | 
					 | 
				
			||||||
             NextToken;
 | 
					 | 
				
			||||||
             ParseRecordMembers(RecordEl,tkend,
 | 
					 | 
				
			||||||
                              (msAdvancedRecords in Scanner.CurrentModeSwitches)
 | 
					 | 
				
			||||||
                              and not (Declarations is TProcedureBody)
 | 
					 | 
				
			||||||
                              and (RecordEl.Name<>''));
 | 
					 | 
				
			||||||
             CheckHint(RecordEl,True);
 | 
					 | 
				
			||||||
             Engine.FinishScope(stTypeDef,RecordEl);
 | 
					 | 
				
			||||||
             end;
 | 
					 | 
				
			||||||
           tkArray:
 | 
					 | 
				
			||||||
             begin
 | 
					 | 
				
			||||||
             ArrEl := TPasArrayType(CreateElement(TPasArrayType, TypeName, Declarations, NamePos));
 | 
					 | 
				
			||||||
             Declarations.Types.Add(ArrEl);
 | 
					 | 
				
			||||||
             InitGenericType(ArrEl,List);
 | 
					 | 
				
			||||||
             DoParseArrayType(ArrEl);
 | 
					 | 
				
			||||||
             CheckHint(ArrEl,True);
 | 
					 | 
				
			||||||
             Engine.FinishScope(stTypeDef,ArrEl);
 | 
					 | 
				
			||||||
             end;
 | 
					 | 
				
			||||||
          tkprocedure,tkfunction:
 | 
					 | 
				
			||||||
            begin
 | 
					 | 
				
			||||||
            if CurToken=tkFunction then
 | 
					 | 
				
			||||||
              begin
 | 
					 | 
				
			||||||
              ProcTypeEl := CreateFunctionType(TypeName, 'Result', Declarations, False, NamePos);
 | 
					 | 
				
			||||||
              ProcType:=ptFunction;
 | 
					 | 
				
			||||||
              end
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
              begin
 | 
					 | 
				
			||||||
              ProcTypeEl := TPasProcedureType(CreateElement(TPasProcedureType, TypeName, Declarations, NamePos));
 | 
					 | 
				
			||||||
              ProcType:=ptProcedure;
 | 
					 | 
				
			||||||
              end;
 | 
					 | 
				
			||||||
            Declarations.Functions.Add(ProcTypeEl);
 | 
					 | 
				
			||||||
            InitGenericType(ProcTypeEl,List);
 | 
					 | 
				
			||||||
            ParseProcedureOrFunction(ProcTypeEl, ProcTypeEl, ProcType, True);
 | 
					 | 
				
			||||||
            end;
 | 
					 | 
				
			||||||
          else
 | 
					 | 
				
			||||||
            ParseExc(nParserGenericClassOrArray,SParserGenericClassOrArray);
 | 
					 | 
				
			||||||
          end;
 | 
					 | 
				
			||||||
        finally
 | 
					 | 
				
			||||||
          for i:=0 to List.Count-1 do
 | 
					 | 
				
			||||||
            TPasElement(List[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
 | 
					 | 
				
			||||||
          List.Free;
 | 
					 | 
				
			||||||
        end;
 | 
					 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      else if CurBlock = declNone then
 | 
					      else if CurBlock = declNone then
 | 
				
			||||||
        begin
 | 
					        begin
 | 
				
			||||||
@ -4339,36 +4267,140 @@ begin
 | 
				
			|||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function TPasParser.ParseTypeDecl(Parent: TPasElement): TPasType;
 | 
					function TPasParser.ParseTypeDecl(Parent: TPasElement): TPasType;
 | 
				
			||||||
 | 
					var
 | 
				
			||||||
 | 
					  TypeName: String;
 | 
				
			||||||
 | 
					  NamePos: TPasSourcePos;
 | 
				
			||||||
 | 
					  OldForceCaret , IsDelphiGenericType: Boolean;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  OldForceCaret:=Scanner.SetForceCaret(True);
 | 
				
			||||||
 | 
					  try
 | 
				
			||||||
 | 
					    IsDelphiGenericType:=false;
 | 
				
			||||||
 | 
					    if (msDelphi in CurrentModeswitches) then
 | 
				
			||||||
 | 
					      begin
 | 
				
			||||||
 | 
					      NextToken;
 | 
				
			||||||
 | 
					      IsDelphiGenericType:=CurToken=tkLessThan;
 | 
				
			||||||
 | 
					      UngetToken;
 | 
				
			||||||
 | 
					      end;
 | 
				
			||||||
 | 
					    if IsDelphiGenericType then
 | 
				
			||||||
 | 
					      Result:=ParseGenericTypeDecl(Parent,false)
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      begin
 | 
				
			||||||
 | 
					      TypeName := CurTokenString;
 | 
				
			||||||
 | 
					      NamePos:=CurSourcePos;
 | 
				
			||||||
 | 
					      ExpectToken(tkEqual);
 | 
				
			||||||
 | 
					      Result:=ParseType(Parent,NamePos,TypeName,True);
 | 
				
			||||||
 | 
					      end;
 | 
				
			||||||
 | 
					  finally
 | 
				
			||||||
 | 
					    Scanner.SetForceCaret(OldForceCaret);
 | 
				
			||||||
 | 
					  end;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function TPasParser.ParseGenericTypeDecl(Parent: TPasElement;
 | 
				
			||||||
 | 
					  AddToParent: boolean): TPasGenericType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  procedure InitGenericType(NewEl: TPasGenericType; GenericTemplateTypes: TFPList);
 | 
				
			||||||
 | 
					  begin
 | 
				
			||||||
 | 
					    ParseGenericTypeDecl:=NewEl;
 | 
				
			||||||
 | 
					    if AddToParent then
 | 
				
			||||||
 | 
					      begin
 | 
				
			||||||
 | 
					      if Parent is TPasDeclarations then
 | 
				
			||||||
 | 
					        begin
 | 
				
			||||||
 | 
					        TPasDeclarations(Parent).Declarations.Add(NewEl);
 | 
				
			||||||
 | 
					        {$IFDEF CheckPasTreeRefCount}NewEl.ChangeRefId('CreateElement','TPasDeclarations.Children');{$ENDIF}
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      else if Parent is TPasMembersType then
 | 
				
			||||||
 | 
					        begin
 | 
				
			||||||
 | 
					        TPasMembersType(Parent).Members.Add(NewEl);
 | 
				
			||||||
 | 
					        {$IFDEF CheckPasTreeRefCount}NewEl.ChangeRefId('CreateElement','TPasMembersType.Members');{$ENDIF}
 | 
				
			||||||
 | 
					        end;
 | 
				
			||||||
 | 
					      end;
 | 
				
			||||||
 | 
					    NewEl.SetGenericTemplates(GenericTemplateTypes);
 | 
				
			||||||
 | 
					    Engine.FinishScope(stGenericTypeTemplates,NewEl);
 | 
				
			||||||
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var
 | 
					var
 | 
				
			||||||
  TypeName: String;
 | 
					  TypeName: String;
 | 
				
			||||||
  NamePos: TPasSourcePos;
 | 
					  NamePos: TPasSourcePos;
 | 
				
			||||||
  OldForceCaret : Boolean;
 | 
					  List: TFPList;
 | 
				
			||||||
  List : TFPList;
 | 
					  ClassEl: TPasClassType;
 | 
				
			||||||
 | 
					  RecordEl: TPasRecordType;
 | 
				
			||||||
 | 
					  ArrEl: TPasArrayType;
 | 
				
			||||||
 | 
					  ProcTypeEl: TPasProcedureType;
 | 
				
			||||||
 | 
					  ProcType: TProcType;
 | 
				
			||||||
  i: Integer;
 | 
					  i: Integer;
 | 
				
			||||||
 | 
					 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
 | 
					  Result:=nil;
 | 
				
			||||||
  TypeName := CurTokenString;
 | 
					  TypeName := CurTokenString;
 | 
				
			||||||
  NamePos:=CurSourcePos;
 | 
					  NamePos := CurSourcePos;
 | 
				
			||||||
  List:=Nil;
 | 
					  List:=TFPList.Create;
 | 
				
			||||||
  OldForceCaret:=Scanner.SetForceCaret(True);
 | 
					 | 
				
			||||||
  try
 | 
					  try
 | 
				
			||||||
    NextToken;
 | 
					    ReadGenericArguments(List,Parent);
 | 
				
			||||||
    if (CurToken=tkLessThan) and (msDelphi in CurrentModeswitches) then
 | 
					 | 
				
			||||||
      List:=TFPList.Create;
 | 
					 | 
				
			||||||
    UnGetToken; // ReadGenericArguments starts at <
 | 
					 | 
				
			||||||
    if Assigned(List) then
 | 
					 | 
				
			||||||
      ReadGenericArguments(List,Parent);
 | 
					 | 
				
			||||||
    ExpectToken(tkEqual);
 | 
					    ExpectToken(tkEqual);
 | 
				
			||||||
    Result:=ParseType(Parent,NamePos,TypeName,True,List);
 | 
					    NextToken;
 | 
				
			||||||
  finally
 | 
					    Case CurToken of
 | 
				
			||||||
    Scanner.SetForceCaret(OldForceCaret);
 | 
					      tkObject,
 | 
				
			||||||
    if List<>nil then
 | 
					      tkClass :
 | 
				
			||||||
 | 
					        begin
 | 
				
			||||||
 | 
					        ClassEl := TPasClassType(CreateElement(TPasClassType,
 | 
				
			||||||
 | 
					          TypeName, Parent, NamePos));
 | 
				
			||||||
 | 
					        if AddToParent and (Parent is TPasDeclarations) then
 | 
				
			||||||
 | 
					          TPasDeclarations(Parent).Classes.Add(ClassEl);
 | 
				
			||||||
 | 
					        InitGenericType(ClassEl,List);
 | 
				
			||||||
 | 
					        NextToken;
 | 
				
			||||||
 | 
					        DoParseClassType(ClassEl);
 | 
				
			||||||
 | 
					        CheckHint(ClassEl,True);
 | 
				
			||||||
 | 
					        Engine.FinishScope(stTypeDef,ClassEl);
 | 
				
			||||||
 | 
					        end;
 | 
				
			||||||
 | 
					     tkRecord:
 | 
				
			||||||
 | 
					       begin
 | 
				
			||||||
 | 
					       RecordEl := TPasRecordType(CreateElement(TPasRecordType,
 | 
				
			||||||
 | 
					         TypeName, Parent, NamePos));
 | 
				
			||||||
 | 
					       if AddToParent and (Parent is TPasDeclarations) then
 | 
				
			||||||
 | 
					         TPasDeclarations(Parent).Classes.Add(RecordEl);
 | 
				
			||||||
 | 
					       InitGenericType(RecordEl,List);
 | 
				
			||||||
 | 
					       NextToken;
 | 
				
			||||||
 | 
					       ParseRecordMembers(RecordEl,tkend,
 | 
				
			||||||
 | 
					                        (msAdvancedRecords in Scanner.CurrentModeSwitches)
 | 
				
			||||||
 | 
					                        and not (Parent is TProcedureBody)
 | 
				
			||||||
 | 
					                        and (RecordEl.Name<>''));
 | 
				
			||||||
 | 
					       CheckHint(RecordEl,True);
 | 
				
			||||||
 | 
					       Engine.FinishScope(stTypeDef,RecordEl);
 | 
				
			||||||
 | 
					       end;
 | 
				
			||||||
 | 
					     tkArray:
 | 
				
			||||||
 | 
					       begin
 | 
				
			||||||
 | 
					       ArrEl := TPasArrayType(CreateElement(TPasArrayType, TypeName, Parent, NamePos));
 | 
				
			||||||
 | 
					       if AddToParent and (Parent is TPasDeclarations) then
 | 
				
			||||||
 | 
					         TPasDeclarations(Parent).Types.Add(ArrEl);
 | 
				
			||||||
 | 
					       InitGenericType(ArrEl,List);
 | 
				
			||||||
 | 
					       DoParseArrayType(ArrEl);
 | 
				
			||||||
 | 
					       CheckHint(ArrEl,True);
 | 
				
			||||||
 | 
					       Engine.FinishScope(stTypeDef,ArrEl);
 | 
				
			||||||
 | 
					       end;
 | 
				
			||||||
 | 
					    tkprocedure,tkfunction:
 | 
				
			||||||
      begin
 | 
					      begin
 | 
				
			||||||
      for i:=0 to List.Count-1 do
 | 
					      if CurToken=tkFunction then
 | 
				
			||||||
        TPasElement(List[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
 | 
					        begin
 | 
				
			||||||
      List.Free;
 | 
					        ProcTypeEl := CreateFunctionType(TypeName, 'Result', Parent, False, NamePos);
 | 
				
			||||||
 | 
					        ProcType:=ptFunction;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        begin
 | 
				
			||||||
 | 
					        ProcTypeEl := TPasProcedureType(CreateElement(TPasProcedureType,
 | 
				
			||||||
 | 
					                                                    TypeName, Parent, NamePos));
 | 
				
			||||||
 | 
					        ProcType:=ptProcedure;
 | 
				
			||||||
 | 
					        end;
 | 
				
			||||||
 | 
					      if AddToParent and (Parent is TPasDeclarations) then
 | 
				
			||||||
 | 
					        TPasDeclarations(Parent).Functions.Add(ProcTypeEl);
 | 
				
			||||||
 | 
					      InitGenericType(ProcTypeEl,List);
 | 
				
			||||||
 | 
					      ParseProcedureOrFunction(ProcTypeEl, ProcTypeEl, ProcType, True);
 | 
				
			||||||
      end;
 | 
					      end;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      ParseTypeParamsNotAllowed;
 | 
				
			||||||
 | 
					    end;
 | 
				
			||||||
 | 
					  finally
 | 
				
			||||||
 | 
					    for i:=0 to List.Count-1 do
 | 
				
			||||||
 | 
					      TPasElement(List[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
 | 
				
			||||||
 | 
					    List.Free;
 | 
				
			||||||
  end;
 | 
					  end;
 | 
				
			||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -7204,7 +7236,7 @@ end;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function TPasParser.ParseClassDecl(Parent: TPasElement;
 | 
					function TPasParser.ParseClassDecl(Parent: TPasElement;
 | 
				
			||||||
  const NamePos: TPasSourcePos; const AClassName: String;
 | 
					  const NamePos: TPasSourcePos; const AClassName: String;
 | 
				
			||||||
  AObjKind: TPasObjKind; PackMode: TPackMode; GenericArgs: TFPList): TPasType;
 | 
					  AObjKind: TPasObjKind; PackMode: TPackMode): TPasType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Var
 | 
					Var
 | 
				
			||||||
  ok: Boolean;
 | 
					  ok: Boolean;
 | 
				
			||||||
@ -7267,7 +7299,7 @@ begin
 | 
				
			|||||||
    if AExternalName<>'' then
 | 
					    if AExternalName<>'' then
 | 
				
			||||||
      PCT.ExternalName:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalName,'''');
 | 
					      PCT.ExternalName:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalName,'''');
 | 
				
			||||||
    if AExternalNameSpace<>'' then
 | 
					    if AExternalNameSpace<>'' then
 | 
				
			||||||
    PCT.ExternalNameSpace:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalNameSpace,'''');
 | 
					      PCT.ExternalNameSpace:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalNameSpace,'''');
 | 
				
			||||||
    PCT.ObjKind := AObjKind;
 | 
					    PCT.ObjKind := AObjKind;
 | 
				
			||||||
    PCT.PackMode:=PackMode;
 | 
					    PCT.PackMode:=PackMode;
 | 
				
			||||||
    if AObjKind=okInterface then
 | 
					    if AObjKind=okInterface then
 | 
				
			||||||
@ -7275,8 +7307,6 @@ begin
 | 
				
			|||||||
      if SameText(Scanner.CurrentValueSwitch[vsInterfaces],'CORBA') then
 | 
					      if SameText(Scanner.CurrentValueSwitch[vsInterfaces],'CORBA') then
 | 
				
			||||||
        PCT.InterfaceType:=citCorba;
 | 
					        PCT.InterfaceType:=citCorba;
 | 
				
			||||||
      end;
 | 
					      end;
 | 
				
			||||||
    if Assigned(GenericArgs) then
 | 
					 | 
				
			||||||
      PCT.SetGenericTemplates(GenericArgs);
 | 
					 | 
				
			||||||
    DoParseClassType(PCT);
 | 
					    DoParseClassType(PCT);
 | 
				
			||||||
    Engine.FinishScope(stTypeDef,Result);
 | 
					    Engine.FinishScope(stTypeDef,Result);
 | 
				
			||||||
    ok:=true;
 | 
					    ok:=true;
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@ Type
 | 
				
			|||||||
    Procedure TestObjectGenerics;
 | 
					    Procedure TestObjectGenerics;
 | 
				
			||||||
    Procedure TestRecordGenerics;
 | 
					    Procedure TestRecordGenerics;
 | 
				
			||||||
    Procedure TestArrayGenerics;
 | 
					    Procedure TestArrayGenerics;
 | 
				
			||||||
 | 
					    Procedure TestArrayGenericsDelphi;
 | 
				
			||||||
    Procedure TestProcTypeGenerics;
 | 
					    Procedure TestProcTypeGenerics;
 | 
				
			||||||
    Procedure TestGenericConstraint;
 | 
					    Procedure TestGenericConstraint;
 | 
				
			||||||
    Procedure TestGenericInterfaceConstraint;
 | 
					    Procedure TestGenericInterfaceConstraint;
 | 
				
			||||||
@ -67,6 +68,17 @@ begin
 | 
				
			|||||||
  ParseDeclarations;
 | 
					  ParseDeclarations;
 | 
				
			||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					procedure TTestGenerics.TestArrayGenericsDelphi;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  Add([
 | 
				
			||||||
 | 
					    '{$mode delphi}',
 | 
				
			||||||
 | 
					    'Type',
 | 
				
			||||||
 | 
					    '  TSome<T> = array of T;',
 | 
				
			||||||
 | 
					    '  TStatic<R,T> = array[R] of T;',
 | 
				
			||||||
 | 
					    '']);
 | 
				
			||||||
 | 
					  ParseDeclarations;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
procedure TTestGenerics.TestProcTypeGenerics;
 | 
					procedure TTestGenerics.TestProcTypeGenerics;
 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
  Add([
 | 
					  Add([
 | 
				
			||||||
 | 
				
			|||||||
@ -29,11 +29,15 @@ type
 | 
				
			|||||||
    // ToDo: constraint T:Unit2.TGen<word>
 | 
					    // ToDo: constraint T:Unit2.TGen<word>
 | 
				
			||||||
    procedure TestGen_GenericNotFoundFail;
 | 
					    procedure TestGen_GenericNotFoundFail;
 | 
				
			||||||
    procedure TestGen_RecordLocalNameDuplicateFail;
 | 
					    procedure TestGen_RecordLocalNameDuplicateFail;
 | 
				
			||||||
    procedure TestGen_Record; // ToDo
 | 
					    procedure TestGen_Record;
 | 
				
			||||||
    // ToDo: type TBird<T> = record end; var b: TBird<word>.T; fail
 | 
					    //procedure TestGen_RecordDelphi;
 | 
				
			||||||
    // ToDo: enums within generic
 | 
					    // ToDo: enums within generic
 | 
				
			||||||
 | 
					    procedure TestGen_Class;
 | 
				
			||||||
 | 
					    //procedure TestGen_ClassDelphi;
 | 
				
			||||||
    // ToDo: generic class
 | 
					    // ToDo: generic class
 | 
				
			||||||
    // ToDo: generic class forward
 | 
					    // ToDo: generic class forward (constraints must be repeated)
 | 
				
			||||||
 | 
					    // ToDo: generic class forward  constraints mismatch fail
 | 
				
			||||||
 | 
					    // ToDo: generic class overload
 | 
				
			||||||
    // ToDo: ancestor cycle: TBird<T> = class(TBird<word>) fail
 | 
					    // ToDo: ancestor cycle: TBird<T> = class(TBird<word>) fail
 | 
				
			||||||
    // ToDo: class-of
 | 
					    // ToDo: class-of
 | 
				
			||||||
    // ToDo: UnitA.impl uses UnitB.intf uses UnitA.intf, UnitB has specialize of UnitA
 | 
					    // ToDo: UnitA.impl uses UnitB.intf uses UnitA.intf, UnitB has specialize of UnitA
 | 
				
			||||||
@ -179,6 +183,26 @@ begin
 | 
				
			|||||||
  ParseProgram;
 | 
					  ParseProgram;
 | 
				
			||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					procedure TTestResolveGenerics.TestGen_Class;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  exit;
 | 
				
			||||||
 | 
					  StartProgram(false);
 | 
				
			||||||
 | 
					  Add([
 | 
				
			||||||
 | 
					  '{$mode objfpc}',
 | 
				
			||||||
 | 
					  'type',
 | 
				
			||||||
 | 
					  '  {#Typ}T = word;',
 | 
				
			||||||
 | 
					  '  generic TBird<{#Templ}T> = class',
 | 
				
			||||||
 | 
					  '    {=Templ}v: T;',
 | 
				
			||||||
 | 
					  '  end;',
 | 
				
			||||||
 | 
					  'var',
 | 
				
			||||||
 | 
					  '  b: specialize TBird<word>;',
 | 
				
			||||||
 | 
					  '  {=Typ}w: T;',
 | 
				
			||||||
 | 
					  'begin',
 | 
				
			||||||
 | 
					  '  b.v:=w;',
 | 
				
			||||||
 | 
					  '']);
 | 
				
			||||||
 | 
					  ParseProgram;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
initialization
 | 
					initialization
 | 
				
			||||||
  RegisterTests([TTestResolveGenerics]);
 | 
					  RegisterTests([TTestResolveGenerics]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user