mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 22:49:23 +02:00
* Support for type helpers, low()..High() ranges, static fields
git-svn-id: trunk@34668 -
This commit is contained in:
parent
f4bbb229fa
commit
0437bc4c8e
@ -705,7 +705,7 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
{ TPasVariable }
|
{ TPasVariable }
|
||||||
TVariableModifier = (vmCVar, vmExternal, vmPublic, vmExport, vmClass);
|
TVariableModifier = (vmCVar, vmExternal, vmPublic, vmExport, vmClass,vmStatic);
|
||||||
TVariableModifiers = set of TVariableModifier;
|
TVariableModifiers = set of TVariableModifier;
|
||||||
|
|
||||||
TPasVariable = class(TPasElement)
|
TPasVariable = class(TPasElement)
|
||||||
@ -4138,7 +4138,11 @@ begin
|
|||||||
If Kind=pekRange then
|
If Kind=pekRange then
|
||||||
Result:='..'
|
Result:='..'
|
||||||
else
|
else
|
||||||
Result:=' '+OpcodeStrings[Opcode]+' ';
|
begin
|
||||||
|
Result:=OpcodeStrings[Opcode];
|
||||||
|
if Not (OpCode in [eopAddress,eopDeref,eopSubIdent]) then
|
||||||
|
Result:=' '+Result+' ';
|
||||||
|
end;
|
||||||
If Assigned(Left) then
|
If Assigned(Left) then
|
||||||
begin
|
begin
|
||||||
op := Left.GetDeclaration(Full);
|
op := Left.GetDeclaration(Full);
|
||||||
|
@ -1063,7 +1063,7 @@ begin
|
|||||||
ParseExcTokenError(';');
|
ParseExcTokenError(';');
|
||||||
UnGetToken;
|
UnGetToken;
|
||||||
end
|
end
|
||||||
else if (CurToken=tkDotDot) then // A: B..C;
|
else if (CurToken in [tkBraceOpen,tkDotDot]) then // A: B..C;
|
||||||
begin
|
begin
|
||||||
K:=stkRange;
|
K:=stkRange;
|
||||||
UnGetToken;
|
UnGetToken;
|
||||||
@ -1225,7 +1225,7 @@ Const
|
|||||||
NoHintTokens = [tkProcedure,tkFunction];
|
NoHintTokens = [tkProcedure,tkFunction];
|
||||||
var
|
var
|
||||||
PM : TPackMode;
|
PM : TPackMode;
|
||||||
CH , ok: Boolean; // Check hint ?
|
CH , isHelper,ok: Boolean; // Check hint ?
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
// NextToken and check pack mode
|
// NextToken and check pack mode
|
||||||
@ -1246,7 +1246,16 @@ begin
|
|||||||
tkInterface: Result := ParseClassDecl(Parent, NamePos, TypeName, okInterface);
|
tkInterface: Result := ParseClassDecl(Parent, NamePos, TypeName, okInterface);
|
||||||
tkSpecialize: Result:=ParseSpecializeType(Parent,TypeName);
|
tkSpecialize: Result:=ParseSpecializeType(Parent,TypeName);
|
||||||
tkClass: Result := ParseClassDecl(Parent, NamePos, TypeName, okClass, PM);
|
tkClass: Result := ParseClassDecl(Parent, NamePos, TypeName, okClass, PM);
|
||||||
tkType: Result:=ParseAliasType(Parent,NamePos,TypeName);
|
tkType:
|
||||||
|
begin
|
||||||
|
NextToken;
|
||||||
|
isHelper:=Curtoken=tkHelper;
|
||||||
|
UnGetToken;
|
||||||
|
if isHelper then
|
||||||
|
Result:=ParseClassDecl(Parent,NamePos,TypeName,okTypeHelper,PM)
|
||||||
|
else
|
||||||
|
Result:=ParseAliasType(Parent,NamePos,TypeName);
|
||||||
|
end;
|
||||||
// Always allowed
|
// Always allowed
|
||||||
tkIdentifier: Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
|
tkIdentifier: Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
|
||||||
tkCaret: Result:=ParsePointerType(Parent,NamePos,TypeName);
|
tkCaret: Result:=ParsePointerType(Parent,NamePos,TypeName);
|
||||||
@ -1552,7 +1561,7 @@ begin
|
|||||||
while CurToken in [tkDot] do
|
while CurToken in [tkDot] do
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
if CurToken=tkIdentifier then
|
if CurToken in [tkIdentifier,tktrue,tkfalse] then // true and false are also identifiers
|
||||||
begin
|
begin
|
||||||
AddToBinaryExprChain(Result,Last,
|
AddToBinaryExprChain(Result,Last,
|
||||||
CreatePrimitiveExpr(AParent,pekIdent,CurTokenString), eopSubIdent);
|
CreatePrimitiveExpr(AParent,pekIdent,CurTokenString), eopSubIdent);
|
||||||
@ -4498,17 +4507,32 @@ Var
|
|||||||
VarList: TFPList;
|
VarList: TFPList;
|
||||||
Element: TPasElement;
|
Element: TPasElement;
|
||||||
I : Integer;
|
I : Integer;
|
||||||
|
isStatic : Boolean;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
VarList := TFPList.Create;
|
VarList := TFPList.Create;
|
||||||
try
|
try
|
||||||
ParseInlineVarDecl(AType, VarList, AVisibility, False);
|
ParseInlineVarDecl(AType, VarList, AVisibility, False);
|
||||||
|
if CurToken=tkSemicolon then
|
||||||
|
begin
|
||||||
|
NextToken;
|
||||||
|
isStatic:=CurTokenIsIdentifier('static');
|
||||||
|
if isStatic then
|
||||||
|
ExpectToken(tkSemicolon)
|
||||||
|
else
|
||||||
|
UngetToken;
|
||||||
|
end;
|
||||||
for i := 0 to VarList.Count - 1 do
|
for i := 0 to VarList.Count - 1 do
|
||||||
begin
|
begin
|
||||||
Element := TPasElement(VarList[i]);
|
Element := TPasElement(VarList[i]);
|
||||||
Element.Visibility := AVisibility;
|
Element.Visibility := AVisibility;
|
||||||
if IsClassField and (Element is TPasVariable) then
|
if (Element is TPasVariable) then
|
||||||
|
begin
|
||||||
|
if IsClassField then
|
||||||
TPasVariable(Element).VarModifiers:=TPasVariable(Element).VarModifiers+[vmClass];
|
TPasVariable(Element).VarModifiers:=TPasVariable(Element).VarModifiers+[vmClass];
|
||||||
|
if isStatic then
|
||||||
|
TPasVariable(Element).VarModifiers:=TPasVariable(Element).VarModifiers+[vmStatic];
|
||||||
|
end;
|
||||||
AType.Members.Add(Element);
|
AType.Members.Add(Element);
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
@ -4689,10 +4713,11 @@ function TPasParser.ParseClassDecl(Parent: TPasElement;
|
|||||||
|
|
||||||
Var
|
Var
|
||||||
ok: Boolean;
|
ok: Boolean;
|
||||||
|
FT : TPasType;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
|
FT:=Nil;
|
||||||
if (AObjKind = okClass) and (CurToken = tkOf) then
|
if (AObjKind = okClass) and (CurToken = tkOf) then
|
||||||
begin
|
begin
|
||||||
Result := TPasClassOfType(CreateElement(TPasClassOfType, AClassName,
|
Result := TPasClassOfType(CreateElement(TPasClassOfType, AClassName,
|
||||||
@ -4704,15 +4729,22 @@ begin
|
|||||||
end;
|
end;
|
||||||
if (CurToken = tkHelper) then
|
if (CurToken = tkHelper) then
|
||||||
begin
|
begin
|
||||||
if Not (AObjKind in [okClass,okRecordHelper]) then
|
if Not (AObjKind in [okClass,okTypeHelper,okRecordHelper]) then
|
||||||
ParseExc(nParserHelperNotAllowed,SParserHelperNotAllowed,[ObjKindNames[AObjKind]]);
|
ParseExc(nParserHelperNotAllowed,SParserHelperNotAllowed,[ObjKindNames[AObjKind]]);
|
||||||
if (AObjKind = okClass) then
|
Case AObjKind of
|
||||||
|
okClass:
|
||||||
AObjKind:=okClassHelper;
|
AObjKind:=okClassHelper;
|
||||||
|
okTypeHelper:
|
||||||
|
begin
|
||||||
|
ExpectToken(tkFor);
|
||||||
|
FT:=ParseType(Parent,Scanner.CurSourcePos,'',False);
|
||||||
|
end
|
||||||
|
end;
|
||||||
NextToken;
|
NextToken;
|
||||||
end;
|
end;
|
||||||
Result := TPasClassType(CreateElement(TPasClassType, AClassName,
|
Result := TPasClassType(CreateElement(TPasClassType, AClassName,
|
||||||
Parent, NamePos));
|
Parent, NamePos));
|
||||||
|
TPasClassType(Result).HelperForType:=FT;
|
||||||
ok:=false;
|
ok:=false;
|
||||||
try
|
try
|
||||||
TPasClassType(Result).ObjKind := AObjKind;
|
TPasClassType(Result).ObjKind := AObjKind;
|
||||||
|
@ -72,6 +72,7 @@ type
|
|||||||
procedure TestOneSpecializedClassInterface;
|
procedure TestOneSpecializedClassInterface;
|
||||||
Procedure TestOneField;
|
Procedure TestOneField;
|
||||||
Procedure TestOneFieldComment;
|
Procedure TestOneFieldComment;
|
||||||
|
procedure TestOneFieldStatic;
|
||||||
Procedure TestOneVarField;
|
Procedure TestOneVarField;
|
||||||
Procedure TestOneClassField;
|
Procedure TestOneClassField;
|
||||||
Procedure TestOneFieldVisibility;
|
Procedure TestOneFieldVisibility;
|
||||||
@ -513,6 +514,16 @@ begin
|
|||||||
AssertVisibility;
|
AssertVisibility;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestClassType.TestOneFieldStatic;
|
||||||
|
begin
|
||||||
|
AddMember('a : integer; static');
|
||||||
|
ParseClass;
|
||||||
|
AssertNotNull('Have 1 field',Field1);
|
||||||
|
AssertMemberName('a');
|
||||||
|
AssertVisibility;
|
||||||
|
AssertTrue('Have static field',vmStatic in TPasVariable(Field1).VarModifiers);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestClassType.TestOneFieldComment;
|
procedure TTestClassType.TestOneFieldComment;
|
||||||
begin
|
begin
|
||||||
AddComment:=true;
|
AddComment:=true;
|
||||||
|
@ -80,6 +80,7 @@ type
|
|||||||
Procedure TestFunctionOneArgDefaultExpr;
|
Procedure TestFunctionOneArgDefaultExpr;
|
||||||
procedure TestProcedureTwoArgsDefault;
|
procedure TestProcedureTwoArgsDefault;
|
||||||
Procedure TestFunctionTwoArgsDefault;
|
Procedure TestFunctionTwoArgsDefault;
|
||||||
|
procedure TestFunctionOneArgEnumeratedExplicit;
|
||||||
procedure TestProcedureOneUntypedVarArg;
|
procedure TestProcedureOneUntypedVarArg;
|
||||||
Procedure TestFunctionOneUntypedVarArg;
|
Procedure TestFunctionOneUntypedVarArg;
|
||||||
procedure TestProcedureTwoUntypedVarArgs;
|
procedure TestProcedureTwoUntypedVarArgs;
|
||||||
@ -562,6 +563,13 @@ begin
|
|||||||
AssertArg(FuncType,0,'B',argDefault,'Integer','1');
|
AssertArg(FuncType,0,'B',argDefault,'Integer','1');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestProcedureFunction.TestFunctionOneArgEnumeratedExplicit;
|
||||||
|
begin
|
||||||
|
ParseFunction('(B : TSomeEnum = TSomeEnum.False)');
|
||||||
|
AssertFunc([],ccDefault,1);
|
||||||
|
AssertArg(FuncType,0,'B',argDefault,'TSomeEnum','TSomeEnum.False');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestProcedureFunction.TestProcedureOneArgDefaultSet;
|
procedure TTestProcedureFunction.TestProcedureOneArgDefaultSet;
|
||||||
begin
|
begin
|
||||||
ParseProcedure('(B : MySet = [1,2])');
|
ParseProcedure('(B : MySet = [1,2])');
|
||||||
|
@ -33,6 +33,7 @@ type
|
|||||||
TTestTypeParser = Class(TBaseTestTypeParser)
|
TTestTypeParser = Class(TBaseTestTypeParser)
|
||||||
private
|
private
|
||||||
Protected
|
Protected
|
||||||
|
procedure StartTypeHelper(ForType: String; AParent: String);
|
||||||
Procedure DoTestAliasType(Const AnAliasType : String; Const AHint : String);
|
Procedure DoTestAliasType(Const AnAliasType : String; Const AHint : String);
|
||||||
procedure DoTestStringType(const AnAliasType: String; const AHint: String);
|
procedure DoTestStringType(const AnAliasType: String; const AHint: String);
|
||||||
procedure DoTypeError(Const AMsg,ASource : string);
|
procedure DoTypeError(Const AMsg,ASource : string);
|
||||||
@ -139,6 +140,7 @@ type
|
|||||||
Procedure TestComplexSet;
|
Procedure TestComplexSet;
|
||||||
Procedure TestComplexSetDeprecated;
|
Procedure TestComplexSetDeprecated;
|
||||||
Procedure TestComplexSetPlatform;
|
Procedure TestComplexSetPlatform;
|
||||||
|
procedure TestRangeLowHigh;
|
||||||
Procedure TestRangeSet;
|
Procedure TestRangeSet;
|
||||||
Procedure TestSubRangeSet;
|
Procedure TestSubRangeSet;
|
||||||
Procedure TestRangeSetDeprecated;
|
Procedure TestRangeSetDeprecated;
|
||||||
@ -155,6 +157,7 @@ type
|
|||||||
Procedure TestReferenceArray;
|
Procedure TestReferenceArray;
|
||||||
Procedure TestReferencePointer;
|
Procedure TestReferencePointer;
|
||||||
Procedure TestInvalidColon;
|
Procedure TestInvalidColon;
|
||||||
|
Procedure TestTypeHelper;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TTestRecordTypeParser }
|
{ TTestRecordTypeParser }
|
||||||
@ -2326,6 +2329,7 @@ Function TBaseTestTypeParser.ParseType(ASource: String; ATypeClass: TClass;
|
|||||||
|
|
||||||
Var
|
Var
|
||||||
D : String;
|
D : String;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Hint:=AHint;
|
Hint:=AHint;
|
||||||
Add('Type');
|
Add('Type');
|
||||||
@ -2340,11 +2344,19 @@ begin
|
|||||||
Add(' '+D+';');
|
Add(' '+D+';');
|
||||||
// Writeln(source.text);
|
// Writeln(source.text);
|
||||||
ParseDeclarations;
|
ParseDeclarations;
|
||||||
|
if ATypeClass.InHeritsFrom(TPasClassType) then
|
||||||
|
AssertEquals('One type definition',1,Declarations.Classes.Count)
|
||||||
|
else
|
||||||
AssertEquals('One type definition',1,Declarations.Types.Count);
|
AssertEquals('One type definition',1,Declarations.Types.Count);
|
||||||
If (AtypeClass<>Nil) then
|
If (AtypeClass<>Nil) then
|
||||||
AssertEquals('First declaration is type definition.',ATypeClass,TObject(Declarations.Types[0]).ClassType);
|
begin
|
||||||
AssertEquals('First declaration has correct name.','A',TPasType(Declarations.Types[0]).Name);
|
if ATypeClass.InHeritsFrom(TPasClassType) then
|
||||||
|
Result:=TPasType(Declarations.Classes[0])
|
||||||
|
else
|
||||||
Result:=TPasType(Declarations.Types[0]);
|
Result:=TPasType(Declarations.Types[0]);
|
||||||
|
AssertEquals('First declaration is type definition.',ATypeClass,Result.ClassType);
|
||||||
|
end;
|
||||||
|
AssertEquals('First declaration has correct name.','A',Result.Name);
|
||||||
FType:=Result;
|
FType:=Result;
|
||||||
Definition:=Result;
|
Definition:=Result;
|
||||||
if (Hint<>'') then
|
if (Hint<>'') then
|
||||||
@ -3044,6 +3056,13 @@ begin
|
|||||||
DoTestComplexSet;
|
DoTestComplexSet;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestTypeParser.TestRangeLowHigh;
|
||||||
|
|
||||||
|
begin
|
||||||
|
DoParseRangeSet('low(TRange)..high(TRange)','');
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TTestTypeParser.TestRangeSet;
|
procedure TTestTypeParser.TestRangeSet;
|
||||||
begin
|
begin
|
||||||
// TRange = (rLow, rMiddle, rHigh);
|
// TRange = (rLow, rMiddle, rHigh);
|
||||||
@ -3198,6 +3217,28 @@ begin
|
|||||||
AssertEquals('wrong colon in type raised an error',true,ok);
|
AssertEquals('wrong colon in type raised an error',true,ok);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TTestTypeParser.StartTypeHelper(ForType: String; AParent: String);
|
||||||
|
Var
|
||||||
|
S : String;
|
||||||
|
begin
|
||||||
|
|
||||||
|
S:='TMyClass = Type Helper';
|
||||||
|
if (AParent<>'') then
|
||||||
|
begin
|
||||||
|
S:=S+'('+AParent;
|
||||||
|
S:=S+')';
|
||||||
|
end;
|
||||||
|
S:=S+' for '+ForType;
|
||||||
|
Add(S);
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestTypeParser.TestTypeHelper;
|
||||||
|
begin
|
||||||
|
ParseType('Type Helper for AnsiString end',TPasClassType,'');
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
RegisterTests([TTestTypeParser,TTestRecordTypeParser,TTestProcedureTypeParser]);
|
RegisterTests([TTestTypeParser,TTestRecordTypeParser,TTestProcedureTypeParser]);
|
||||||
end.
|
end.
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<RunParams>
|
<RunParams>
|
||||||
<local>
|
<local>
|
||||||
<FormatVersion Value="1"/>
|
<FormatVersion Value="1"/>
|
||||||
<CommandLineParams Value="--suite=TTestTypeParser.TestGenericArray"/>
|
<CommandLineParams Value="--suite=TTestTypeParser.TestRangeLowHigh"/>
|
||||||
</local>
|
</local>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="1">
|
<RequiredPackages Count="1">
|
||||||
|
Loading…
Reference in New Issue
Block a user