mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-27 16:30:41 +02:00
fcl-passrc: parser: fixed (a.b).c
git-svn-id: trunk@40870 -
This commit is contained in:
parent
38f158bb69
commit
4f04f23479
@ -993,9 +993,9 @@ type
|
||||
Current: TPasProperty;
|
||||
end;
|
||||
|
||||
{ TPasSubScope - base class for sub scopes aka dotted scopes }
|
||||
{ TPasSubExprScope - base class for sub scopes aka dotted scopes }
|
||||
|
||||
TPasSubScope = Class(TPasIdentifierScope)
|
||||
TPasSubExprScope = Class(TPasIdentifierScope)
|
||||
public
|
||||
class function IsStoredInElement: boolean; override;
|
||||
end;
|
||||
@ -1010,7 +1010,7 @@ type
|
||||
|
||||
{ TPasModuleDotScope - scope for searching unitname.<identifier> }
|
||||
|
||||
TPasModuleDotScope = Class(TPasSubScope)
|
||||
TPasModuleDotScope = Class(TPasSubExprScope)
|
||||
private
|
||||
FModule: TPasModule;
|
||||
procedure OnInternalIterate(El: TPasElement; ElScope, StartScope: TPasScope;
|
||||
@ -1031,7 +1031,7 @@ type
|
||||
|
||||
{ TPasDotIdentifierScope }
|
||||
|
||||
TPasDotIdentifierScope = Class(TPasSubScope)
|
||||
TPasDotIdentifierScope = Class(TPasSubExprScope)
|
||||
public
|
||||
IdentifierScope: TPasIdentifierScope;
|
||||
OnlyTypeMembers: boolean; // true=only class var/procs, false=default=all
|
||||
@ -1410,7 +1410,9 @@ type
|
||||
procedure ResolveSubIdent(El: TBinaryExpr; Access: TResolvedRefAccess); virtual;
|
||||
procedure ResolveParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
|
||||
procedure ResolveFuncParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
|
||||
procedure ResolveFuncParamsExprName(NameExpr: TPasExpr; Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
|
||||
procedure ResolveArrayParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
|
||||
procedure ResolveArrayParamsExprName(NameExpr: TPasExpr; Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
|
||||
procedure ResolveArrayParamsArgs(Params: TParamsExpr;
|
||||
const ResolvedValue: TPasResolverResult; Access: TResolvedRefAccess); virtual;
|
||||
function ResolveBracketOperatorClassOrRec(Params: TParamsExpr;
|
||||
@ -1747,8 +1749,8 @@ type
|
||||
function PushRecordDotScope(CurRecordType: TPasRecordType): TPasDotRecordScope;
|
||||
function PushEnumDotScope(CurEnumType: TPasEnumType): TPasDotEnumTypeScope;
|
||||
function PushWithExprScope(Expr: TPasExpr): TPasWithExprScope;
|
||||
procedure ResetSubScopes(out Depth: integer);
|
||||
procedure RestoreSubScopes(Depth: integer);
|
||||
procedure ResetSubExprScopes(out Depth: integer);
|
||||
procedure RestoreSubExprScopes(Depth: integer);
|
||||
function GetInheritedExprScope(ErrorEl: TPasElement): TPasProcedureScope;
|
||||
// log and messages
|
||||
class function MangleSourceLineNumber(Line, Column: integer): integer;
|
||||
@ -1894,11 +1896,13 @@ type
|
||||
function GetNextDottedExpr(El: TPasExpr): TPasExpr;
|
||||
function GetLeftMostExpr(El: TPasExpr): TPasExpr;
|
||||
function GetRightMostExpr(El: TPasExpr): TPasExpr;
|
||||
function GetParamsOfNameExpr(El: TPasExpr): TParamsExpr;
|
||||
function GetUsesUnitInFilename(InFileExpr: TPasExpr): string;
|
||||
function GetPathStart(El: TPasExpr): TPasExpr;
|
||||
function GetNewInstanceExpr(El: TPasExpr): TPasExpr;
|
||||
function ParentNeedsExprResult(El: TPasExpr): boolean;
|
||||
function GetReference_ConstructorType(Ref: TResolvedReference): TPasMembersType;
|
||||
function GetParamsValueRef(Params: TParamsExpr): TResolvedReference;
|
||||
function IsDynArray(TypeEl: TPasType; OptionalOpenArray: boolean = true): boolean;
|
||||
function IsOpenArray(TypeEl: TPasType): boolean;
|
||||
function IsDynOrOpenArray(TypeEl: TPasType): boolean;
|
||||
@ -3210,9 +3214,9 @@ begin
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
{ TPasSubScope }
|
||||
{ TPasSubExprScope }
|
||||
|
||||
class function TPasSubScope.IsStoredInElement: boolean;
|
||||
class function TPasSubExprScope.IsStoredInElement: boolean;
|
||||
begin
|
||||
Result:=false;
|
||||
end;
|
||||
@ -3915,6 +3919,29 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPasResolver.GetParamsOfNameExpr(El: TPasExpr): TParamsExpr;
|
||||
// Checks is El is the name expression of a call or array access
|
||||
// For example: a.b.El() a.El[]
|
||||
// Note: TPasParser guarantees that there is at most one TBinaryExpr between
|
||||
// El and TParamsExpr
|
||||
var
|
||||
Parent: TPasElement;
|
||||
begin
|
||||
Result:=nil;
|
||||
if not IsNameExpr(El) then exit;
|
||||
Parent:=El.Parent;
|
||||
if Parent is TBinaryExpr then
|
||||
begin
|
||||
if (TBinaryExpr(Parent).OpCode<>eopSubIdent)
|
||||
or (TBinaryExpr(Parent).right<>El) then
|
||||
exit;
|
||||
El:=TBinaryExpr(Parent); // continue
|
||||
Parent:=El.Parent;
|
||||
end;
|
||||
if (Parent is TParamsExpr) and (TParamsExpr(Parent).Value=El) then
|
||||
exit(TParamsExpr(Parent)); // params found
|
||||
end;
|
||||
|
||||
function TPasResolver.GetUsesUnitInFilename(InFileExpr: TPasExpr): string;
|
||||
var
|
||||
Value: TResEvalValue;
|
||||
@ -8040,10 +8067,26 @@ var
|
||||
DottedName: String;
|
||||
Bin: TBinaryExpr;
|
||||
ProcScope: TPasProcedureScope;
|
||||
Params: TParamsExpr;
|
||||
begin
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveNameExpr El=',GetObjName(El),' Name="',aName,'" ',Access);
|
||||
{$ENDIF}
|
||||
Params:=GetParamsOfNameExpr(El);
|
||||
if Params<>nil then
|
||||
begin
|
||||
if Params.Kind=pekFuncParams then
|
||||
begin
|
||||
ResolveFuncParamsExprName(El,Params,Access);
|
||||
exit;
|
||||
end
|
||||
else if Params.Kind=pekArrayParams then
|
||||
begin
|
||||
ResolveArrayParamsExprName(El,Params,Access);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
DeclEl:=FindElementWithoutParams(aName,FindData,El,false);
|
||||
if DeclEl.ClassType=TPasUsesUnit then
|
||||
begin
|
||||
@ -8414,14 +8457,14 @@ begin
|
||||
end;
|
||||
|
||||
// first resolve params
|
||||
ResetSubScopes(ScopeDepth);
|
||||
ResetSubExprScopes(ScopeDepth);
|
||||
if Params.Kind in [pekFuncParams,pekArrayParams] then
|
||||
ParamAccess:=rraParamToUnknownProc
|
||||
else
|
||||
ParamAccess:=rraRead;
|
||||
for i:=0 to length(Params.Params)-1 do
|
||||
ResolveExpr(Params.Params[i],ParamAccess);
|
||||
RestoreSubScopes(ScopeDepth);
|
||||
RestoreSubExprScopes(ScopeDepth);
|
||||
|
||||
// then resolve the call, typecast, array, set
|
||||
if (Params.Kind=pekFuncParams) then
|
||||
@ -8436,6 +8479,64 @@ end;
|
||||
|
||||
procedure TPasResolver.ResolveFuncParamsExpr(Params: TParamsExpr;
|
||||
Access: TResolvedRefAccess);
|
||||
var
|
||||
Value: TPasExpr;
|
||||
SubParams: TParamsExpr;
|
||||
ResolvedEl: TPasResolverResult;
|
||||
begin
|
||||
Value:=Params.Value;
|
||||
if Value is TBinaryExpr then
|
||||
begin
|
||||
// Note: a.b() is the same as (a.b)()
|
||||
// Note: a.b().c is stored as
|
||||
// TBinaryExpr eopSubIdent
|
||||
// / \
|
||||
// left = TParamsExpr right = TPrimitiveExpr 'c'
|
||||
// Value = TBinaryExpr
|
||||
// / \
|
||||
// left = TPrimitiveExpr 'a' right = TPrimitiveExpr 'b'
|
||||
while (Value is TBinaryExpr) and (TBinaryExpr(Value).OpCode=eopSubIdent) do
|
||||
Value:=TBinaryExpr(Value).right;
|
||||
if IsNameExpr(Value) then
|
||||
begin
|
||||
ResolveBinaryExpr(TBinaryExpr(Params.Value),Access);
|
||||
if not (Value.CustomData is TResolvedReference) then
|
||||
RaiseNotYetImplemented(20190115140557,Params);
|
||||
// already resolved
|
||||
exit;
|
||||
end;
|
||||
// ToDo: (a+b)()
|
||||
//ResolveBinaryExpr(TBinaryExpr(Params.Value),rraRead);
|
||||
RaiseNotYetImplemented(20190115140809,Params);
|
||||
end
|
||||
else if IsNameExpr(Value) then
|
||||
begin
|
||||
ResolveFuncParamsExprName(Value,Params,Access);
|
||||
end
|
||||
else if Value.ClassType=TParamsExpr then
|
||||
begin
|
||||
SubParams:=TParamsExpr(Value);
|
||||
if (SubParams.Kind in [pekArrayParams,pekFuncParams]) then
|
||||
begin
|
||||
// e.g. Name()() or Name[]()
|
||||
ResolveExpr(SubParams,rraRead);
|
||||
ComputeElement(SubParams,ResolvedEl,[rcNoImplicitProc,rcSetReferenceFlags]);
|
||||
if IsProcedureType(ResolvedEl,true) then
|
||||
begin
|
||||
CheckCallProcCompatibility(TPasProcedureType(ResolvedEl.LoTypeEl),Params,true);
|
||||
CreateReference(TPasProcedureType(ResolvedEl.LoTypeEl),Value,Access);
|
||||
exit;
|
||||
end
|
||||
end;
|
||||
RaiseMsg(20170216152202,nIllegalQualifierAfter,sIllegalQualifierAfter,
|
||||
['(',SubParams.ElementTypeName],Params);
|
||||
end
|
||||
else
|
||||
RaiseNotYetImplemented(20161014085118,Params.Value);
|
||||
end;
|
||||
|
||||
procedure TPasResolver.ResolveFuncParamsExprName(NameExpr: TPasExpr;
|
||||
Params: TParamsExpr; Access: TResolvedRefAccess);
|
||||
|
||||
procedure FinishProcParams(ProcType: TPasProcedureType);
|
||||
var
|
||||
@ -8445,7 +8546,7 @@ procedure TPasResolver.ResolveFuncParamsExpr(Params: TParamsExpr;
|
||||
if not (Access in [rraRead,rraParamToUnknownProc]) then
|
||||
begin
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveFuncParamsExpr.FinishProcParams Params=',GetObjName(Params),' Value=',GetObjName(Params.Value),' Access=',Access);
|
||||
writeln('TPasResolver.ResolveFuncParamsExpr.FinishProcParams Params=',GetObjName(Params),' NameEl=',GetObjName(NameExpr),' Access=',Access);
|
||||
{$ENDIF}
|
||||
RaiseMsg(20170306104440,nVariableIdentifierExpected,sVariableIdentifierExpected,[],Params);
|
||||
end;
|
||||
@ -8473,33 +8574,30 @@ procedure TPasResolver.ResolveFuncParamsExpr(Params: TParamsExpr;
|
||||
|
||||
var
|
||||
i: Integer;
|
||||
ElName, Msg: String;
|
||||
CallName, Msg: String;
|
||||
FindCallData: TFindCallElData;
|
||||
Abort: boolean;
|
||||
El, FoundEl: TPasElement;
|
||||
Ref: TResolvedReference;
|
||||
FindData: TPRFindData;
|
||||
BuiltInProc: TResElDataBuiltInProc;
|
||||
SubParams: TParamsExpr;
|
||||
ResolvedEl: TPasResolverResult;
|
||||
Value: TPasExpr;
|
||||
TypeEl: TPasType;
|
||||
C: TClass;
|
||||
begin
|
||||
Value:=Params.Value;
|
||||
if IsNameExpr(Value) then
|
||||
begin
|
||||
// e.g. Name() -> find compatible
|
||||
if Value.ClassType=TPrimitiveExpr then
|
||||
ElName:=TPrimitiveExpr(Value).Value
|
||||
if NameExpr.ClassType=TPrimitiveExpr then
|
||||
CallName:=TPrimitiveExpr(NameExpr).Value
|
||||
else if NameExpr.ClassType=TSelfExpr then
|
||||
CallName:='Self'
|
||||
else
|
||||
ElName:='Self';
|
||||
RaiseNotYetImplemented(20190115143539,NameExpr);
|
||||
FindCallData:=Default(TFindCallElData);
|
||||
FindCallData.Params:=Params;
|
||||
Abort:=false;
|
||||
IterateElements(ElName,@OnFindCallElements,@FindCallData,Abort);
|
||||
IterateElements(CallName,@OnFindCallElements,@FindCallData,Abort);
|
||||
if FindCallData.Found=nil then
|
||||
RaiseIdentifierNotFound(20170216152544,ElName,Value);
|
||||
RaiseIdentifierNotFound(20170216152544,CallName,NameExpr);
|
||||
if FindCallData.Distance=cIncompatible then
|
||||
begin
|
||||
// FoundEl one element, but it was incompatible => raise error
|
||||
@ -8554,7 +8652,7 @@ begin
|
||||
FindCallData.Params:=Params;
|
||||
FindCallData.List:=TFPList.Create;
|
||||
try
|
||||
IterateElements(ElName,@OnFindCallElements,@FindCallData,Abort);
|
||||
IterateElements(CallName,@OnFindCallElements,@FindCallData,Abort);
|
||||
Msg:='';
|
||||
for i:=0 to FindCallData.List.Count-1 do
|
||||
begin
|
||||
@ -8570,7 +8668,7 @@ begin
|
||||
Msg:=Msg+', '+GetElementSourcePosStr(El);
|
||||
end;
|
||||
RaiseMsg(20170216152200,nCantDetermineWhichOverloadedFunctionToCall,
|
||||
sCantDetermineWhichOverloadedFunctionToCall+Msg,[ElName],Value);
|
||||
sCantDetermineWhichOverloadedFunctionToCall+Msg,[CallName],NameExpr);
|
||||
finally
|
||||
FindCallData.List.Free;
|
||||
end;
|
||||
@ -8578,11 +8676,11 @@ begin
|
||||
|
||||
// FoundEl compatible element -> create reference
|
||||
FoundEl:=FindCallData.Found;
|
||||
Ref:=CreateReference(FoundEl,Value,rraRead);
|
||||
Ref:=CreateReference(FoundEl,NameExpr,rraRead);
|
||||
if FindCallData.StartScope.ClassType=ScopeClass_WithExpr then
|
||||
Ref.WithExprScope:=TPasWithExprScope(FindCallData.StartScope);
|
||||
FindData:=Default(TPRFindData);
|
||||
FindData.ErrorPosEl:=Value;
|
||||
FindData.ErrorPosEl:=NameExpr;
|
||||
FindData.StartScope:=FindCallData.StartScope;
|
||||
FindData.ElScope:=FindCallData.ElScope;
|
||||
FindData.Found:=FoundEl;
|
||||
@ -8663,51 +8761,102 @@ begin
|
||||
RaiseMsg(20170306104301,nIllegalQualifierAfter,sIllegalQualifierAfter,
|
||||
['(',TypeEl.ElementTypeName],Params);
|
||||
end;
|
||||
end
|
||||
else if Value.ClassType=TParamsExpr then
|
||||
begin
|
||||
SubParams:=TParamsExpr(Value);
|
||||
if (SubParams.Kind in [pekArrayParams,pekFuncParams]) then
|
||||
begin
|
||||
// e.g. Name()() or Name[]()
|
||||
ResolveExpr(SubParams,rraRead);
|
||||
ComputeElement(SubParams,ResolvedEl,[rcNoImplicitProc,rcSetReferenceFlags]);
|
||||
if IsProcedureType(ResolvedEl,true) then
|
||||
begin
|
||||
CheckCallProcCompatibility(TPasProcedureType(ResolvedEl.LoTypeEl),Params,true);
|
||||
CreateReference(TPasProcedureType(ResolvedEl.LoTypeEl),Value,Access);
|
||||
exit;
|
||||
end
|
||||
end;
|
||||
RaiseMsg(20170216152202,nIllegalQualifierAfter,sIllegalQualifierAfter,
|
||||
['(',SubParams.ElementTypeName],Params);
|
||||
end
|
||||
else
|
||||
RaiseNotYetImplemented(20161014085118,Params.Value);
|
||||
end;
|
||||
|
||||
procedure TPasResolver.ResolveArrayParamsExpr(Params: TParamsExpr;
|
||||
Access: TResolvedRefAccess);
|
||||
var
|
||||
ResolvedEl: TPasResolverResult;
|
||||
Value: TPasExpr;
|
||||
SubParams: TParamsExpr;
|
||||
begin
|
||||
Value:=Params.Value;
|
||||
if Value=nil then
|
||||
RaiseInternalError(20180423093120,GetObjName(Params));
|
||||
|
||||
procedure ResolveValueName(Value: TPasElement; ArrayName: string);
|
||||
var
|
||||
if IsNameExpr(Value) then
|
||||
begin
|
||||
// e.g. Name[]
|
||||
ResolveArrayParamsExprName(Value,Params,Access);
|
||||
exit;
|
||||
end
|
||||
else if Value.ClassType=TParamsExpr then
|
||||
begin
|
||||
SubParams:=TParamsExpr(Value);
|
||||
// e.g. Name()[] or Name[][] or [][]
|
||||
ResolveExpr(SubParams,rraRead);
|
||||
ComputeElement(SubParams,ResolvedEl,[rcNoImplicitProc,rcSetReferenceFlags]);
|
||||
if Value.CustomData=nil then
|
||||
CreateReference(ResolvedEl.LoTypeEl,Value,Access);
|
||||
end
|
||||
else if Value.InheritsFrom(TUnaryExpr) then
|
||||
begin
|
||||
ResolveExpr(TUnaryExpr(Value).Operand,Access);
|
||||
ComputeElement(Value,ResolvedEl,[rcSetReferenceFlags]);
|
||||
end
|
||||
else if Value is TBinaryExpr then
|
||||
begin
|
||||
// Note: a.b[] is the same as (a.b)[]
|
||||
// Note: a.b[].c is stored as
|
||||
// TBinaryExpr eopSubIdent
|
||||
// / \
|
||||
// left = TParamsExpr right = TPrimitiveExpr 'c'
|
||||
// Value = TBinaryExpr
|
||||
// / \
|
||||
// left = TPrimitiveExpr 'a' right = TPrimitiveExpr 'b'
|
||||
while (Value is TBinaryExpr) and (TBinaryExpr(Value).OpCode=eopSubIdent) do
|
||||
Value:=TBinaryExpr(Value).right;
|
||||
if IsNameExpr(Value) then
|
||||
begin
|
||||
ResolveBinaryExpr(TBinaryExpr(Params.Value),Access);
|
||||
if not (Value.CustomData is TResolvedReference) then
|
||||
RaiseNotYetImplemented(20190115144534,Params);
|
||||
// already resolved
|
||||
exit;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// ToDo: (a+b)[]
|
||||
//ResolveBinaryExpr(TBinaryExpr(Params.Value),rraRead);
|
||||
RaiseNotYetImplemented(20190115144539,Params);
|
||||
end;
|
||||
end
|
||||
else
|
||||
RaiseNotYetImplemented(20160927212610,Value);
|
||||
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveArrayParamsExpr Value=',GetObjName(Value),' ',GetResolverResultDbg(ResolvedEl));
|
||||
{$ENDIF}
|
||||
ResolveArrayParamsArgs(Params,ResolvedEl,Access);
|
||||
end;
|
||||
|
||||
procedure TPasResolver.ResolveArrayParamsExprName(NameExpr: TPasExpr;
|
||||
Params: TParamsExpr; Access: TResolvedRefAccess);
|
||||
// e.g. a.NameExp[]
|
||||
var
|
||||
ArrayName: String;
|
||||
FindData: TPRFindData;
|
||||
Ref: TResolvedReference;
|
||||
DeclEl: TPasElement;
|
||||
Proc, ImplProc: TPasProcedure;
|
||||
ProcScope: TPasProcedureScope;
|
||||
begin
|
||||
ResolvedEl: TPasResolverResult;
|
||||
begin
|
||||
if (NameExpr.ClassType=TPrimitiveExpr)
|
||||
and (TPrimitiveExpr(NameExpr).Kind=pekIdent) then
|
||||
// e.g. Name[]
|
||||
DeclEl:=FindElementWithoutParams(ArrayName,FindData,Value,true);
|
||||
Ref:=CreateReference(DeclEl,Value,Access,@FindData);
|
||||
ArrayName:=TPrimitiveExpr(NameExpr).Value
|
||||
else if (NameExpr.ClassType=TSelfExpr) then
|
||||
// e.g. Self[]
|
||||
ArrayName:='Self';
|
||||
|
||||
DeclEl:=FindElementWithoutParams(ArrayName,FindData,NameExpr,true);
|
||||
Ref:=CreateReference(DeclEl,NameExpr,Access,@FindData);
|
||||
CheckFoundElement(FindData,Ref);
|
||||
if DeclEl is TPasProcedure then
|
||||
begin
|
||||
Proc:=TPasProcedure(DeclEl);
|
||||
if (Access=rraAssign) and (Proc.ProcType is TPasFunctionType)
|
||||
and (Value.ClassType=TPrimitiveExpr)
|
||||
and (Params.Parent.ClassType=TPasImplAssign)
|
||||
and (TPasImplAssign(Params.Parent).left=Params) then
|
||||
begin
|
||||
@ -8723,47 +8872,9 @@ var
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
ComputeElement(Value,ResolvedEl,[rcSetReferenceFlags]);
|
||||
end;
|
||||
|
||||
var
|
||||
Value: TPasExpr;
|
||||
SubParams: TParamsExpr;
|
||||
begin
|
||||
Value:=Params.Value;
|
||||
if Value=nil then
|
||||
RaiseInternalError(20180423093120,GetObjName(Params));
|
||||
if (Value.ClassType=TPrimitiveExpr)
|
||||
and (TPrimitiveExpr(Value).Kind=pekIdent) then
|
||||
// e.g. Name[]
|
||||
ResolveValueName(Value,TPrimitiveExpr(Value).Value)
|
||||
else if (Value.ClassType=TSelfExpr) then
|
||||
// e.g. Self[]
|
||||
ResolveValueName(Value,'Self')
|
||||
else if Value.ClassType=TParamsExpr then
|
||||
begin
|
||||
SubParams:=TParamsExpr(Value);
|
||||
if (SubParams.Kind in [pekArrayParams,pekFuncParams]) then
|
||||
begin
|
||||
// e.g. Name()[] or Name[][]
|
||||
ResolveExpr(SubParams,rraRead);
|
||||
ComputeElement(SubParams,ResolvedEl,[rcNoImplicitProc,rcSetReferenceFlags]);
|
||||
if Value.CustomData=nil then
|
||||
CreateReference(ResolvedEl.LoTypeEl,Value,Access);
|
||||
end
|
||||
else
|
||||
RaiseNotYetImplemented(20161010194925,Value);
|
||||
end
|
||||
else if Value.InheritsFrom(TUnaryExpr) then
|
||||
begin
|
||||
ResolveExpr(TUnaryExpr(Value).Operand,Access);
|
||||
ComputeElement(Value,ResolvedEl,[rcSetReferenceFlags]);
|
||||
end
|
||||
else
|
||||
RaiseNotYetImplemented(20160927212610,Value);
|
||||
|
||||
ComputeElement(NameExpr,ResolvedEl,[rcSetReferenceFlags]);
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveArrayParamsExpr Value=',GetObjName(Value),' ',GetResolverResultDbg(ResolvedEl));
|
||||
writeln('TPasResolver.ResolveArrayParamsExprName NameExp=',GetObjName(NameExpr),' ',GetResolverResultDbg(ResolvedEl));
|
||||
{$ENDIF}
|
||||
ResolveArrayParamsArgs(Params,ResolvedEl,Access);
|
||||
end;
|
||||
@ -10615,34 +10726,10 @@ var
|
||||
ArrayEl: TPasArrayType;
|
||||
ArgNo: Integer;
|
||||
OrigResolved: TPasResolverResult;
|
||||
SubParams: TParamsExpr;
|
||||
ClassOrRecordScope: TPasClassOrRecordScope;
|
||||
begin
|
||||
if Params.Value.CustomData is TResolvedReference then
|
||||
begin
|
||||
// e.g. Name[]
|
||||
ComputeElement(Params.Value,ResolvedEl,
|
||||
Flags-[rcNoImplicitProc,rcNoImplicitProcType],StartEl);
|
||||
end
|
||||
else if Params.Value.ClassType=TParamsExpr then
|
||||
begin
|
||||
SubParams:=TParamsExpr(Params.Value);
|
||||
if SubParams.Kind in [pekArrayParams,pekFuncParams] then
|
||||
begin
|
||||
// e.g. Name()[] or Name[][]
|
||||
ComputeElement(SubParams,ResolvedEl,
|
||||
Flags-[rcNoImplicitProc,rcNoImplicitProcType],StartEl);
|
||||
end
|
||||
else
|
||||
RaiseNotYetImplemented(20161010195646,SubParams);
|
||||
end
|
||||
else if Params.Value.ClassType=TUnaryExpr then
|
||||
begin
|
||||
ComputeElement(Params.Value,ResolvedEl,
|
||||
Flags-[rcNoImplicitProc,rcNoImplicitProcType],StartEl);
|
||||
end
|
||||
else
|
||||
RaiseNotYetImplemented(20160928174144,Params);
|
||||
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ComputeArrayParams ResolvedEl=',GetResolverResultDbg(ResolvedEl));
|
||||
@ -10766,9 +10853,9 @@ var
|
||||
Param0: TPasExpr;
|
||||
ClassOrRec: TPasMembersType;
|
||||
begin
|
||||
if Params.Value.CustomData is TResolvedReference then
|
||||
begin
|
||||
Ref:=TResolvedReference(Params.Value.CustomData);
|
||||
Ref:=GetParamsValueRef(Params);
|
||||
if Ref=nil then
|
||||
RaiseNotYetImplemented(20160928174124,Params);
|
||||
DeclEl:=Ref.Declaration;
|
||||
if DeclEl.ClassType=TPasUnresolvedSymbolRef then
|
||||
begin
|
||||
@ -10880,9 +10967,6 @@ begin
|
||||
else
|
||||
RaiseNotYetImplemented(20160928180048,Params,GetResolverResultDbg(ResolvedEl));
|
||||
end;
|
||||
end
|
||||
else
|
||||
RaiseNotYetImplemented(20160928174124,Params);
|
||||
end;
|
||||
|
||||
procedure TPasResolver.ComputeTypeCast(ToLoType, ToHiType: TPasType;
|
||||
@ -12120,6 +12204,7 @@ begin
|
||||
{$ENDIF}
|
||||
if (Result=nil) and ([refConst,refConstExt]*Flags<>[]) then
|
||||
RaiseConstantExprExp(20170518213616,Expr);
|
||||
if Sender=nil then ;
|
||||
end;
|
||||
|
||||
function TPasResolver.OnExprEvalParams(Sender: TResExprEvaluator;
|
||||
@ -12214,6 +12299,7 @@ begin
|
||||
pekSet: ;
|
||||
end;
|
||||
if Flags=[] then ;
|
||||
if Sender=nil then ;
|
||||
end;
|
||||
|
||||
procedure TPasResolver.OnRangeCheckEl(Sender: TResExprEvaluator;
|
||||
@ -12223,6 +12309,7 @@ begin
|
||||
if (MsgType=mtWarning)
|
||||
and (bsRangeChecks in CurrentParser.Scanner.CurrentBoolSwitches) then
|
||||
MsgType:=mtError;
|
||||
if Sender=nil then ;
|
||||
end;
|
||||
|
||||
function TPasResolver.EvalBaseTypeCast(Params: TParamsExpr;
|
||||
@ -12992,6 +13079,7 @@ procedure TPasResolver.BI_Assigned_OnGetCallResult(Proc: TResElDataBuiltInProc;
|
||||
begin
|
||||
SetResolverIdentifier(ResolvedEl,btBoolean,Proc.Proc,
|
||||
FBaseTypes[btBoolean],FBaseTypes[btBoolean],[rrfReadable]);
|
||||
if Params=nil then ;
|
||||
end;
|
||||
|
||||
procedure TPasResolver.BI_Assigned_OnFinishParamsExpr(
|
||||
@ -14954,7 +15042,7 @@ begin
|
||||
Scope.IterateElements(AName,Scope,OnIterateElement,Data,Abort);
|
||||
if Abort then
|
||||
exit;
|
||||
if Scope is TPasSubScope then break;
|
||||
if Scope is TPasSubExprScope then break;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -15535,7 +15623,7 @@ end;
|
||||
|
||||
procedure TPasResolver.Clear;
|
||||
begin
|
||||
RestoreSubScopes(0);
|
||||
RestoreSubExprScopes(0);
|
||||
// clear stack, keep DefaultScope
|
||||
while (FScopeCount>0) and (FTopScope<>DefaultScope) do
|
||||
PopScope;
|
||||
@ -16046,11 +16134,11 @@ begin
|
||||
Result:=WithExprScope;
|
||||
end;
|
||||
|
||||
procedure TPasResolver.ResetSubScopes(out Depth: integer);
|
||||
procedure TPasResolver.ResetSubExprScopes(out Depth: integer);
|
||||
// move all sub scopes from Scopes to SubScopes
|
||||
begin
|
||||
Depth:=FSubScopeCount;
|
||||
while TopScope is TPasSubScope do
|
||||
while TopScope is TPasSubExprScope do
|
||||
begin
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResetSubScopes moving ',TopScope.ClassName,' ScopeCount=',ScopeCount,' SubScopeCount=',FSubScopeCount);
|
||||
@ -16068,7 +16156,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPasResolver.RestoreSubScopes(Depth: integer);
|
||||
procedure TPasResolver.RestoreSubExprScopes(Depth: integer);
|
||||
// restore sub scopes
|
||||
begin
|
||||
while FSubScopeCount>Depth do
|
||||
@ -20869,6 +20957,25 @@ begin
|
||||
Result:=(Ref.Context as TResolvedRefCtxConstructor).Typ as TPasMembersType;
|
||||
end;
|
||||
|
||||
function TPasResolver.GetParamsValueRef(Params: TParamsExpr): TResolvedReference;
|
||||
var
|
||||
El: TPasExpr;
|
||||
begin
|
||||
Result:=nil;
|
||||
if Params=nil then exit;
|
||||
El:=Params.Value;
|
||||
while El<>nil do
|
||||
begin
|
||||
if El.CustomData is TResolvedReference then
|
||||
exit(TResolvedReference(El.CustomData));
|
||||
if (El is TBinaryExpr)
|
||||
and (TBinaryExpr(El).OpCode=eopSubIdent) then
|
||||
El:=TBinaryExpr(El).right
|
||||
else
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPasResolver.IsDynArray(TypeEl: TPasType; OptionalOpenArray: boolean
|
||||
): boolean;
|
||||
begin
|
||||
|
@ -341,8 +341,6 @@ type
|
||||
function CreateBinaryExpr(AParent : TPasElement; xleft, xright: TPasExpr; AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos): TBinaryExpr; overload;
|
||||
procedure AddToBinaryExprChain(var ChainFirst: TPasExpr;
|
||||
Element: TPasExpr; AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos);
|
||||
procedure AddParamsToBinaryExprChain(var ChainFirst: TPasExpr;
|
||||
Params: TParamsExpr);
|
||||
{$IFDEF VerbosePasParser}
|
||||
procedure WriteBinaryExprChain(Prefix: string; First, Last: TPasExpr);
|
||||
{$ENDIF}
|
||||
@ -2355,9 +2353,9 @@ begin
|
||||
if CurToken in [tkIdentifier,tktrue,tkfalse,tkself] then // true and false are sub identifiers as well
|
||||
begin
|
||||
aName:=aName+'.'+CurTokenString;
|
||||
expr:=CreatePrimitiveExpr(AParent,pekIdent,CurTokenString);
|
||||
AddToBinaryExprChain(Result,expr,eopSubIdent,ScrPos);
|
||||
Func:=expr;
|
||||
Expr:=CreatePrimitiveExpr(AParent,pekIdent,CurTokenString);
|
||||
AddToBinaryExprChain(Result,Expr,eopSubIdent,ScrPos);
|
||||
Func:=Expr;
|
||||
NextToken;
|
||||
end
|
||||
else
|
||||
@ -2373,14 +2371,18 @@ begin
|
||||
else
|
||||
Params:=ParseParams(AParent,pekArrayParams);
|
||||
if not Assigned(Params) then Exit;
|
||||
AddParamsToBinaryExprChain(Result,Params);
|
||||
Params.Value:=Result;
|
||||
Result.Parent:=Params;
|
||||
Result:=Params;
|
||||
CanSpecialize:=false;
|
||||
Func:=nil;
|
||||
end;
|
||||
tkCaret:
|
||||
begin
|
||||
Result:=CreateUnaryExpr(AParent,Result,TokenToExprOp(CurToken));
|
||||
NextToken;
|
||||
CanSpecialize:=false;
|
||||
Func:=nil;
|
||||
end;
|
||||
tkLessThan:
|
||||
begin
|
||||
@ -2402,6 +2404,7 @@ begin
|
||||
CanSpecialize:=false;
|
||||
NextToken;
|
||||
end;
|
||||
Func:=nil;
|
||||
end
|
||||
else
|
||||
break;
|
||||
@ -2568,26 +2571,40 @@ begin
|
||||
CheckToken(tkBraceClose);
|
||||
end;
|
||||
NextToken;
|
||||
// for expressions like (ppdouble)^^;
|
||||
while (CurToken=tkCaret) do
|
||||
repeat
|
||||
case CurToken of
|
||||
tkCaret:
|
||||
begin
|
||||
// for expressions like (ppdouble)^^;
|
||||
x:=CreateUnaryExpr(AParent,x, TokenToExprOp(tkCaret));
|
||||
NextToken;
|
||||
end;
|
||||
// for expressions like (PChar(a)+10)[0];
|
||||
if (CurToken=tkSquaredBraceOpen) then
|
||||
tkBraceOpen:
|
||||
begin
|
||||
// for expressions like (a+b)(0);
|
||||
ArrParams:=ParseParams(AParent,pekFuncParams,False);
|
||||
ArrParams.Value:=x;
|
||||
x.Parent:=ArrParams;
|
||||
x:=ArrParams;
|
||||
end;
|
||||
tkSquaredBraceOpen:
|
||||
begin
|
||||
// for expressions like (PChar(a)+10)[0];
|
||||
ArrParams:=ParseParams(AParent,pekArrayParams,False);
|
||||
ArrParams.Value:=x;
|
||||
x.Parent:=ArrParams;
|
||||
x:=ArrParams;
|
||||
end;
|
||||
// for expressions like (TObject(m)).Free;
|
||||
if (CurToken=tkDot) then
|
||||
tkDot:
|
||||
begin
|
||||
// for expressions like (TObject(m)).Free;
|
||||
NextToken;
|
||||
x:=CreateBinaryExpr(AParent,x, ParseExprOperand(AParent), TokenToExprOp(tkDot));
|
||||
end
|
||||
else
|
||||
break;
|
||||
end;
|
||||
until false;
|
||||
end
|
||||
else
|
||||
begin
|
||||
@ -5221,7 +5238,9 @@ function TPasParser.ParseProperty(Parent: TPasElement; const AName: String;
|
||||
Result := Result + '[';
|
||||
Params:=TParamsExpr(CreateElement(TParamsExpr,'',aParent));
|
||||
Params.Kind:=pekArrayParams;
|
||||
AddParamsToBinaryExprChain(Expr,Params);
|
||||
Params.Value:=Expr;
|
||||
Expr.Parent:=Params;
|
||||
Expr:=Params;
|
||||
NextToken;
|
||||
case CurToken of
|
||||
tkChar: Param:=CreatePrimitiveExpr(aParent,pekString, CurTokenText);
|
||||
@ -7042,37 +7061,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPasParser.AddParamsToBinaryExprChain(var ChainFirst: TPasExpr;
|
||||
Params: TParamsExpr);
|
||||
// append Params to chain, using the last(right) element as Params.Value
|
||||
var
|
||||
Bin: TBinaryExpr;
|
||||
begin
|
||||
if Params.Value<>nil then
|
||||
ParseExcSyntaxError;
|
||||
if ChainFirst=nil then
|
||||
ParseExcSyntaxError;
|
||||
if ChainFirst is TBinaryExpr then
|
||||
begin
|
||||
Bin:=TBinaryExpr(ChainFirst);
|
||||
if Bin.left=nil then
|
||||
ParseExcSyntaxError;
|
||||
if Bin.right=nil then
|
||||
ParseExcSyntaxError;
|
||||
Params.Value:=Bin.right;
|
||||
Params.Value.Parent:=Params;
|
||||
Bin.right:=Params;
|
||||
Params.Parent:=Bin;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Params.Value:=ChainFirst;
|
||||
Params.Parent:=ChainFirst.Parent;
|
||||
ChainFirst.Parent:=Params;
|
||||
ChainFirst:=Params;
|
||||
end;
|
||||
end;
|
||||
|
||||
{$IFDEF VerbosePasParser}
|
||||
{AllowWriteln}
|
||||
procedure TPasParser.WriteBinaryExprChain(Prefix: string; First, Last: TPasExpr
|
||||
|
@ -96,14 +96,19 @@ type
|
||||
Procedure TestBinaryLessThanEqual;
|
||||
Procedure TestBinaryLargerThan;
|
||||
Procedure TestBinaryLargerThanEqual;
|
||||
procedure TestBinaryFullIdent;
|
||||
procedure TestBinarySubIdent;
|
||||
Procedure TestArrayElement;
|
||||
Procedure TestArrayElementrecord;
|
||||
Procedure TestArrayElementRecord;
|
||||
Procedure TestArrayElement2Dims;
|
||||
Procedure TestFunctionCall;
|
||||
Procedure TestFunctionCall2args;
|
||||
Procedure TestFunctionCallNoArgs;
|
||||
Procedure ParseStrWithFormatFullyQualified;
|
||||
Procedure TestSubIdentStrWithFormat;
|
||||
Procedure TestAPlusCallB;
|
||||
Procedure TestAPlusBBracketFuncParams;
|
||||
Procedure TestAPlusBBracketArrayParams;
|
||||
Procedure TestAPlusBBracketDotC;
|
||||
Procedure TestADotBDotC;
|
||||
Procedure TestRange;
|
||||
Procedure TestBracketsTotal;
|
||||
Procedure TestBracketsLeft;
|
||||
@ -257,7 +262,7 @@ begin
|
||||
AssertExpression('Simple identifier',theExpr,pekIdent,'b');
|
||||
end;
|
||||
|
||||
procedure TTestExpressions.TestBinaryFullIdent;
|
||||
procedure TTestExpressions.TestBinarySubIdent;
|
||||
begin
|
||||
DeclareVar('integer','a');
|
||||
DeclareVar('record x,y : integer; end','b');
|
||||
@ -282,7 +287,7 @@ begin
|
||||
AssertExpression('Simple identifier',p.params[0],pekNumber,'1');
|
||||
end;
|
||||
|
||||
procedure TTestExpressions.TestArrayElementrecord;
|
||||
procedure TTestExpressions.TestArrayElementRecord;
|
||||
|
||||
Var
|
||||
P : TParamsExpr;
|
||||
@ -290,14 +295,15 @@ Var
|
||||
begin
|
||||
DeclareVar('record a : array[1..2] of integer; end ','b');
|
||||
ParseExpression('b.a[1]');
|
||||
B:=AssertExpression('Binary of record',TheExpr,pekBinary,TBinaryExpr) as TBinaryExpr;
|
||||
AssertEquals('Name is Subident',eopSubIdent,B.Opcode);
|
||||
AssertExpression('Name of array',B.Left,pekIdent,'b');
|
||||
P:=TParamsExpr(AssertExpression('Simple identifier',B.right,pekArrayParams,TParamsExpr));
|
||||
AssertExpression('Name of array',P.Value,pekIdent,'a');
|
||||
P:=TParamsExpr(AssertExpression('Array Param',TheExpr,pekArrayParams,TParamsExpr));
|
||||
TAssert.AssertSame('P.value.parent=P',P,P.Value.Parent);
|
||||
AssertEquals('One dimension',1,Length(P.params));
|
||||
AssertExpression('Simple identifier',P.params[0],pekNumber,'1');
|
||||
|
||||
B:=TBinaryExpr(AssertExpression('Binary of record',P.Value,pekBinary,TBinaryExpr));
|
||||
AssertEquals('Name is Subident',eopSubIdent,B.Opcode);
|
||||
AssertExpression('Name of array',B.Left,pekIdent,'b');
|
||||
AssertExpression('Name of array',B.right,pekIdent,'a');
|
||||
TAssert.AssertSame('B.left.parent=B',B,B.left.Parent);
|
||||
TAssert.AssertSame('B.right.parent=B',B,B.right.Parent);
|
||||
end;
|
||||
@ -1124,7 +1130,7 @@ begin
|
||||
AssertNotNull('Have left',AOperand);
|
||||
end;
|
||||
|
||||
Procedure TTestExpressions.ParseStrWithFormatFullyQualified;
|
||||
procedure TTestExpressions.TestSubIdentStrWithFormat;
|
||||
|
||||
Var
|
||||
P : TParamsExpr;
|
||||
@ -1134,12 +1140,113 @@ begin
|
||||
DeclareVar('string','a');
|
||||
DeclareVar('integer','i');
|
||||
ParseExpression('system.str(i:0:3,a)');
|
||||
B:=TBinaryExpr(AssertExpression('Binary identifier',theExpr,pekBinary,TBinaryExpr));
|
||||
P:=TParamsExpr(AssertExpression('Simple identifier',B.Right,pekFuncParams,TParamsExpr));
|
||||
AssertExpression('Name of function',P.Value,pekIdent,'str');
|
||||
P:=TParamsExpr(AssertExpression('Params',TheExpr,pekFuncParams,TParamsExpr));
|
||||
TAssert.AssertSame('P.value.parent=P',P,P.Value.Parent);
|
||||
AssertEquals('2 argument',2,Length(p.params));
|
||||
AssertExpression('Simple identifier',p.params[0],pekIdent,'i');
|
||||
AssertExpression('Simple identifier',p.params[1],pekIdent,'a');
|
||||
TAssert.AssertSame('P.params[0].parent=P',P,P.params[0].Parent);
|
||||
TAssert.AssertSame('P.params[1].parent=P',P,P.params[1].Parent);
|
||||
B:=TBinaryExpr(AssertExpression('Binary identifier',P.Value,pekBinary,TBinaryExpr));
|
||||
AssertExpression('Name of unit',B.left,pekIdent,'system');
|
||||
AssertExpression('Name of function',B.right,pekIdent,'str');
|
||||
TAssert.AssertSame('B.left.parent=B',B,B.left.Parent);
|
||||
TAssert.AssertSame('B.right.parent=B',B,B.right.Parent);
|
||||
end;
|
||||
|
||||
procedure TTestExpressions.TestAPlusCallB;
|
||||
var
|
||||
B: TBinaryExpr;
|
||||
P: TParamsExpr;
|
||||
begin
|
||||
DeclareVar('string','a');
|
||||
DeclareVar('integer','b');
|
||||
ParseExpression('a+b(1)');
|
||||
B:=TBinaryExpr(AssertExpression('Binary identifier',TheExpr,pekBinary,TBinaryExpr));
|
||||
AssertExpression('left a',B.left,pekIdent,'a');
|
||||
TAssert.AssertSame('B.left.parent=B',B,B.left.Parent);
|
||||
TAssert.AssertSame('B.right.parent=B',B,B.right.Parent);
|
||||
P:=TParamsExpr(AssertExpression('Params',B.right,pekFuncParams,TParamsExpr));
|
||||
TAssert.AssertSame('P.value.parent=P',P,P.Value.Parent);
|
||||
AssertEquals('1 argument',1,Length(p.params));
|
||||
AssertExpression('param 1',p.params[0],pekNumber,'1');
|
||||
end;
|
||||
|
||||
procedure TTestExpressions.TestAPlusBBracketFuncParams;
|
||||
var
|
||||
P: TParamsExpr;
|
||||
B: TBinaryExpr;
|
||||
begin
|
||||
DeclareVar('string','a');
|
||||
DeclareVar('integer','b');
|
||||
ParseExpression('(a+b)(1)');
|
||||
P:=TParamsExpr(AssertExpression('Params',TheExpr,pekFuncParams,TParamsExpr));
|
||||
TAssert.AssertSame('P.value.parent=P',P,P.Value.Parent);
|
||||
AssertEquals('1 argument',1,Length(p.params));
|
||||
AssertExpression('param 1',p.params[0],pekNumber,'1');
|
||||
B:=TBinaryExpr(AssertExpression('Binary identifier',P.Value,pekBinary,TBinaryExpr));
|
||||
TAssert.AssertSame('B.left.parent=B',B,B.left.Parent);
|
||||
TAssert.AssertSame('B.right.parent=B',B,B.right.Parent);
|
||||
AssertExpression('left a',B.left,pekIdent,'a');
|
||||
AssertExpression('right b',B.right,pekIdent,'b');
|
||||
end;
|
||||
|
||||
procedure TTestExpressions.TestAPlusBBracketArrayParams;
|
||||
var
|
||||
B: TBinaryExpr;
|
||||
P: TParamsExpr;
|
||||
begin
|
||||
DeclareVar('string','a');
|
||||
DeclareVar('integer','b');
|
||||
ParseExpression('(a+b)[1]');
|
||||
P:=TParamsExpr(AssertExpression('Params',TheExpr,pekArrayParams,TParamsExpr));
|
||||
TAssert.AssertSame('P.value.parent=P',P,P.Value.Parent);
|
||||
AssertEquals('1 argument',1,Length(p.params));
|
||||
AssertExpression('param 1',p.params[0],pekNumber,'1');
|
||||
|
||||
B:=TBinaryExpr(AssertExpression('Binary identifier',P.Value,pekBinary,TBinaryExpr));
|
||||
TAssert.AssertSame('B.left.parent=B',B,B.left.Parent);
|
||||
TAssert.AssertSame('B.right.parent=B',B,B.right.Parent);
|
||||
AssertExpression('left a',B.left,pekIdent,'a');
|
||||
AssertExpression('right b',B.right,pekIdent,'b');
|
||||
end;
|
||||
|
||||
procedure TTestExpressions.TestAPlusBBracketDotC;
|
||||
var
|
||||
B, PlusB: TBinaryExpr;
|
||||
begin
|
||||
DeclareVar('string','a');
|
||||
DeclareVar('integer','b');
|
||||
ParseExpression('(a+b).c');
|
||||
B:=TBinaryExpr(AssertExpression('Binary identifier',TheExpr,pekBinary,TBinaryExpr));
|
||||
AssertEquals('().',eopSubIdent,B.OpCode);
|
||||
TAssert.AssertSame('B.left.parent=B',B,B.left.Parent);
|
||||
TAssert.AssertSame('B.right.parent=B',B,B.right.Parent);
|
||||
AssertExpression('right c',B.right,pekIdent,'c');
|
||||
|
||||
PlusB:=TBinaryExpr(AssertExpression('Binary identifier',B.left,pekBinary,TBinaryExpr));
|
||||
TAssert.AssertSame('PlusB.left.parent=PlusB',PlusB,PlusB.left.Parent);
|
||||
TAssert.AssertSame('PlusB.right.parent=PlusB',PlusB,PlusB.right.Parent);
|
||||
AssertExpression('left a',PlusB.left,pekIdent,'a');
|
||||
AssertExpression('right b',PlusB.right,pekIdent,'b');
|
||||
end;
|
||||
|
||||
procedure TTestExpressions.TestADotBDotC;
|
||||
var
|
||||
B, SubB: TBinaryExpr;
|
||||
begin
|
||||
ParseExpression('a.b.c');
|
||||
B:=TBinaryExpr(AssertExpression('Binary identifier',TheExpr,pekBinary,TBinaryExpr));
|
||||
AssertEquals('dot expr',eopSubIdent,B.OpCode);
|
||||
TAssert.AssertSame('B.left.parent=B',B,B.left.Parent);
|
||||
TAssert.AssertSame('B.right.parent=B',B,B.right.Parent);
|
||||
AssertExpression('right c',B.right,pekIdent,'c');
|
||||
|
||||
SubB:=TBinaryExpr(AssertExpression('Binary identifier',B.left,pekBinary,TBinaryExpr));
|
||||
TAssert.AssertSame('PlusB.left.parent=PlusB',SubB,SubB.left.Parent);
|
||||
TAssert.AssertSame('PlusB.right.parent=PlusB',SubB,SubB.right.Parent);
|
||||
AssertExpression('left a',SubB.left,pekIdent,'a');
|
||||
AssertExpression('right b',SubB.right,pekIdent,'b');
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
Loading…
Reference in New Issue
Block a user