mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-03 18:57:11 +01:00
* Support for functions in records
git-svn-id: trunk@29553 -
This commit is contained in:
parent
817555cd6e
commit
a842569bf1
@ -63,7 +63,7 @@ resourcestring
|
|||||||
SParserNoConstructorAllowed = 'Constructors or Destructors are not allowed in Interfaces or Record helpers';
|
SParserNoConstructorAllowed = 'Constructors or Destructors are not allowed in Interfaces or Record helpers';
|
||||||
SParserNoFieldsAllowed = 'Fields are not allowed in Interfaces';
|
SParserNoFieldsAllowed = 'Fields are not allowed in Interfaces';
|
||||||
SParserInvalidRecordVisibility = 'Records can only have public and (strict) private as visibility specifiers';
|
SParserInvalidRecordVisibility = 'Records can only have public and (strict) private as visibility specifiers';
|
||||||
|
SErrRecordMethodsNotAllowed = 'Record methods not allowed at this location.';
|
||||||
type
|
type
|
||||||
TPasParserLogHandler = Procedure (Sender : TObject; Const Msg : String) of object;
|
TPasParserLogHandler = Procedure (Sender : TObject; Const Msg : String) of object;
|
||||||
TPParserLogEvent = (pleInterface,pleImplementation);
|
TPParserLogEvent = (pleInterface,pleImplementation);
|
||||||
@ -150,7 +150,7 @@ type
|
|||||||
Procedure DoLog(Const Msg : String; SkipSourceInfo : Boolean = False);overload;
|
Procedure DoLog(Const Msg : String; SkipSourceInfo : Boolean = False);overload;
|
||||||
Procedure DoLog(Const Fmt : String; Args : Array of const;SkipSourceInfo : Boolean = False);overload;
|
Procedure DoLog(Const Fmt : String; Args : Array of const;SkipSourceInfo : Boolean = False);overload;
|
||||||
function GetProcTypeFromToken(tk: TToken; IsClass: Boolean=False ): TProcType;
|
function GetProcTypeFromToken(tk: TToken; IsClass: Boolean=False ): TProcType;
|
||||||
procedure ParseRecordFieldList(ARec: TPasRecordType; AEndToken: TToken);
|
procedure ParseRecordFieldList(ARec: TPasRecordType; AEndToken: TToken; AllowMethods : Boolean);
|
||||||
procedure ParseRecordVariantParts(ARec: TPasRecordType; AEndToken: TToken);
|
procedure ParseRecordVariantParts(ARec: TPasRecordType; AEndToken: TToken);
|
||||||
function GetProcedureClass(ProcType : TProcType): TPTreeElement;
|
function GetProcedureClass(ProcType : TProcType): TPTreeElement;
|
||||||
procedure ParseClassFields(AType: TPasClassType; const AVisibility: TPasMemberVisibility; IsClassField : Boolean);
|
procedure ParseClassFields(AType: TPasClassType; const AVisibility: TPasMemberVisibility; IsClassField : Boolean);
|
||||||
@ -3587,7 +3587,7 @@ begin
|
|||||||
NextToken;
|
NextToken;
|
||||||
M:=TPasRecordType(CreateElement(TPasRecordType,'',V));
|
M:=TPasRecordType(CreateElement(TPasRecordType,'',V));
|
||||||
V.Members:=M;
|
V.Members:=M;
|
||||||
ParseRecordFieldList(M,tkBraceClose);
|
ParseRecordFieldList(M,tkBraceClose,False);
|
||||||
// Current token is closing ), so we eat that
|
// Current token is closing ), so we eat that
|
||||||
NextToken;
|
NextToken;
|
||||||
// If there is a semicolon, we eat that too.
|
// If there is a semicolon, we eat that too.
|
||||||
@ -3612,16 +3612,31 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// Starts on first token after Record or (. Ends on AEndToken
|
// Starts on first token after Record or (. Ends on AEndToken
|
||||||
Procedure TPasParser.ParseRecordFieldList(ARec : TPasRecordType; AEndToken : TToken);
|
Procedure TPasParser.ParseRecordFieldList(ARec : TPasRecordType; AEndToken : TToken; AllowMethods : Boolean);
|
||||||
|
|
||||||
Var
|
Var
|
||||||
VN : String;
|
VN : String;
|
||||||
v : TPasmemberVisibility;
|
v : TPasmemberVisibility;
|
||||||
|
Proc: TPasProcedure;
|
||||||
|
ProcType: TProcType;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
v:=visPublic;
|
||||||
while CurToken<>AEndToken do
|
while CurToken<>AEndToken do
|
||||||
begin
|
begin
|
||||||
Case CurToken of
|
Case CurToken of
|
||||||
|
tkProcedure,
|
||||||
|
tkFunction :
|
||||||
|
begin
|
||||||
|
if Not AllowMethods then
|
||||||
|
ParseExc(SErrRecordMethodsNotAllowed);
|
||||||
|
ProcType:=GetProcTypeFromtoken(CurToken,False);
|
||||||
|
Proc:=ParseProcedureOrFunctionDecl(ARec,ProcType,v);
|
||||||
|
if Proc.Parent is TPasOverloadedProc then
|
||||||
|
TPasOverloadedProc(Proc.Parent).Overloads.Add(Proc)
|
||||||
|
else
|
||||||
|
ARec.Members.Add(Proc);
|
||||||
|
end;
|
||||||
tkIdentifier :
|
tkIdentifier :
|
||||||
begin
|
begin
|
||||||
v:=visDefault;
|
v:=visDefault;
|
||||||
@ -3669,7 +3684,7 @@ begin
|
|||||||
try
|
try
|
||||||
Result.PackMode:=PackMode;
|
Result.PackMode:=PackMode;
|
||||||
NextToken;
|
NextToken;
|
||||||
ParseRecordFieldList(Result,tkEnd);
|
ParseRecordFieldList(Result,tkEnd,true);
|
||||||
except
|
except
|
||||||
FreeAndNil(Result);
|
FreeAndNil(Result);
|
||||||
Raise;
|
Raise;
|
||||||
|
|||||||
@ -160,12 +160,14 @@ type
|
|||||||
procedure AssertVariantSelector(AName, AType: string);
|
procedure AssertVariantSelector(AName, AType: string);
|
||||||
procedure AssertField1(Hints: TPasMemberHints);
|
procedure AssertField1(Hints: TPasMemberHints);
|
||||||
procedure AssertField2(Hints: TPasMemberHints);
|
procedure AssertField2(Hints: TPasMemberHints);
|
||||||
|
procedure AssertMethod2(Hints: TPasMemberHints);
|
||||||
procedure AssertVariant1(Hints: TPasMemberHints);
|
procedure AssertVariant1(Hints: TPasMemberHints);
|
||||||
procedure AssertVariant1(Hints: TPasMemberHints; VariantLabels : Array of string);
|
procedure AssertVariant1(Hints: TPasMemberHints; VariantLabels : Array of string);
|
||||||
procedure AssertVariant2(Hints: TPasMemberHints);
|
procedure AssertVariant2(Hints: TPasMemberHints);
|
||||||
procedure AssertVariant2(Hints: TPasMemberHints; VariantLabels : Array of string);
|
procedure AssertVariant2(Hints: TPasMemberHints; VariantLabels : Array of string);
|
||||||
procedure AssertOneIntegerField(Hints: TPasMemberHints);
|
procedure AssertOneIntegerField(Hints: TPasMemberHints);
|
||||||
procedure AssertTwoIntegerFields(Hints1, Hints2: TPasMemberHints);
|
procedure AssertTwoIntegerFields(Hints1, Hints2: TPasMemberHints);
|
||||||
|
procedure AssertIntegerFieldAndMethod(Hints1, Hints2: TPasMemberHints);
|
||||||
procedure AssertRecordField(AIndex: Integer;Hints: TPasMemberHints);
|
procedure AssertRecordField(AIndex: Integer;Hints: TPasMemberHints);
|
||||||
procedure AssertRecordVariant(AIndex: Integer;Hints: TPasMemberHints; VariantLabels : Array of string);
|
procedure AssertRecordVariant(AIndex: Integer;Hints: TPasMemberHints; VariantLabels : Array of string);
|
||||||
Procedure AssertRecordVariantVariant(AIndex: Integer;Const AFieldName,ATypeName: string;Hints: TPasMemberHints; VariantLabels : Array of string);
|
Procedure AssertRecordVariantVariant(AIndex: Integer;Const AFieldName,ATypeName: string;Hints: TPasMemberHints; VariantLabels : Array of string);
|
||||||
@ -228,6 +230,8 @@ type
|
|||||||
Procedure TestTwoDeprecatedFieldsCombined;
|
Procedure TestTwoDeprecatedFieldsCombined;
|
||||||
Procedure TestTwoDeprecatedFieldsCombinedDeprecated;
|
Procedure TestTwoDeprecatedFieldsCombinedDeprecated;
|
||||||
Procedure TestTwoDeprecatedFieldsCombinedPlatform;
|
Procedure TestTwoDeprecatedFieldsCombinedPlatform;
|
||||||
|
Procedure TestFieldAndMethod;
|
||||||
|
Procedure TestFieldAnd2Methods;
|
||||||
Procedure TestNested;
|
Procedure TestNested;
|
||||||
Procedure TestNestedDeprecated;
|
Procedure TestNestedDeprecated;
|
||||||
Procedure TestNestedPlatform;
|
Procedure TestNestedPlatform;
|
||||||
@ -1434,6 +1438,18 @@ begin
|
|||||||
AssertTrue('Field 2 hints match',Field2.Hints=Hints)
|
AssertTrue('Field 2 hints match',Field2.Hints=Hints)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestRecordTypeParser.AssertMethod2(Hints: TPasMemberHints);
|
||||||
|
|
||||||
|
Var
|
||||||
|
P : TPasProcedure;
|
||||||
|
|
||||||
|
begin
|
||||||
|
AssertEquals('Member 2 type',TPasProcedure,TObject(TheRecord.Members[1]).ClassType);
|
||||||
|
P:=TPasProcedure(TheRecord.Members[1]);
|
||||||
|
AssertEquals('Method name','dosomething2',P.Name);
|
||||||
|
AssertTrue('Method hints match',P.Hints=Hints)
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestRecordTypeParser.AssertOneIntegerField(Hints : TPasMemberHints);
|
procedure TTestRecordTypeParser.AssertOneIntegerField(Hints : TPasMemberHints);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -1449,6 +1465,14 @@ begin
|
|||||||
AssertField2(Hints2);
|
AssertField2(Hints2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestRecordTypeParser.AssertIntegerFieldAndMethod(Hints1,
|
||||||
|
Hints2: TPasMemberHints);
|
||||||
|
begin
|
||||||
|
AssertEquals('Two members',2,TheRecord.Members.Count);
|
||||||
|
AssertField1(Hints1);
|
||||||
|
AssertMethod2(Hints2);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestRecordTypeParser.AssertRecordField(AIndex: Integer;
|
procedure TTestRecordTypeParser.AssertRecordField(AIndex: Integer;
|
||||||
Hints: TPasMemberHints);
|
Hints: TPasMemberHints);
|
||||||
|
|
||||||
@ -1771,6 +1795,29 @@ begin
|
|||||||
AssertTwoIntegerFields([hdeprecated],[hdeprecated]);
|
AssertTwoIntegerFields([hdeprecated],[hdeprecated]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestRecordTypeParser.TestFieldAndMethod;
|
||||||
|
begin
|
||||||
|
TestFields(['x : integer;','procedure dosomething2;'],'',False);
|
||||||
|
AssertIntegerFieldAndMethod([],[]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestRecordTypeParser.TestFieldAnd2Methods;
|
||||||
|
Var
|
||||||
|
P : TPasFunction;
|
||||||
|
|
||||||
|
begin
|
||||||
|
TestFields(['x : integer;','procedure dosomething2;','function dosomething3 : Integer;'],'',False);
|
||||||
|
AssertEquals('Member count',3,TheRecord.Members.Count);
|
||||||
|
AssertField1([]);
|
||||||
|
AssertMethod2([]);
|
||||||
|
AssertEquals('Member 3 type',TPasFunction,TObject(TheRecord.Members[2]).ClassType);
|
||||||
|
P:=TPasFunction(TheRecord.Members[2]);
|
||||||
|
AssertEquals('Method 2 name','dosomething3',P.Name);
|
||||||
|
AssertTrue('Method 2 hints match',[]=P.Hints);
|
||||||
|
// Standard type
|
||||||
|
AssertEquals('Method 2 result type','Integer', P.FuncType.ResultEl.ResultType.Name);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestRecordTypeParser.TestNested;
|
procedure TTestRecordTypeParser.TestNested;
|
||||||
begin
|
begin
|
||||||
TestFields(['x : integer;','y : record',' z : integer;','end'],'',False);
|
TestFields(['x : integer;','y : record',' z : integer;','end'],'',False);
|
||||||
|
|||||||
@ -34,13 +34,10 @@
|
|||||||
<LaunchingApplication Use="True"/>
|
<LaunchingApplication Use="True"/>
|
||||||
</local>
|
</local>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="2">
|
<RequiredPackages Count="1">
|
||||||
<Item1>
|
<Item1>
|
||||||
<PackageName Value="FPCUnitConsoleRunner"/>
|
|
||||||
</Item1>
|
|
||||||
<Item2>
|
|
||||||
<PackageName Value="FCL"/>
|
<PackageName Value="FCL"/>
|
||||||
</Item2>
|
</Item1>
|
||||||
</RequiredPackages>
|
</RequiredPackages>
|
||||||
<Units Count="12">
|
<Units Count="12">
|
||||||
<Unit0>
|
<Unit0>
|
||||||
@ -109,6 +106,7 @@
|
|||||||
<Version Value="11"/>
|
<Version Value="11"/>
|
||||||
<SearchPaths>
|
<SearchPaths>
|
||||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||||
|
<OtherUnitFiles Value="../src"/>
|
||||||
</SearchPaths>
|
</SearchPaths>
|
||||||
<Other>
|
<Other>
|
||||||
<CompilerMessages>
|
<CompilerMessages>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user