mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-03 23:57:17 +01:00
fcl-passrc: implemented @@ memory address operator in scanner, parser and resolver
git-svn-id: trunk@37108 -
This commit is contained in:
parent
ada62f0b41
commit
a9baac5a48
@ -141,6 +141,7 @@ const
|
||||
nOverflowInArithmeticOperation = 3068;
|
||||
nDivByZero = 3069;
|
||||
nRangeCheckInSetConstructor = 3070;
|
||||
nIncompatibleTypesGotParametersExpected = 3071;
|
||||
|
||||
// resourcestring patterns of messages
|
||||
resourcestring
|
||||
@ -214,6 +215,7 @@ resourcestring
|
||||
sOverflowInArithmeticOperation = 'Overflow in arithmetic operation';
|
||||
sDivByZero = 'Division by zero';
|
||||
sRangeCheckInSetConstructor = 'range check error in set constructor or duplicate set element';
|
||||
sIncompatibleTypesGotParametersExpected = 'Incompatible types, got %s parameters, expected %s';
|
||||
|
||||
type
|
||||
{ TResolveData - base class for data stored in TPasElement.CustomData }
|
||||
|
||||
@ -150,13 +150,13 @@ Works:
|
||||
- a:=value
|
||||
|
||||
ToDo:
|
||||
- @@
|
||||
- range checking:
|
||||
- arr[index]
|
||||
- indexedprop[param]
|
||||
- case-of unique
|
||||
- defaultvalue
|
||||
- stored
|
||||
- @@
|
||||
- fail to write a loop var inside the loop
|
||||
- warn: create class with abstract methods
|
||||
- classes - TPasClassType
|
||||
@ -10762,7 +10762,14 @@ begin
|
||||
end;
|
||||
ProcArgs1:=Proc1.Args;
|
||||
ProcArgs2:=Proc2.Args;
|
||||
if ProcArgs1.Count<>ProcArgs2.Count then exit;
|
||||
if ProcArgs1.Count<>ProcArgs2.Count then
|
||||
begin
|
||||
if RaiseOnIncompatible then
|
||||
RaiseMsg(20170902142829,nIncompatibleTypesGotParametersExpected,
|
||||
sIncompatibleTypesGotParametersExpected,
|
||||
[IntToStr(ProcArgs1.Count),IntToStr(ProcArgs2.Count)],ErrorEl);
|
||||
exit;
|
||||
end;
|
||||
for i:=0 to ProcArgs1.Count-1 do
|
||||
begin
|
||||
{$IFDEF VerbosePasResolver}
|
||||
@ -11279,7 +11286,7 @@ begin
|
||||
// for example ProcVar:=Proc
|
||||
if CheckProcTypeCompatibility(TPasProcedureType(LHS.TypeEl),
|
||||
TPasProcedure(RHS.IdentEl).ProcType,true,ErrorEl,RaiseOnIncompatible) then
|
||||
Result:=cExact;
|
||||
exit(cExact);
|
||||
end;
|
||||
end
|
||||
else if LBT=btPointer then
|
||||
@ -11413,7 +11420,7 @@ begin
|
||||
if RErrorEl=nil then RErrorEl:=LErrorEl;
|
||||
// check if the RHS is type compatible to LHS
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.CheckEqualCompatibility LHS=',GetResolverResultDbg(LHS),' RHS=',GetResolverResultDbg(RHS));
|
||||
writeln('TPasResolver.CheckEqualResCompatibility LHS=',GetResolverResultDbg(LHS),' RHS=',GetResolverResultDbg(RHS));
|
||||
{$ENDIF}
|
||||
if not (rrfReadable in LHS.Flags) then
|
||||
begin
|
||||
@ -12880,7 +12887,7 @@ begin
|
||||
ComputeBinaryExpr(TBinaryExpr(El),ResolvedEl,Flags,StartEl)
|
||||
else if ElClass=TUnaryExpr then
|
||||
begin
|
||||
if TUnaryExpr(El).OpCode=eopAddress then
|
||||
if TUnaryExpr(El).OpCode in [eopAddress,eopMemAddress] then
|
||||
ComputeElement(TUnaryExpr(El).Operand,ResolvedEl,Flags+[rcNoImplicitProc],StartEl)
|
||||
else
|
||||
ComputeElement(TUnaryExpr(El).Operand,ResolvedEl,Flags,StartEl);
|
||||
@ -12906,6 +12913,13 @@ begin
|
||||
end
|
||||
else
|
||||
RaiseMsg(20170216152535,nIllegalQualifier,sIllegalQualifier,[OpcodeStrings[TUnaryExpr(El).OpCode]],El);
|
||||
eopMemAddress:
|
||||
begin
|
||||
if (ResolvedEl.BaseType=btContext) and (ResolvedEl.TypeEl is TPasProcedureType) then
|
||||
exit
|
||||
else
|
||||
RaiseMsg(20170902145547,nIllegalQualifier,sIllegalQualifier,[OpcodeStrings[TUnaryExpr(El).OpCode]],El);
|
||||
end;
|
||||
end;
|
||||
RaiseNotYetImplemented(20160926142426,El);
|
||||
end
|
||||
|
||||
@ -175,7 +175,7 @@ type
|
||||
eopEqual, eopNotEqual, // Logical
|
||||
eopLessThan,eopGreaterThan, eopLessthanEqual,eopGreaterThanEqual, // ordering
|
||||
eopIn,eopIs,eopAs, eopSymmetricaldifference, // Specials
|
||||
eopAddress, eopDeref, // Pointers
|
||||
eopAddress, eopDeref, eopMemAddress, // Pointers
|
||||
eopSubIdent); // SomeRec.A, A is subIdent of SomeRec
|
||||
|
||||
{ TPasExpr }
|
||||
@ -1481,7 +1481,7 @@ const
|
||||
'=','<>',
|
||||
'<','>','<=','>=',
|
||||
'in','is','as','><',
|
||||
'@','^',
|
||||
'@','^','@@',
|
||||
'.');
|
||||
|
||||
|
||||
@ -3582,8 +3582,6 @@ function TPasRecordType.GetDeclaration (full : boolean) : string;
|
||||
Var
|
||||
S : TStringList;
|
||||
temp : string;
|
||||
i : integer;
|
||||
|
||||
begin
|
||||
S:=TStringList.Create;
|
||||
Try
|
||||
|
||||
@ -1877,6 +1877,7 @@ begin
|
||||
tkEqual : Result:=eopEqual;
|
||||
tkGreaterThan : Result:=eopGreaterThan;
|
||||
tkAt : Result:=eopAddress;
|
||||
tkAtAt : Result:=eopMemAddress;
|
||||
tkNotEqual : Result:=eopNotEqual;
|
||||
tkLessEqualThan : Result:=eopLessthanEqual;
|
||||
tkGreaterEqualThan : Result:=eopGreaterThanEqual;
|
||||
@ -2046,18 +2047,6 @@ begin
|
||||
Last:=CreateSelfExpr(AParent);
|
||||
HandleSelf(Last);
|
||||
end;
|
||||
tkAt:
|
||||
begin
|
||||
// is this still needed?
|
||||
// P:=@function;
|
||||
NextToken;
|
||||
if (length(CurTokenText)=0) or not (CurTokenText[1] in ['A'..'_']) then
|
||||
begin
|
||||
UngetToken;
|
||||
ParseExcExpectedIdentifier;
|
||||
end;
|
||||
Last:=CreatePrimitiveExpr(AParent,pekString, '@'+CurTokenText);
|
||||
end;
|
||||
tkCaret:
|
||||
begin
|
||||
// is this still needed?
|
||||
@ -2155,7 +2144,7 @@ begin
|
||||
case t of
|
||||
// tkDot:
|
||||
// Result:=5;
|
||||
tknot,tkAt:
|
||||
tknot,tkAt,tkAtAt:
|
||||
Result:=4;
|
||||
tkMul, tkDivision, tkdiv, tkmod, tkand, tkShl,tkShr, tkas, tkPower :
|
||||
Result:=3;
|
||||
@ -2180,7 +2169,7 @@ var
|
||||
NotBinary : Boolean;
|
||||
|
||||
const
|
||||
PrefixSym = [tkPlus, tkMinus, tknot, tkAt]; // + - not @
|
||||
PrefixSym = [tkPlus, tkMinus, tknot, tkAt, tkAtAt]; // + - not @
|
||||
BinaryOP = [tkMul, tkDivision, tkdiv, tkmod, tkDotDot,
|
||||
tkand, tkShl,tkShr, tkas, tkPower,
|
||||
tkPlus, tkMinus, tkor, tkxor, tkSymmetricalDifference,
|
||||
@ -4659,7 +4648,7 @@ Var
|
||||
Function atEndOfAsm : Boolean;
|
||||
|
||||
begin
|
||||
Result:=(CurToken=tkEnd) and (LastToken<>tkAt);
|
||||
Result:=(CurToken=tkEnd) and not (LastToken in [tkAt,tkAtAt]);
|
||||
end;
|
||||
|
||||
begin
|
||||
@ -5137,11 +5126,12 @@ begin
|
||||
end;
|
||||
tkEOF:
|
||||
CheckToken(tkend);
|
||||
tkAt,tkBraceOpen,tkIdentifier,tkNumber,tkSquaredBraceOpen,tkMinus,tkPlus,tkinherited:
|
||||
tkAt,tkAtAt,tkBraceOpen,tkIdentifier,tkNumber,tkSquaredBraceOpen,tkMinus,tkPlus,tkinherited:
|
||||
begin
|
||||
// This should in fact not be checked here.
|
||||
// if (CurToken=tkAt) and not (msDelphi in CurrentModeswitches) then
|
||||
// ParseExc;
|
||||
// Do not check this here:
|
||||
// if (CurToken=tkAt) and not (msDelphi in CurrentModeswitches) then
|
||||
// ParseExc;
|
||||
|
||||
// On is usable as an identifier
|
||||
if lowerCase(CurTokenText)='on' then
|
||||
begin
|
||||
|
||||
@ -138,6 +138,7 @@ type
|
||||
tkAssignMinus, // -=
|
||||
tkAssignMul, // *=
|
||||
tkAssignDivision, // /=
|
||||
tkAtAt, // @@
|
||||
// Reserved words
|
||||
tkabsolute,
|
||||
tkand,
|
||||
@ -685,6 +686,7 @@ const
|
||||
'-=',
|
||||
'*=',
|
||||
'/=',
|
||||
'@@',
|
||||
// Reserved words
|
||||
'absolute',
|
||||
'and',
|
||||
@ -3268,6 +3270,11 @@ begin
|
||||
begin
|
||||
Inc(TokenStr);
|
||||
Result := tkAt;
|
||||
if TokenStr^='@' then
|
||||
begin
|
||||
Inc(TokenStr);
|
||||
Result:=tkAtAt;
|
||||
end;
|
||||
end;
|
||||
'[':
|
||||
begin
|
||||
|
||||
@ -565,6 +565,7 @@ type
|
||||
Procedure TestProcTypeCall;
|
||||
Procedure TestProcType_FunctionFPC;
|
||||
Procedure TestProcType_FunctionDelphi;
|
||||
Procedure TestProcType_ProcedureDelphi;
|
||||
Procedure TestProcType_MethodFPC;
|
||||
Procedure TestProcType_MethodDelphi;
|
||||
Procedure TestAssignProcToMethodFail;
|
||||
@ -9202,6 +9203,7 @@ begin
|
||||
Add('var');
|
||||
Add(' b: boolean;');
|
||||
Add(' vP, vQ: tfuncint;');
|
||||
Add(' ');
|
||||
Add('begin');
|
||||
Add(' vp:=nil;');
|
||||
Add(' vp:=vp;');
|
||||
@ -9231,6 +9233,55 @@ begin
|
||||
ParseProgram;
|
||||
end;
|
||||
|
||||
procedure TTestResolver.TestProcType_ProcedureDelphi;
|
||||
begin
|
||||
StartProgram(false);
|
||||
Add('{$mode Delphi}');
|
||||
Add('type');
|
||||
Add(' TProc = procedure;');
|
||||
Add('procedure Doit;');
|
||||
Add('begin end;');
|
||||
Add('var');
|
||||
Add(' b: boolean;');
|
||||
Add(' vP, vQ: tproc;');
|
||||
Add('begin');
|
||||
Add(' vp:=nil;');
|
||||
Add(' vp:=vp;');
|
||||
Add(' vp:=vq;');
|
||||
Add(' vp:=@doit;'); // ok in fpc and delphi, Note that in Delphi type of @F is Pointer, while in FPC it is the proc type
|
||||
Add(' vp:=doit;'); // illegal in fpc, ok in delphi
|
||||
//Add(' vp:=@doit;'); // illegal in fpc, ok in delphi (because Delphi treats @F as Pointer), not supported by resolver
|
||||
Add(' vp;'); // ok in fpc and delphi
|
||||
Add(' vp();');
|
||||
|
||||
// equal
|
||||
//Add(' b:=vp=nil;'); // ok in fpc, illegal in delphi
|
||||
Add(' b:=@@vp=nil;'); // ok in fpc delphi mode, ok in delphi
|
||||
//Add(' b:=nil=vp;'); // ok in fpc, illegal in delphi
|
||||
Add(' b:=nil=@@vp;'); // ok in fpc delphi mode, ok in delphi
|
||||
Add(' b:=@@vp=@@vq;'); // ok in fpc delphi mode, ok in Delphi
|
||||
//Add(' b:=vp=vq;'); // in fpc compare proctypes, in delphi compare results
|
||||
//Add(' b:=vp=@doit;'); // ok in fpc, illegal in delphi
|
||||
Add(' b:=@@vp=@doit;'); // ok in fpc delphi mode, ok in delphi
|
||||
//Add(' b:=@doit=vp;'); // ok in fpc, illegal in delphi
|
||||
Add(' b:=@doit=@@vp;'); // ok in fpc delphi mode, ok in delphi
|
||||
|
||||
// unequal
|
||||
//Add(' b:=vp<>nil;'); // ok in fpc, illegal in delphi
|
||||
Add(' b:=@@vp<>nil;'); // ok in fpc mode delphi, ok in delphi
|
||||
//Add(' b:=nil<>vp;'); // ok in fpc, illegal in delphi
|
||||
Add(' b:=nil<>@@vp;'); // ok in fpc mode delphi, ok in delphi
|
||||
//Add(' b:=vp<>vq;'); // in fpc compare proctypes, in delphi compare results
|
||||
Add(' b:=@@vp<>@@vq;'); // ok in fpc mode delphi, ok in delphi
|
||||
//Add(' b:=vp<>@doit;'); // ok in fpc, illegal in delphi
|
||||
Add(' b:=@@vp<>@doit;'); // ok in fpc mode delphi, illegal in delphi
|
||||
//Add(' b:=@doit<>vp;'); // ok in fpc, illegal in delphi
|
||||
Add(' b:=@doit<>@@vp;'); // ok in fpc mode delphi, illegal in delphi
|
||||
|
||||
Add(' b:=Assigned(vp);');
|
||||
ParseProgram;
|
||||
end;
|
||||
|
||||
procedure TTestResolver.TestProcType_MethodFPC;
|
||||
begin
|
||||
StartProgram(false);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user