mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 10:29:24 +02:00
fcl-passrc: started anonymous methods
git-svn-id: trunk@40475 -
This commit is contained in:
parent
b82026dcf8
commit
0fe9e24297
@ -1824,6 +1824,7 @@ type
|
|||||||
function GetPasPropertyStoredExpr(El: TPasProperty): TPasExpr;
|
function GetPasPropertyStoredExpr(El: TPasProperty): TPasExpr;
|
||||||
function GetPasPropertyDefaultExpr(El: TPasProperty): TPasExpr;
|
function GetPasPropertyDefaultExpr(El: TPasProperty): TPasExpr;
|
||||||
function GetPasClassAncestor(ClassEl: TPasClassType; SkipAlias: boolean): TPasType;
|
function GetPasClassAncestor(ClassEl: TPasClassType; SkipAlias: boolean): TPasType;
|
||||||
|
function GetParentProcBody(El: TPasElement): TProcedureBody;
|
||||||
function ProcHasImplElements(Proc: TPasProcedure): boolean; virtual;
|
function ProcHasImplElements(Proc: TPasProcedure): boolean; virtual;
|
||||||
function IndexOfImplementedInterface(ClassEl: TPasClassType; aType: TPasType): integer;
|
function IndexOfImplementedInterface(ClassEl: TPasClassType; aType: TPasType): integer;
|
||||||
function GetLoop(El: TPasElement): TPasImplElement;
|
function GetLoop(El: TPasElement): TPasImplElement;
|
||||||
@ -2072,8 +2073,8 @@ begin
|
|||||||
dec(Indent,2);
|
dec(Indent,2);
|
||||||
end;
|
end;
|
||||||
Result:=Result+')';
|
Result:=Result+')';
|
||||||
if El is TPasFunction then
|
if (El is TPasProcedure) and (TPasProcedure(El).ProcType is TPasFunctionType) then
|
||||||
Result:=Result+':'+GetTreeDbg(TPasFunctionType(TPasFunction(El).ProcType).ResultEl,Indent);
|
Result:=Result+':'+GetTreeDbg(TPasFunctionType(TPasProcedure(El).ProcType).ResultEl,Indent);
|
||||||
if TPasProcedureType(El).IsOfObject then
|
if TPasProcedureType(El).IsOfObject then
|
||||||
Result:=Result+' '+ProcTypeModifiers[ptmOfObject];
|
Result:=Result+' '+ProcTypeModifiers[ptmOfObject];
|
||||||
if TPasProcedureType(El).IsNested then
|
if TPasProcedureType(El).IsNested then
|
||||||
@ -2273,6 +2274,10 @@ begin
|
|||||||
Result:='class procedure'
|
Result:='class procedure'
|
||||||
else if C=TPasClassFunction then
|
else if C=TPasClassFunction then
|
||||||
Result:='class function'
|
Result:='class function'
|
||||||
|
else if C=TPasAnonymousProcedure then
|
||||||
|
Result:='anonymous procedure'
|
||||||
|
else if C=TPasAnonymousFunction then
|
||||||
|
Result:='anonymous function'
|
||||||
else if C=TPasMethodResolution then
|
else if C=TPasMethodResolution then
|
||||||
Result:='method resolution'
|
Result:='method resolution'
|
||||||
else if C=TInterfaceSection then
|
else if C=TInterfaceSection then
|
||||||
@ -5310,13 +5315,17 @@ var
|
|||||||
pm: TProcedureModifier;
|
pm: TProcedureModifier;
|
||||||
ptm: TProcTypeModifier;
|
ptm: TProcTypeModifier;
|
||||||
ObjKind: TPasObjKind;
|
ObjKind: TPasObjKind;
|
||||||
|
ParentBody: TProcedureBody;
|
||||||
begin
|
begin
|
||||||
if (El.Parent is TPasProcedure) and (TPasProcedure(El.Parent).ProcType=El) then
|
if El.Parent is TPasProcedure then
|
||||||
|
Proc:=TPasProcedure(El.Parent)
|
||||||
|
else
|
||||||
|
Proc:=nil;
|
||||||
|
if (Proc<>nil) and (Proc.ProcType=El) then
|
||||||
begin
|
begin
|
||||||
// finished header of a procedure declaration
|
// finished header of a procedure declaration
|
||||||
// -> search the best fitting proc
|
// -> search the best fitting proc
|
||||||
CheckTopScope(FScopeClass_Proc);
|
CheckTopScope(FScopeClass_Proc);
|
||||||
Proc:=TPasProcedure(El.Parent);
|
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
writeln('TPasResolver.FinishProcedureHeader El=',GetTreeDbg(El),' ',GetElementSourcePosStr(El),' IsForward=',Proc.IsForward,' Parent=',GetObjName(El.Parent));
|
writeln('TPasResolver.FinishProcedureHeader El=',GetTreeDbg(El),' ',GetElementSourcePosStr(El),' IsForward=',Proc.IsForward,' Parent=',GetObjName(El.Parent));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -5325,13 +5334,14 @@ begin
|
|||||||
if (proProcTypeWithoutIsNested in Options) and El.IsNested then
|
if (proProcTypeWithoutIsNested in Options) and El.IsNested then
|
||||||
RaiseInvalidProcTypeModifier(20170402120811,El,ptmIsNested,El);
|
RaiseInvalidProcTypeModifier(20170402120811,El,ptmIsNested,El);
|
||||||
|
|
||||||
if (Proc.Parent.ClassType=TProcedureBody) then
|
ParentBody:=GetParentProcBody(Proc.Parent);
|
||||||
|
if (ParentBody<>nil) then
|
||||||
begin
|
begin
|
||||||
// nested sub proc
|
// nested sub proc
|
||||||
if not (proProcTypeWithoutIsNested in Options) then
|
if not (proProcTypeWithoutIsNested in Options) then
|
||||||
El.IsNested:=true;
|
El.IsNested:=true;
|
||||||
// inherit 'of Object'
|
// inherit 'of Object'
|
||||||
ParentProc:=Proc.Parent.Parent as TPasProcedure;
|
ParentProc:=ParentBody.Parent as TPasProcedure;
|
||||||
if ParentProc.ProcType.IsOfObject then
|
if ParentProc.ProcType.IsOfObject then
|
||||||
El.IsOfObject:=true;
|
El.IsOfObject:=true;
|
||||||
end;
|
end;
|
||||||
@ -5393,7 +5403,7 @@ begin
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
// intf proc, forward proc, proc body, method body
|
// intf proc, forward proc, proc body, method body, anonymous proc
|
||||||
if Proc.IsAbstract then
|
if Proc.IsAbstract then
|
||||||
RaiseInvalidProcModifier(20170216151634,Proc,pmAbstract,Proc);
|
RaiseInvalidProcModifier(20170216151634,Proc,pmAbstract,Proc);
|
||||||
if Proc.IsVirtual then
|
if Proc.IsVirtual then
|
||||||
@ -5405,8 +5415,12 @@ begin
|
|||||||
if Proc.IsStatic then
|
if Proc.IsStatic then
|
||||||
RaiseInvalidProcTypeModifier(20170216151640,El,ptmStatic,El);
|
RaiseInvalidProcTypeModifier(20170216151640,El,ptmStatic,El);
|
||||||
if (not HasDots)
|
if (not HasDots)
|
||||||
and (Proc.ClassType<>TPasProcedure)
|
and (Proc.GetProcTypeEnum in [
|
||||||
and (Proc.ClassType<>TPasFunction) then
|
ptClassOperator,
|
||||||
|
ptConstructor, ptDestructor,
|
||||||
|
ptClassProcedure, ptClassFunction,
|
||||||
|
ptClassConstructor, ptClassDestructor
|
||||||
|
]) then
|
||||||
RaiseXExpectedButYFound(20170419232724,'full method name','short name',El);
|
RaiseXExpectedButYFound(20170419232724,'full method name','short name',El);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -5418,7 +5432,8 @@ begin
|
|||||||
|
|
||||||
// finish interface/implementation/nested procedure/method declaration
|
// finish interface/implementation/nested procedure/method declaration
|
||||||
|
|
||||||
if not IsValidIdent(ProcName) then
|
if not (Proc.GetProcTypeEnum in [ptAnonymousProcedure,ptAnonymousFunction])
|
||||||
|
and not IsValidIdent(ProcName) then
|
||||||
RaiseNotYetImplemented(20160922163407,El);
|
RaiseNotYetImplemented(20160922163407,El);
|
||||||
|
|
||||||
if El is TPasFunctionType then
|
if El is TPasFunctionType then
|
||||||
@ -5436,7 +5451,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// finish interface/implementation/nested procedure
|
// finish interface/implementation/nested procedure
|
||||||
if ProcNeedsBody(Proc) then
|
if (ProcName<>'') and ProcNeedsBody(Proc) then
|
||||||
begin
|
begin
|
||||||
// check if there is a forward declaration
|
// check if there is a forward declaration
|
||||||
ParentScope:=Scopes[ScopeCount-2];
|
ParentScope:=Scopes[ScopeCount-2];
|
||||||
@ -5483,13 +5498,16 @@ begin
|
|||||||
StoreScannerFlagsInProc(ProcScope);
|
StoreScannerFlagsInProc(ProcScope);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// check for invalid overloads
|
if ProcName<>'' then
|
||||||
FindData:=Default(TFindOverloadProcData);
|
begin
|
||||||
FindData.Proc:=Proc;
|
// check for invalid overloads
|
||||||
FindData.Args:=Proc.ProcType.Args;
|
FindData:=Default(TFindOverloadProcData);
|
||||||
FindData.Kind:=fopkProc;
|
FindData.Proc:=Proc;
|
||||||
Abort:=false;
|
FindData.Args:=Proc.ProcType.Args;
|
||||||
IterateElements(ProcName,@OnFindOverloadProc,@FindData,Abort);
|
FindData.Kind:=fopkProc;
|
||||||
|
Abort:=false;
|
||||||
|
IterateElements(ProcName,@OnFindOverloadProc,@FindData,Abort);
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
else if El.Name<>'' then
|
else if El.Name<>'' then
|
||||||
begin
|
begin
|
||||||
@ -6836,12 +6854,12 @@ begin
|
|||||||
else
|
else
|
||||||
RaiseNotYetImplemented(20170203161826,ImplProc);
|
RaiseNotYetImplemented(20170203161826,ImplProc);
|
||||||
end;
|
end;
|
||||||
if DeclProc is TPasFunction then
|
if DeclProc.ProcType is TPasFunctionType then
|
||||||
begin
|
begin
|
||||||
// redirect implementation 'Result' to declaration FuncType.ResultEl
|
// redirect implementation 'Result' to declaration FuncType.ResultEl
|
||||||
Identifier:=ImplProcScope.FindLocalIdentifier(ResolverResultVar);
|
Identifier:=ImplProcScope.FindLocalIdentifier(ResolverResultVar);
|
||||||
if Identifier.Element is TPasResultElement then
|
if Identifier.Element is TPasResultElement then
|
||||||
Identifier.Element:=TPasFunction(DeclProc).FuncType.ResultEl;
|
Identifier.Element:=TPasFunctionType(DeclProc.ProcType).ResultEl;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -6899,11 +6917,11 @@ begin
|
|||||||
RaiseXExpectedButYFound(20170216151729,DeclProc.TypeName,ImplProc.TypeName,ImplProc);
|
RaiseXExpectedButYFound(20170216151729,DeclProc.TypeName,ImplProc.TypeName,ImplProc);
|
||||||
if ImplProc.CallingConvention<>DeclProc.CallingConvention then
|
if ImplProc.CallingConvention<>DeclProc.CallingConvention then
|
||||||
RaiseMsg(20170216151731,nCallingConventionMismatch,sCallingConventionMismatch,[],ImplProc);
|
RaiseMsg(20170216151731,nCallingConventionMismatch,sCallingConventionMismatch,[],ImplProc);
|
||||||
if ImplProc is TPasFunction then
|
if ImplProc.ProcType is TPasFunctionType then
|
||||||
begin
|
begin
|
||||||
// check result type
|
// check result type
|
||||||
ImplResult:=TPasFunction(ImplProc).FuncType.ResultEl.ResultType;
|
ImplResult:=TPasFunctionType(ImplProc.ProcType).ResultEl.ResultType;
|
||||||
DeclResult:=TPasFunction(DeclProc).FuncType.ResultEl.ResultType;
|
DeclResult:=TPasFunctionType(DeclProc.ProcType).ResultEl.ResultType;
|
||||||
|
|
||||||
if not CheckElTypeCompatibility(ImplResult,DeclResult,prraSimple) then
|
if not CheckElTypeCompatibility(ImplResult,DeclResult,prraSimple) then
|
||||||
RaiseIncompatibleType(20170216151734,nResultTypeMismatchExpectedButFound,
|
RaiseIncompatibleType(20170216151734,nResultTypeMismatchExpectedButFound,
|
||||||
@ -7827,6 +7845,7 @@ begin
|
|||||||
[],El);
|
[],El);
|
||||||
ResolveRecordValues(TRecordValues(El));
|
ResolveRecordValues(TRecordValues(El));
|
||||||
end
|
end
|
||||||
|
else if ElClass=TProcedureExpr then
|
||||||
else
|
else
|
||||||
RaiseNotYetImplemented(20170222184329,El);
|
RaiseNotYetImplemented(20170222184329,El);
|
||||||
|
|
||||||
@ -7882,7 +7901,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
// examples: funca or @proca or a.funca or @a.funca ...
|
// examples: funca or @proca or a.funca or @a.funca ...
|
||||||
Proc:=TPasProcedure(DeclEl);
|
Proc:=TPasProcedure(DeclEl);
|
||||||
if (Access=rraAssign) and (Proc is TPasFunction)
|
if (Access=rraAssign) and (Proc.ProcType is TPasFunctionType)
|
||||||
and (El.ClassType=TPrimitiveExpr)
|
and (El.ClassType=TPrimitiveExpr)
|
||||||
and (El.Parent.ClassType=TPasImplAssign)
|
and (El.Parent.ClassType=TPasImplAssign)
|
||||||
and (TPasImplAssign(El.Parent).left=El) then
|
and (TPasImplAssign(El.Parent).left=El) then
|
||||||
@ -7895,7 +7914,7 @@ begin
|
|||||||
if El.HasParent(ImplProc) then
|
if El.HasParent(ImplProc) then
|
||||||
begin
|
begin
|
||||||
// "FuncA:=" within FuncA -> redirect to ResultEl
|
// "FuncA:=" within FuncA -> redirect to ResultEl
|
||||||
Ref.Declaration:=(Proc as TPasFunction).FuncType.ResultEl;
|
Ref.Declaration:=TPasFunctionType(Proc.ProcType).ResultEl;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -8499,7 +8518,7 @@ var
|
|||||||
if DeclEl is TPasProcedure then
|
if DeclEl is TPasProcedure then
|
||||||
begin
|
begin
|
||||||
Proc:=TPasProcedure(DeclEl);
|
Proc:=TPasProcedure(DeclEl);
|
||||||
if (Access=rraAssign) and (Proc is TPasFunction)
|
if (Access=rraAssign) and (Proc.ProcType is TPasFunctionType)
|
||||||
and (Value.ClassType=TPrimitiveExpr)
|
and (Value.ClassType=TPrimitiveExpr)
|
||||||
and (Params.Parent.ClassType=TPasImplAssign)
|
and (Params.Parent.ClassType=TPasImplAssign)
|
||||||
and (TPasImplAssign(Params.Parent).left=Params) then
|
and (TPasImplAssign(Params.Parent).left=Params) then
|
||||||
@ -8512,7 +8531,7 @@ var
|
|||||||
if Params.HasParent(ImplProc) then
|
if Params.HasParent(ImplProc) then
|
||||||
begin
|
begin
|
||||||
// "FuncA[]:=" within FuncA -> redirect to ResultEl
|
// "FuncA[]:=" within FuncA -> redirect to ResultEl
|
||||||
Ref.Declaration:=(Proc as TPasFunction).FuncType.ResultEl;
|
Ref.Declaration:=TPasFunctionType(Proc.ProcType).ResultEl;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -8930,7 +8949,8 @@ begin
|
|||||||
else if (Access in [rraRead,rraParamToUnknownProc])
|
else if (Access in [rraRead,rraParamToUnknownProc])
|
||||||
and ((C=TPrimitiveExpr)
|
and ((C=TPrimitiveExpr)
|
||||||
or (C=TNilExpr)
|
or (C=TNilExpr)
|
||||||
or (C=TBoolConstExpr)) then
|
or (C=TBoolConstExpr)
|
||||||
|
or (C=TProcedureExpr)) then
|
||||||
// ok
|
// ok
|
||||||
else if C=TUnaryExpr then
|
else if C=TUnaryExpr then
|
||||||
AccessExpr(TUnaryExpr(Expr).Operand,Access)
|
AccessExpr(TUnaryExpr(Expr).Operand,Access)
|
||||||
@ -9350,10 +9370,10 @@ begin
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
if not (TopScope is TPasIdentifierScope) then
|
if not (TopScope is TPasIdentifierScope) then
|
||||||
RaiseInvalidScopeForElement(20160922163522,El);
|
RaiseInvalidScopeForElement(20160922163522,El);
|
||||||
// Note: El.ProcType is nil !
|
// Note: El.ProcType is nil ! It is parsed later.
|
||||||
ProcName:=El.Name;
|
ProcName:=El.Name;
|
||||||
HasDot:=Pos('.',ProcName)>1;
|
HasDot:=Pos('.',ProcName)>1;
|
||||||
if not HasDot then
|
if (not HasDot) and (ProcName<>'') then
|
||||||
AddIdentifier(TPasIdentifierScope(TopScope),ProcName,El,pikProc);
|
AddIdentifier(TPasIdentifierScope(TopScope),ProcName,El,pikProc);
|
||||||
ProcScope:=TPasProcedureScope(PushScope(El,FScopeClass_Proc));
|
ProcScope:=TPasProcedureScope(PushScope(El,FScopeClass_Proc));
|
||||||
ProcScope.ModeSwitches:=CurrentParser.CurrentModeswitches;
|
ProcScope.ModeSwitches:=CurrentParser.CurrentModeswitches;
|
||||||
@ -9420,7 +9440,7 @@ begin
|
|||||||
|
|
||||||
ProcScope.VisibilityContext:=CurClassType;
|
ProcScope.VisibilityContext:=CurClassType;
|
||||||
ProcScope.ClassScope:=NoNil(CurClassType.CustomData) as TPasClassScope;
|
ProcScope.ClassScope:=NoNil(CurClassType.CustomData) as TPasClassScope;
|
||||||
end;
|
end;// HasDot=true
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasResolver.AddArgument(El: TPasArgument);
|
procedure TPasResolver.AddArgument(El: TPasArgument);
|
||||||
@ -10500,9 +10520,9 @@ begin
|
|||||||
Proc:=TPasProcedure(ResolvedEl.IdentEl);
|
Proc:=TPasProcedure(ResolvedEl.IdentEl);
|
||||||
if rcConstant in Flags then
|
if rcConstant in Flags then
|
||||||
RaiseConstantExprExp(20170216152637,Params);
|
RaiseConstantExprExp(20170216152637,Params);
|
||||||
if Proc is TPasFunction then
|
if Proc.ProcType is TPasFunctionType then
|
||||||
// function call => return result
|
// function call => return result
|
||||||
ComputeElement(TPasFunction(Proc).FuncType.ResultEl,ResolvedEl,
|
ComputeElement(TPasFunctionType(Proc.ProcType).ResultEl,ResolvedEl,
|
||||||
Flags+[rcNoImplicitProc],StartEl)
|
Flags+[rcNoImplicitProc],StartEl)
|
||||||
else if (Proc.ClassType=TPasConstructor)
|
else if (Proc.ClassType=TPasConstructor)
|
||||||
and (rrfNewInstance in Ref.Flags) then
|
and (rrfNewInstance in Ref.Flags) then
|
||||||
@ -12498,6 +12518,7 @@ var
|
|||||||
ProcScope: TPasProcedureScope;
|
ProcScope: TPasProcedureScope;
|
||||||
ResultEl: TPasResultElement;
|
ResultEl: TPasResultElement;
|
||||||
Flags: TPasResolverComputeFlags;
|
Flags: TPasResolverComputeFlags;
|
||||||
|
CtxProc: TPasProcedure;
|
||||||
begin
|
begin
|
||||||
if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)=0) then
|
if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)=0) then
|
||||||
exit(cExact);
|
exit(cExact);
|
||||||
@ -12515,14 +12536,15 @@ begin
|
|||||||
begin
|
begin
|
||||||
// first param is function result
|
// first param is function result
|
||||||
ProcScope:=TPasProcedureScope(Scopes[i]);
|
ProcScope:=TPasProcedureScope(Scopes[i]);
|
||||||
if not (ProcScope.Element is TPasFunction) then
|
CtxProc:=TPasProcedure(ProcScope.Element);
|
||||||
|
if not (CtxProc.ProcType is TPasFunctionType) then
|
||||||
begin
|
begin
|
||||||
if RaiseOnError then
|
if RaiseOnError then
|
||||||
RaiseMsg(20170216152312,nWrongNumberOfParametersForCallTo,
|
RaiseMsg(20170216152312,nWrongNumberOfParametersForCallTo,
|
||||||
sWrongNumberOfParametersForCallTo,['procedure exit'],Params.Params[0]);
|
sWrongNumberOfParametersForCallTo,['procedure exit'],Params.Params[0]);
|
||||||
exit(cIncompatible);
|
exit(cIncompatible);
|
||||||
end;
|
end;
|
||||||
ResultEl:=(ProcScope.Element as TPasFunction).FuncType.ResultEl;
|
ResultEl:=TPasFunctionType(CtxProc.ProcType).ResultEl;
|
||||||
ComputeElement(ResultEl,ResultResolved,[rcType]);
|
ComputeElement(ResultEl,ResultResolved,[rcType]);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -12937,9 +12959,9 @@ begin
|
|||||||
begin
|
begin
|
||||||
Expr:=TPasVariable(ParamResolved.IdentEl).Expr;
|
Expr:=TPasVariable(ParamResolved.IdentEl).Expr;
|
||||||
if Expr is TArrayValues then
|
if Expr is TArrayValues then
|
||||||
Evaluated:=TResEvalInt.CreateValue(length(TArrayValues(Expr).Values)-1)
|
Evaluated:=TResEvalInt.CreateValue(TMaxPrecInt(length(TArrayValues(Expr).Values))-1)
|
||||||
else if (Expr is TParamsExpr) and (TParamsExpr(Expr).Kind=pekSet) then
|
else if (Expr is TParamsExpr) and (TParamsExpr(Expr).Kind=pekSet) then
|
||||||
Evaluated:=TResEvalInt.CreateValue(length(TParamsExpr(Expr).Params)-1);
|
Evaluated:=TResEvalInt.CreateValue(TMaxPrecInt(length(TParamsExpr(Expr).Params))-1);
|
||||||
if Evaluated=nil then
|
if Evaluated=nil then
|
||||||
RaiseXExpectedButYFound(20170601191003,'array constant','expression',Params);
|
RaiseXExpectedButYFound(20170601191003,'array constant','expression',Params);
|
||||||
end
|
end
|
||||||
@ -13635,8 +13657,9 @@ begin
|
|||||||
aType:=TPasArgument(Decl).ArgType
|
aType:=TPasArgument(Decl).ArgType
|
||||||
else if Decl.ClassType=TPasResultElement then
|
else if Decl.ClassType=TPasResultElement then
|
||||||
aType:=TPasResultElement(Decl).ResultType
|
aType:=TPasResultElement(Decl).ResultType
|
||||||
else if Decl is TPasFunction then
|
else if (Decl is TPasProcedure)
|
||||||
aType:=TPasFunction(Decl).FuncType.ResultEl.ResultType;
|
and (TPasProcedure(Decl).ProcType is TPasFunctionType) then
|
||||||
|
aType:=TPasFunctionType(TPasProcedure(Decl).ProcType).ResultEl.ResultType;
|
||||||
{$IFDEF VerbosePasResolver}
|
{$IFDEF VerbosePasResolver}
|
||||||
{AllowWriteln}
|
{AllowWriteln}
|
||||||
if aType=nil then
|
if aType=nil then
|
||||||
@ -16446,7 +16469,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
EnumType:=TPasEnumType(LTypeEl);
|
EnumType:=TPasEnumType(LTypeEl);
|
||||||
LRangeValue:=TResEvalRangeInt.CreateValue(revskEnum,EnumType,
|
LRangeValue:=TResEvalRangeInt.CreateValue(revskEnum,EnumType,
|
||||||
0,EnumType.Values.Count-1);
|
0,TMaxPrecInt(EnumType.Values.Count)-1);
|
||||||
end
|
end
|
||||||
else if C=TPasUnresolvedSymbolRef then
|
else if C=TPasUnresolvedSymbolRef then
|
||||||
begin
|
begin
|
||||||
@ -17047,7 +17070,15 @@ begin
|
|||||||
if CheckProcTypeCompatibility(TPasProcedureType(LHS.LoTypeEl),
|
if CheckProcTypeCompatibility(TPasProcedureType(LHS.LoTypeEl),
|
||||||
TPasProcedure(RHS.IdentEl).ProcType,true,ErrorEl,RaiseOnIncompatible) then
|
TPasProcedure(RHS.IdentEl).ProcType,true,ErrorEl,RaiseOnIncompatible) then
|
||||||
exit(cExact);
|
exit(cExact);
|
||||||
end;
|
end
|
||||||
|
else if (LHS.LoTypeEl is TPasProcedureType)
|
||||||
|
and (RHS.ExprEl is TProcedureExpr) then
|
||||||
|
begin
|
||||||
|
// for example ProcVar:=anonymous-procedure...
|
||||||
|
if CheckProcTypeCompatibility(TPasProcedureType(LHS.LoTypeEl),
|
||||||
|
TProcedureExpr(RHS.ExprEl).Proc.ProcType,true,ErrorEl,RaiseOnIncompatible) then
|
||||||
|
exit(cExact);
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else if LBT=btPointer then
|
else if LBT=btPointer then
|
||||||
begin
|
begin
|
||||||
@ -19846,7 +19877,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
TypeEl:=TPasProcedure(El).ProcType;
|
TypeEl:=TPasProcedure(El).ProcType;
|
||||||
SetResolverIdentifier(ResolvedEl,btProc,El,TypeEl,TypeEl,[rrfCanBeStatement]);
|
SetResolverIdentifier(ResolvedEl,btProc,El,TypeEl,TypeEl,[rrfCanBeStatement]);
|
||||||
if El is TPasFunction then
|
if TPasProcedure(El).ProcType is TPasFunctionType then
|
||||||
Include(ResolvedEl.Flags,rrfReadable);
|
Include(ResolvedEl.Flags,rrfReadable);
|
||||||
// Note: the readability of TPasConstructor depends on the context
|
// Note: the readability of TPasConstructor depends on the context
|
||||||
// Note: implicit calls are handled in TPrimitiveExpr
|
// Note: implicit calls are handled in TPrimitiveExpr
|
||||||
@ -19857,6 +19888,11 @@ begin
|
|||||||
TPasProcedureType(El),TPasProcedureType(El),[rrfCanBeStatement]);
|
TPasProcedureType(El),TPasProcedureType(El),[rrfCanBeStatement]);
|
||||||
// Note: implicit calls are handled in TPrimitiveExpr
|
// Note: implicit calls are handled in TPrimitiveExpr
|
||||||
end
|
end
|
||||||
|
else if ElClass=TProcedureExpr then
|
||||||
|
begin
|
||||||
|
TypeEl:=TProcedureExpr(El).Proc.ProcType;
|
||||||
|
SetResolverValueExpr(ResolvedEl,btProc,TypeEl,TypeEl,TProcedureExpr(El),[rrfReadable]);
|
||||||
|
end
|
||||||
else if ElClass=TPasArrayType then
|
else if ElClass=TPasArrayType then
|
||||||
SetResolverIdentifier(ResolvedEl,btContext,El,TPasArrayType(El),TPasArrayType(El),[])
|
SetResolverIdentifier(ResolvedEl,btContext,El,TPasArrayType(El),TPasArrayType(El),[])
|
||||||
else if ElClass=TArrayValues then
|
else if ElClass=TArrayValues then
|
||||||
@ -20001,6 +20037,17 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasResolver.GetParentProcBody(El: TPasElement): TProcedureBody;
|
||||||
|
begin
|
||||||
|
while El<>nil do
|
||||||
|
begin
|
||||||
|
if El is TProcedureBody then
|
||||||
|
exit(TProcedureBody(El));
|
||||||
|
El:=El.Parent;
|
||||||
|
end;
|
||||||
|
Result:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasResolver.ProcHasImplElements(Proc: TPasProcedure): boolean;
|
function TPasResolver.ProcHasImplElements(Proc: TPasProcedure): boolean;
|
||||||
begin
|
begin
|
||||||
Result:=GetProcFirstImplEl(Proc)<>nil;
|
Result:=GetProcFirstImplEl(Proc)<>nil;
|
||||||
@ -20558,7 +20605,7 @@ begin
|
|||||||
else if C=TPasEnumType then
|
else if C=TPasEnumType then
|
||||||
begin
|
begin
|
||||||
Result:=TResEvalRangeInt.CreateValue(revskEnum,TPasEnumType(Decl),
|
Result:=TResEvalRangeInt.CreateValue(revskEnum,TPasEnumType(Decl),
|
||||||
0,TPasEnumType(Decl).Values.Count-1);
|
0,TMaxPrecInt(TPasEnumType(Decl).Values.Count)-1);
|
||||||
Result.IdentEl:=Decl;
|
Result.IdentEl:=Decl;
|
||||||
exit;
|
exit;
|
||||||
end
|
end
|
||||||
|
@ -82,6 +82,8 @@ resourcestring
|
|||||||
SPasTreeClassDestructor = 'class destructor';
|
SPasTreeClassDestructor = 'class destructor';
|
||||||
SPasTreeConstructor = 'constructor';
|
SPasTreeConstructor = 'constructor';
|
||||||
SPasTreeDestructor = 'destructor';
|
SPasTreeDestructor = 'destructor';
|
||||||
|
SPasTreeAnonymousProcedure = 'anonymous procedure';
|
||||||
|
SPasTreeAnonymousFunction = 'anonymous function';
|
||||||
SPasTreeProcedureImpl = 'procedure/function implementation';
|
SPasTreeProcedureImpl = 'procedure/function implementation';
|
||||||
SPasTreeConstructorImpl = 'constructor implementation';
|
SPasTreeConstructorImpl = 'constructor implementation';
|
||||||
SPasTreeDestructorImpl = 'destructor implementation';
|
SPasTreeDestructorImpl = 'destructor implementation';
|
||||||
@ -192,7 +194,7 @@ type
|
|||||||
|
|
||||||
TPasExprKind = (pekIdent, pekNumber, pekString, pekSet, pekNil, pekBoolConst,
|
TPasExprKind = (pekIdent, pekNumber, pekString, pekSet, pekNil, pekBoolConst,
|
||||||
pekRange, pekUnary, pekBinary, pekFuncParams, pekArrayParams, pekListOfExp,
|
pekRange, pekUnary, pekBinary, pekFuncParams, pekArrayParams, pekListOfExp,
|
||||||
pekInherited, pekSelf, pekSpecialize);
|
pekInherited, pekSelf, pekSpecialize, pekProcedure);
|
||||||
|
|
||||||
TExprOpCode = (eopNone,
|
TExprOpCode = (eopNone,
|
||||||
eopAdd,eopSubtract,eopMultiply,eopDivide, eopDiv,eopMod, eopPower,// arithmetic
|
eopAdd,eopSubtract,eopMultiply,eopDivide, eopDiv,eopMod, eopPower,// arithmetic
|
||||||
@ -969,7 +971,8 @@ type
|
|||||||
ptOperator, ptClassOperator,
|
ptOperator, ptClassOperator,
|
||||||
ptConstructor, ptDestructor,
|
ptConstructor, ptDestructor,
|
||||||
ptClassProcedure, ptClassFunction,
|
ptClassProcedure, ptClassFunction,
|
||||||
ptClassConstructor, ptClassDestructor);
|
ptClassConstructor, ptClassDestructor,
|
||||||
|
ptAnonymousProcedure, ptAnonymousFunction);
|
||||||
|
|
||||||
{ TPasProcedureBase }
|
{ TPasProcedureBase }
|
||||||
|
|
||||||
@ -1004,6 +1007,8 @@ type
|
|||||||
|
|
||||||
TProcedureBody = class;
|
TProcedureBody = class;
|
||||||
|
|
||||||
|
{ TPasProcedure - named procedure, not anonymous }
|
||||||
|
|
||||||
TPasProcedure = class(TPasProcedureBase)
|
TPasProcedure = class(TPasProcedureBase)
|
||||||
Private
|
Private
|
||||||
FModifiers : TProcedureModifiers;
|
FModifiers : TProcedureModifiers;
|
||||||
@ -1020,13 +1025,13 @@ type
|
|||||||
procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
|
procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
|
||||||
const Arg: Pointer); override;
|
const Arg: Pointer); override;
|
||||||
public
|
public
|
||||||
ProcType : TPasProcedureType;
|
|
||||||
Body : TProcedureBody;
|
|
||||||
PublicName, // e.g. public PublicName;
|
PublicName, // e.g. public PublicName;
|
||||||
LibrarySymbolName,
|
LibrarySymbolName,
|
||||||
LibraryExpr : TPasExpr; // e.g. external LibraryExpr name LibrarySymbolName;
|
LibraryExpr : TPasExpr; // e.g. external LibraryExpr name LibrarySymbolName;
|
||||||
DispIDExpr : TPasExpr;
|
DispIDExpr : TPasExpr;
|
||||||
AliasName : String;
|
AliasName : String;
|
||||||
|
ProcType : TPasProcedureType;
|
||||||
|
Body : TProcedureBody;
|
||||||
Procedure AddModifier(AModifier : TProcedureModifier);
|
Procedure AddModifier(AModifier : TProcedureModifier);
|
||||||
Function IsVirtual : Boolean;
|
Function IsVirtual : Boolean;
|
||||||
Function IsDynamic : Boolean;
|
Function IsDynamic : Boolean;
|
||||||
@ -1039,6 +1044,7 @@ type
|
|||||||
Function IsReintroduced : Boolean;
|
Function IsReintroduced : Boolean;
|
||||||
Function IsStatic : Boolean;
|
Function IsStatic : Boolean;
|
||||||
Function IsForward: Boolean;
|
Function IsForward: Boolean;
|
||||||
|
Function GetProcTypeEnum: TProcType; virtual;
|
||||||
Property Modifiers : TProcedureModifiers Read FModifiers Write FModifiers;
|
Property Modifiers : TProcedureModifiers Read FModifiers Write FModifiers;
|
||||||
Property CallingConvention : TCallingConvention Read GetCallingConvention Write SetCallingConvention;
|
Property CallingConvention : TCallingConvention Read GetCallingConvention Write SetCallingConvention;
|
||||||
Property MessageName : String Read FMessageName Write FMessageName;
|
Property MessageName : String Read FMessageName Write FMessageName;
|
||||||
@ -1048,14 +1054,16 @@ type
|
|||||||
|
|
||||||
TArrayOfPasProcedure = array of TPasProcedure;
|
TArrayOfPasProcedure = array of TPasProcedure;
|
||||||
|
|
||||||
|
{ TPasFunction - named function, not anonymous function}
|
||||||
|
|
||||||
TPasFunction = class(TPasProcedure)
|
TPasFunction = class(TPasProcedure)
|
||||||
private
|
private
|
||||||
function GetFT: TPasFunctionType; inline;
|
function GetFT: TPasFunctionType; inline;
|
||||||
public
|
public
|
||||||
function ElementTypeName: string; override;
|
function ElementTypeName: string; override;
|
||||||
function TypeName: string; override;
|
function TypeName: string; override;
|
||||||
function GetDeclaration (full : boolean) : string; override;
|
|
||||||
Property FuncType : TPasFunctionType Read GetFT;
|
Property FuncType : TPasFunctionType Read GetFT;
|
||||||
|
function GetProcTypeEnum: TProcType; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TPasOperator }
|
{ TPasOperator }
|
||||||
@ -1082,17 +1090,18 @@ type
|
|||||||
Function OldName(WithPath : Boolean) : String;
|
Function OldName(WithPath : Boolean) : String;
|
||||||
function ElementTypeName: string; override;
|
function ElementTypeName: string; override;
|
||||||
function TypeName: string; override;
|
function TypeName: string; override;
|
||||||
|
function GetProcTypeEnum: TProcType; override;
|
||||||
function GetDeclaration (full : boolean) : string; override;
|
function GetDeclaration (full : boolean) : string; override;
|
||||||
Property OperatorType : TOperatorType Read FOperatorType Write FOperatorType;
|
Property OperatorType : TOperatorType Read FOperatorType Write FOperatorType;
|
||||||
// True if the declaration was using a token instead of an identifier
|
// True if the declaration was using a token instead of an identifier
|
||||||
Property TokenBased : Boolean Read FTokenBased Write FTokenBased;
|
Property TokenBased : Boolean Read FTokenBased Write FTokenBased;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Type
|
|
||||||
{ TPasClassOperator }
|
{ TPasClassOperator }
|
||||||
|
|
||||||
TPasClassOperator = class(TPasOperator)
|
TPasClassOperator = class(TPasOperator)
|
||||||
function TypeName: string; override;
|
function TypeName: string; override;
|
||||||
|
function GetProcTypeEnum: TProcType; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -1102,6 +1111,7 @@ Type
|
|||||||
public
|
public
|
||||||
function ElementTypeName: string; override;
|
function ElementTypeName: string; override;
|
||||||
function TypeName: string; override;
|
function TypeName: string; override;
|
||||||
|
function GetProcTypeEnum: TProcType; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TPasClassConstructor }
|
{ TPasClassConstructor }
|
||||||
@ -1110,6 +1120,7 @@ Type
|
|||||||
public
|
public
|
||||||
function ElementTypeName: string; override;
|
function ElementTypeName: string; override;
|
||||||
function TypeName: string; override;
|
function TypeName: string; override;
|
||||||
|
function GetProcTypeEnum: TProcType; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TPasDestructor }
|
{ TPasDestructor }
|
||||||
@ -1118,6 +1129,7 @@ Type
|
|||||||
public
|
public
|
||||||
function ElementTypeName: string; override;
|
function ElementTypeName: string; override;
|
||||||
function TypeName: string; override;
|
function TypeName: string; override;
|
||||||
|
function GetProcTypeEnum: TProcType; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TPasClassDestructor }
|
{ TPasClassDestructor }
|
||||||
@ -1126,6 +1138,7 @@ Type
|
|||||||
public
|
public
|
||||||
function ElementTypeName: string; override;
|
function ElementTypeName: string; override;
|
||||||
function TypeName: string; override;
|
function TypeName: string; override;
|
||||||
|
function GetProcTypeEnum: TProcType; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TPasClassProcedure }
|
{ TPasClassProcedure }
|
||||||
@ -1134,6 +1147,7 @@ Type
|
|||||||
public
|
public
|
||||||
function ElementTypeName: string; override;
|
function ElementTypeName: string; override;
|
||||||
function TypeName: string; override;
|
function TypeName: string; override;
|
||||||
|
function GetProcTypeEnum: TProcType; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TPasClassFunction }
|
{ TPasClassFunction }
|
||||||
@ -1142,8 +1156,43 @@ Type
|
|||||||
public
|
public
|
||||||
function ElementTypeName: string; override;
|
function ElementTypeName: string; override;
|
||||||
function TypeName: string; override;
|
function TypeName: string; override;
|
||||||
|
function GetProcTypeEnum: TProcType; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TPasAnonymousProcedure - parent is TProcedureExpr }
|
||||||
|
|
||||||
|
TPasAnonymousProcedure = class(TPasProcedure)
|
||||||
|
public
|
||||||
|
function ElementTypeName: string; override;
|
||||||
|
function TypeName: string; override;
|
||||||
|
function GetProcTypeEnum: TProcType; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TPasAnonymousFunction - parent is TProcedureExpr and ProcType is TPasFunctionType}
|
||||||
|
|
||||||
|
TPasAnonymousFunction = class(TPasAnonymousProcedure)
|
||||||
|
private
|
||||||
|
function GetFT: TPasFunctionType; inline;
|
||||||
|
public
|
||||||
|
function ElementTypeName: string; override;
|
||||||
|
function TypeName: string; override;
|
||||||
|
Property FuncType : TPasFunctionType Read GetFT;
|
||||||
|
function GetProcTypeEnum: TProcType; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TProcedureExpr }
|
||||||
|
|
||||||
|
TProcedureExpr = class(TPasExpr)
|
||||||
|
public
|
||||||
|
Proc: TPasAnonymousProcedure;
|
||||||
|
constructor Create(AParent: TPasElement); overload;
|
||||||
|
destructor Destroy; override;
|
||||||
|
function GetDeclaration(full: Boolean): string; override;
|
||||||
|
procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
|
||||||
|
const Arg: Pointer); override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
TPasImplBlock = class;
|
TPasImplBlock = class;
|
||||||
|
|
||||||
{ TProcedureBody - the var+type+const+begin, without the header, child of TPasProcedure }
|
{ TProcedureBody - the var+type+const+begin, without the header, child of TPasProcedure }
|
||||||
@ -1577,7 +1626,8 @@ const
|
|||||||
'ListOfExp',
|
'ListOfExp',
|
||||||
'Inherited',
|
'Inherited',
|
||||||
'Self',
|
'Self',
|
||||||
'Specialize');
|
'Specialize',
|
||||||
|
'Procedure');
|
||||||
|
|
||||||
OpcodeStrings : Array[TExprOpCode] of string = (
|
OpcodeStrings : Array[TExprOpCode] of string = (
|
||||||
'','+','-','*','/','div','mod','**',
|
'','+','-','*','/','div','mod','**',
|
||||||
@ -1643,6 +1693,26 @@ begin
|
|||||||
El:=nil;
|
El:=nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Function IndentStrings(S : TStrings; indent : Integer) : string;
|
||||||
|
Var
|
||||||
|
I,CurrLen,CurrPos : Integer;
|
||||||
|
begin
|
||||||
|
Result:='';
|
||||||
|
CurrLen:=0;
|
||||||
|
CurrPos:=0;
|
||||||
|
For I:=0 to S.Count-1 do
|
||||||
|
begin
|
||||||
|
CurrLen:=Length(S[i]);
|
||||||
|
If (CurrLen+CurrPos)>72 then
|
||||||
|
begin
|
||||||
|
Result:=Result+LineEnding+StringOfChar(' ',Indent);
|
||||||
|
CurrPos:=Indent;
|
||||||
|
end;
|
||||||
|
Result:=Result+S[i];
|
||||||
|
CurrPos:=CurrPos+CurrLen;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{$IFDEF HasPTDumpStack}
|
{$IFDEF HasPTDumpStack}
|
||||||
procedure PTDumpStack;
|
procedure PTDumpStack;
|
||||||
begin
|
begin
|
||||||
@ -1843,6 +1913,11 @@ begin
|
|||||||
Result:='class operator';
|
Result:='class operator';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasClassOperator.GetProcTypeEnum: TProcType;
|
||||||
|
begin
|
||||||
|
Result:=ptClassOperator;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TPasImplAsmStatement }
|
{ TPasImplAsmStatement }
|
||||||
|
|
||||||
constructor TPasImplAsmStatement.Create(const AName: string;
|
constructor TPasImplAsmStatement.Create(const AName: string;
|
||||||
@ -1865,6 +1940,79 @@ begin
|
|||||||
Result:='class '+ inherited TypeName;
|
Result:='class '+ inherited TypeName;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasClassConstructor.GetProcTypeEnum: TProcType;
|
||||||
|
begin
|
||||||
|
Result:=ptClassConstructor;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TPasAnonymousProcedure }
|
||||||
|
|
||||||
|
function TPasAnonymousProcedure.ElementTypeName: string;
|
||||||
|
begin
|
||||||
|
Result:=SPasTreeAnonymousProcedure;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPasAnonymousProcedure.TypeName: string;
|
||||||
|
begin
|
||||||
|
Result:='anonymous procedure';
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPasAnonymousProcedure.GetProcTypeEnum: TProcType;
|
||||||
|
begin
|
||||||
|
Result:=ptAnonymousProcedure;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TPasAnonymousFunction }
|
||||||
|
|
||||||
|
function TPasAnonymousFunction.GetFT: TPasFunctionType;
|
||||||
|
begin
|
||||||
|
Result:=ProcType as TPasFunctionType;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPasAnonymousFunction.ElementTypeName: string;
|
||||||
|
begin
|
||||||
|
Result := SPasTreeAnonymousFunction;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPasAnonymousFunction.TypeName: string;
|
||||||
|
begin
|
||||||
|
Result:='anonymous function';
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPasAnonymousFunction.GetProcTypeEnum: TProcType;
|
||||||
|
begin
|
||||||
|
Result:=ptAnonymousFunction;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TProcedureExpr }
|
||||||
|
|
||||||
|
constructor TProcedureExpr.Create(AParent: TPasElement);
|
||||||
|
begin
|
||||||
|
inherited Create(AParent,pekProcedure, eopNone);
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TProcedureExpr.Destroy;
|
||||||
|
begin
|
||||||
|
ReleaseAndNil(TPasElement(Proc){$IFDEF CheckPasTreeRefCount},'TProcedureExpr.Proc'{$ENDIF});
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TProcedureExpr.GetDeclaration(full: Boolean): string;
|
||||||
|
begin
|
||||||
|
if Proc<>nil then
|
||||||
|
Result:=Proc.GetDeclaration(full)
|
||||||
|
else
|
||||||
|
Result:='procedure-expr';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TProcedureExpr.ForEachCall(const aMethodCall: TOnForEachPasElement;
|
||||||
|
const Arg: Pointer);
|
||||||
|
begin
|
||||||
|
inherited ForEachCall(aMethodCall, Arg);
|
||||||
|
if Proc<>nil then
|
||||||
|
Proc.ForEachCall(aMethodCall,Arg);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TPasImplRaise }
|
{ TPasImplRaise }
|
||||||
|
|
||||||
destructor TPasImplRaise.Destroy;
|
destructor TPasImplRaise.Destroy;
|
||||||
@ -2157,7 +2305,7 @@ begin
|
|||||||
Result:=ProcType as TPasFunctionType;
|
Result:=ProcType as TPasFunctionType;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPasFunction.ElementTypeName: string; begin Result := SPasTreeFunction end;
|
function TPasFunction.ElementTypeName: string; begin Result := SPasTreeFunction; end;
|
||||||
function TPasClassProcedure.ElementTypeName: string; begin Result := SPasTreeClassProcedure; end;
|
function TPasClassProcedure.ElementTypeName: string; begin Result := SPasTreeClassProcedure; end;
|
||||||
function TPasClassConstructor.ElementTypeName: string; begin Result := SPasTreeClassConstructor; end;
|
function TPasClassConstructor.ElementTypeName: string; begin Result := SPasTreeClassConstructor; end;
|
||||||
function TPasClassDestructor.ElementTypeName: string; begin Result := SPasTreeClassDestructor; end;
|
function TPasClassDestructor.ElementTypeName: string; begin Result := SPasTreeClassDestructor; end;
|
||||||
@ -2167,6 +2315,11 @@ begin
|
|||||||
Result:='destructor';
|
Result:='destructor';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasClassDestructor.GetProcTypeEnum: TProcType;
|
||||||
|
begin
|
||||||
|
Result:=ptClassDestructor;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasClassFunction.ElementTypeName: string; begin Result := SPasTreeClassFunction; end;
|
function TPasClassFunction.ElementTypeName: string; begin Result := SPasTreeClassFunction; end;
|
||||||
|
|
||||||
class function TPasOperator.OperatorTypeToToken(T: TOperatorType): String;
|
class function TPasOperator.OperatorTypeToToken(T: TOperatorType): String;
|
||||||
@ -3229,12 +3382,12 @@ end;
|
|||||||
|
|
||||||
destructor TPasProcedure.Destroy;
|
destructor TPasProcedure.Destroy;
|
||||||
begin
|
begin
|
||||||
ReleaseAndNil(TPasElement(ProcType){$IFDEF CheckPasTreeRefCount},'TPasProcedure.ProcType'{$ENDIF});
|
|
||||||
ReleaseAndNil(TPasElement(Body){$IFDEF CheckPasTreeRefCount},'TPasProcedure.Body'{$ENDIF});
|
|
||||||
ReleaseAndNil(TPasElement(PublicName){$IFDEF CheckPasTreeRefCount},'TPasProcedure.PublicName'{$ENDIF});
|
ReleaseAndNil(TPasElement(PublicName){$IFDEF CheckPasTreeRefCount},'TPasProcedure.PublicName'{$ENDIF});
|
||||||
ReleaseAndNil(TPasElement(LibraryExpr){$IFDEF CheckPasTreeRefCount},'TPasProcedure.LibraryExpr'{$ENDIF});
|
ReleaseAndNil(TPasElement(LibraryExpr){$IFDEF CheckPasTreeRefCount},'TPasProcedure.LibraryExpr'{$ENDIF});
|
||||||
ReleaseAndNil(TPasElement(LibrarySymbolName){$IFDEF CheckPasTreeRefCount},'TPasProcedure.LibrarySymbolName'{$ENDIF});
|
ReleaseAndNil(TPasElement(LibrarySymbolName){$IFDEF CheckPasTreeRefCount},'TPasProcedure.LibrarySymbolName'{$ENDIF});
|
||||||
ReleaseAndNil(TPasElement(DispIDExpr){$IFDEF CheckPasTreeRefCount},'TPasProcedure.DispIDExpr'{$ENDIF});
|
ReleaseAndNil(TPasElement(DispIDExpr){$IFDEF CheckPasTreeRefCount},'TPasProcedure.DispIDExpr'{$ENDIF});
|
||||||
|
ReleaseAndNil(TPasElement(ProcType){$IFDEF CheckPasTreeRefCount},'TPasProcedure.ProcType'{$ENDIF});
|
||||||
|
ReleaseAndNil(TPasElement(Body){$IFDEF CheckPasTreeRefCount},'TPasProcedure.Body'{$ENDIF});
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3764,29 +3917,6 @@ begin
|
|||||||
ForEachChildCall(aMethodCall,Arg,ElType,true);
|
ForEachChildCall(aMethodCall,Arg,ElType,true);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Function IndentStrings(S : TStrings; indent : Integer) : string;
|
|
||||||
|
|
||||||
Var
|
|
||||||
I,CurrLen,CurrPos : Integer;
|
|
||||||
|
|
||||||
|
|
||||||
begin
|
|
||||||
Result:='';
|
|
||||||
CurrLen:=0;
|
|
||||||
CurrPos:=0;
|
|
||||||
For I:=0 to S.Count-1 do
|
|
||||||
begin
|
|
||||||
CurrLen:=Length(S[i]);
|
|
||||||
If (CurrLen+CurrPos)>72 then
|
|
||||||
begin
|
|
||||||
Result:=Result+LineEnding+StringOfChar(' ',Indent);
|
|
||||||
CurrPos:=Indent;
|
|
||||||
end;
|
|
||||||
Result:=Result+S[i];
|
|
||||||
CurrPos:=CurrPos+CurrLen;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TPasEnumType.GetDeclaration (full : boolean) : string;
|
function TPasEnumType.GetDeclaration (full : boolean) : string;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
@ -4278,8 +4408,8 @@ procedure TPasProcedure.ForEachCall(const aMethodCall: TOnForEachPasElement;
|
|||||||
const Arg: Pointer);
|
const Arg: Pointer);
|
||||||
begin
|
begin
|
||||||
inherited ForEachCall(aMethodCall, Arg);
|
inherited ForEachCall(aMethodCall, Arg);
|
||||||
ForEachChildCall(aMethodCall,Arg,PublicName,false);
|
|
||||||
ForEachChildCall(aMethodCall,Arg,ProcType,false);
|
ForEachChildCall(aMethodCall,Arg,ProcType,false);
|
||||||
|
ForEachChildCall(aMethodCall,Arg,PublicName,false);
|
||||||
ForEachChildCall(aMethodCall,Arg,LibraryExpr,false);
|
ForEachChildCall(aMethodCall,Arg,LibraryExpr,false);
|
||||||
ForEachChildCall(aMethodCall,Arg,LibrarySymbolName,false);
|
ForEachChildCall(aMethodCall,Arg,LibrarySymbolName,false);
|
||||||
ForEachChildCall(aMethodCall,Arg,Body,false);
|
ForEachChildCall(aMethodCall,Arg,Body,false);
|
||||||
@ -4347,36 +4477,28 @@ begin
|
|||||||
Result:=pmForward in FModifiers;
|
Result:=pmForward in FModifiers;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPasProcedure.GetDeclaration(full: Boolean): string;
|
function TPasProcedure.GetProcTypeEnum: TProcType;
|
||||||
|
|
||||||
Var
|
|
||||||
S : TStringList;
|
|
||||||
begin
|
begin
|
||||||
S:=TStringList.Create;
|
Result:=ptProcedure;
|
||||||
try
|
|
||||||
If Full then
|
|
||||||
S.Add(TypeName+' '+Name);
|
|
||||||
ProcType.GetArguments(S);
|
|
||||||
GetModifiers(S);
|
|
||||||
Result:=IndentStrings(S,Length(S[0]));
|
|
||||||
finally
|
|
||||||
S.Free;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPasFunction.GetDeclaration (full : boolean) : string;
|
function TPasProcedure.GetDeclaration(full: Boolean): string;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
S : TStringList;
|
S : TStringList;
|
||||||
T : string;
|
T: String;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
S:=TStringList.Create;
|
S:=TStringList.Create;
|
||||||
try
|
try
|
||||||
If Full then
|
If Full then
|
||||||
S.Add(TypeName+' '+Name);
|
begin
|
||||||
|
T:=TypeName;
|
||||||
|
if Name<>'' then
|
||||||
|
T:=T+' '+Name;
|
||||||
|
S.Add(T);
|
||||||
|
end;
|
||||||
ProcType.GetArguments(S);
|
ProcType.GetArguments(S);
|
||||||
If Assigned((Proctype as TPasFunctionType).ResultEl) then
|
If ProcType is TPasFunctionType
|
||||||
|
and Assigned(TPasFunctionType(Proctype).ResultEl) then
|
||||||
With TPasFunctionType(ProcType).ResultEl.ResultType do
|
With TPasFunctionType(ProcType).ResultEl.ResultType do
|
||||||
begin
|
begin
|
||||||
T:=' : ';
|
T:=' : ';
|
||||||
@ -4398,6 +4520,11 @@ begin
|
|||||||
Result:='function';
|
Result:='function';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasFunction.GetProcTypeEnum: TProcType;
|
||||||
|
begin
|
||||||
|
Result:=ptFunction;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasOperator.GetOperatorDeclaration(Full : Boolean) : string;
|
function TPasOperator.GetOperatorDeclaration(Full : Boolean) : string;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -4450,26 +4577,51 @@ begin
|
|||||||
Result:='operator';
|
Result:='operator';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasOperator.GetProcTypeEnum: TProcType;
|
||||||
|
begin
|
||||||
|
Result:=ptOperator;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasClassProcedure.TypeName: string;
|
function TPasClassProcedure.TypeName: string;
|
||||||
begin
|
begin
|
||||||
Result:='class procedure';
|
Result:='class procedure';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasClassProcedure.GetProcTypeEnum: TProcType;
|
||||||
|
begin
|
||||||
|
Result:=ptClassProcedure;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasClassFunction.TypeName: string;
|
function TPasClassFunction.TypeName: string;
|
||||||
begin
|
begin
|
||||||
Result:='class function';
|
Result:='class function';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasClassFunction.GetProcTypeEnum: TProcType;
|
||||||
|
begin
|
||||||
|
Result:=ptClassFunction;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasConstructor.TypeName: string;
|
function TPasConstructor.TypeName: string;
|
||||||
begin
|
begin
|
||||||
Result:='constructor';
|
Result:='constructor';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasConstructor.GetProcTypeEnum: TProcType;
|
||||||
|
begin
|
||||||
|
Result:=ptConstructor;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasDestructor.TypeName: string;
|
function TPasDestructor.TypeName: string;
|
||||||
begin
|
begin
|
||||||
Result:='destructor';
|
Result:='destructor';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasDestructor.GetProcTypeEnum: TProcType;
|
||||||
|
begin
|
||||||
|
Result:=ptDestructor;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasArgument.GetDeclaration (full : boolean) : string;
|
function TPasArgument.GetDeclaration (full : boolean) : string;
|
||||||
begin
|
begin
|
||||||
If Assigned(ArgType) then
|
If Assigned(ArgType) then
|
||||||
|
@ -314,7 +314,7 @@ type
|
|||||||
function ReadDottedIdentifier(Parent: TPasElement; out Expr: TPasExpr; NeedAsString: boolean): String;
|
function ReadDottedIdentifier(Parent: TPasElement; out Expr: TPasExpr; NeedAsString: boolean): String;
|
||||||
function CheckProcedureArgs(Parent: TPasElement;
|
function CheckProcedureArgs(Parent: TPasElement;
|
||||||
Args: TFPList; // list of TPasArgument
|
Args: TFPList; // list of TPasArgument
|
||||||
Mandatory: Boolean): boolean;
|
ProcType: TProcType): boolean;
|
||||||
function CheckVisibility(S: String; var AVisibility: TPasMemberVisibility): Boolean;
|
function CheckVisibility(S: String; var AVisibility: TPasMemberVisibility): Boolean;
|
||||||
procedure ParseExc(MsgNumber: integer; const Msg: String);
|
procedure ParseExc(MsgNumber: integer; const Msg: String);
|
||||||
procedure ParseExc(MsgNumber: integer; const Fmt: String; Args : Array of {$ifdef pas2js}jsvalue{$else}const{$endif});
|
procedure ParseExc(MsgNumber: integer; const Fmt: String; Args : Array of {$ifdef pas2js}jsvalue{$else}const{$endif});
|
||||||
@ -349,12 +349,15 @@ type
|
|||||||
function CreateRecordValues(AParent : TPasElement): TRecordValues;
|
function CreateRecordValues(AParent : TPasElement): TRecordValues;
|
||||||
Function IsCurTokenHint(out AHint : TPasMemberHint) : Boolean; overload;
|
Function IsCurTokenHint(out AHint : TPasMemberHint) : Boolean; overload;
|
||||||
Function IsCurTokenHint: Boolean; overload;
|
Function IsCurTokenHint: Boolean; overload;
|
||||||
Function TokenIsCallingConvention(const S : String; out CC : TCallingConvention) : Boolean; virtual;
|
Function TokenIsCallingConvention(const S: String; out CC : TCallingConvention) : Boolean; virtual;
|
||||||
Function TokenIsProcedureModifier(Parent : TPasElement; const S : String; Out PM : TProcedureModifier) : Boolean; virtual;
|
Function TokenIsProcedureModifier(Parent: TPasElement; const S: String; Out PM : TProcedureModifier): Boolean; virtual;
|
||||||
|
Function TokenIsAnonymousProcedureModifier(Parent: TPasElement; S: String; Out PM: TProcedureModifier): Boolean; virtual;
|
||||||
Function TokenIsProcedureTypeModifier(Parent : TPasElement; const S : String; Out PTM : TProcTypeModifier) : Boolean; virtual;
|
Function TokenIsProcedureTypeModifier(Parent : TPasElement; const S : String; Out PTM : TProcTypeModifier) : Boolean; virtual;
|
||||||
Function CheckHint(Element : TPasElement; ExpectSemiColon : Boolean) : TPasMemberHints;
|
Function CheckHint(Element : TPasElement; ExpectSemiColon : Boolean) : TPasMemberHints;
|
||||||
|
function IsAnonymousProcAllowed(El: TPasElement): boolean; virtual;
|
||||||
function ParseParams(AParent : TPasElement; ParamsKind: TPasExprKind; AllowFormatting : Boolean = False): TParamsExpr;
|
function ParseParams(AParent : TPasElement; ParamsKind: TPasExprKind; AllowFormatting : Boolean = False): TParamsExpr;
|
||||||
function ParseExpIdent(AParent : TPasElement): TPasExpr;
|
function ParseExprOperand(AParent : TPasElement): TPasExpr;
|
||||||
|
function ParseExpIdent(AParent : TPasElement): TPasExpr; deprecated 'use ParseExprOperand instead'; // since fpc 3.3.1
|
||||||
procedure DoParseClassType(AType: TPasClassType);
|
procedure DoParseClassType(AType: TPasClassType);
|
||||||
function DoParseExpression(AParent: TPaselement;InitExpr: TPasExpr=nil; AllowEqual : Boolean = True): TPasExpr;
|
function DoParseExpression(AParent: TPaselement;InitExpr: TPasExpr=nil; AllowEqual : Boolean = True): TPasExpr;
|
||||||
function DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
|
function DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
|
||||||
@ -1241,6 +1244,21 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasParser.TokenIsAnonymousProcedureModifier(Parent: TPasElement;
|
||||||
|
S: String; out PM: TProcedureModifier): Boolean;
|
||||||
|
begin
|
||||||
|
S:=LowerCase(S);
|
||||||
|
case S of
|
||||||
|
'assembler':
|
||||||
|
begin
|
||||||
|
PM:=pmAssembler;
|
||||||
|
exit(true);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Result:=false;
|
||||||
|
if Parent=nil then ;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasParser.TokenIsProcedureTypeModifier(Parent: TPasElement;
|
function TPasParser.TokenIsProcedureTypeModifier(Parent: TPasElement;
|
||||||
const S: String; out PTM: TProcTypeModifier): Boolean;
|
const S: String; out PTM: TProcTypeModifier): Boolean;
|
||||||
begin
|
begin
|
||||||
@ -1291,6 +1309,17 @@ begin
|
|||||||
ExpectToken(tkSemiColon);
|
ExpectToken(tkSemiColon);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasParser.IsAnonymousProcAllowed(El: TPasElement): boolean;
|
||||||
|
begin
|
||||||
|
while El is TPasExpr do
|
||||||
|
El:=El.Parent;
|
||||||
|
if not (El is TPasImplBlock) then
|
||||||
|
exit(false); // only in statements
|
||||||
|
while El is TPasImplBlock do
|
||||||
|
El:=El.Parent;
|
||||||
|
Result:=El is TProcedureBody; // needs a parent procedure
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasParser.CheckPackMode: TPackMode;
|
function TPasParser.CheckPackMode: TPackMode;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -2007,6 +2036,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
repeat
|
repeat
|
||||||
Expr:=DoParseExpression(Params);
|
Expr:=DoParseExpression(Params);
|
||||||
|
writeln('AAA1 TPasParser.ParseParams ',CurTokenString,' ',curtoken);
|
||||||
if not Assigned(Expr) then
|
if not Assigned(Expr) then
|
||||||
ParseExcSyntaxError;
|
ParseExcSyntaxError;
|
||||||
Params.AddParam(Expr);
|
Params.AddParam(Expr);
|
||||||
@ -2081,7 +2111,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPasParser.ParseExpIdent(AParent: TPasElement): TPasExpr;
|
function TPasParser.ParseExprOperand(AParent: TPasElement): TPasExpr;
|
||||||
|
|
||||||
Function IsWriteOrStr(P : TPasExpr) : boolean;
|
Function IsWriteOrStr(P : TPasExpr) : boolean;
|
||||||
|
|
||||||
@ -2109,7 +2139,7 @@ function TPasParser.ParseExpIdent(AParent: TPasElement): TPasExpr;
|
|||||||
begin // self.Write(EscapeText(AText));
|
begin // self.Write(EscapeText(AText));
|
||||||
optk:=CurToken;
|
optk:=CurToken;
|
||||||
NextToken;
|
NextToken;
|
||||||
b:=CreateBinaryExpr(AParent,Last, ParseExpIdent(AParent), TokenToExprOp(optk));
|
b:=CreateBinaryExpr(AParent,Last, ParseExprOperand(AParent), TokenToExprOp(optk));
|
||||||
if not Assigned(b.right) then
|
if not Assigned(b.right) then
|
||||||
begin
|
begin
|
||||||
b.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
|
b.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
|
||||||
@ -2180,15 +2210,16 @@ var
|
|||||||
ISE: TInlineSpecializeExpr;
|
ISE: TInlineSpecializeExpr;
|
||||||
ST: TPasSpecializeType;
|
ST: TPasSpecializeType;
|
||||||
SrcPos, ScrPos: TPasSourcePos;
|
SrcPos, ScrPos: TPasSourcePos;
|
||||||
|
ProcType: TProcType;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Result:=nil;
|
Result:=nil;
|
||||||
CanSpecialize:=false;
|
CanSpecialize:=false;
|
||||||
aName:='';
|
aName:='';
|
||||||
case CurToken of
|
case CurToken of
|
||||||
tkString: Last:=CreatePrimitiveExpr(AParent,pekString,CurTokenString);
|
tkString: Last:=CreatePrimitiveExpr(AParent,pekString,CurTokenString);
|
||||||
tkChar: Last:=CreatePrimitiveExpr(AParent,pekString,CurTokenText);
|
tkChar: Last:=CreatePrimitiveExpr(AParent,pekString,CurTokenText);
|
||||||
tkNumber: Last:=CreatePrimitiveExpr(AParent,pekNumber,CurTokenString);
|
tkNumber: Last:=CreatePrimitiveExpr(AParent,pekNumber,CurTokenString);
|
||||||
tkIdentifier:
|
tkIdentifier:
|
||||||
begin
|
begin
|
||||||
CanSpecialize:=true;
|
CanSpecialize:=true;
|
||||||
@ -2212,7 +2243,7 @@ begin
|
|||||||
if (CurToken=tkIdentifier) then
|
if (CurToken=tkIdentifier) then
|
||||||
begin
|
begin
|
||||||
SrcPos:=CurTokenPos;
|
SrcPos:=CurTokenPos;
|
||||||
Bin:=CreateBinaryExpr(AParent,Last,ParseExpIdent(AParent),eopNone,SrcPos);
|
Bin:=CreateBinaryExpr(AParent,Last,ParseExprOperand(AParent),eopNone,SrcPos);
|
||||||
if not Assigned(Bin.right) then
|
if not Assigned(Bin.right) then
|
||||||
begin
|
begin
|
||||||
Bin.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
|
Bin.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
|
||||||
@ -2230,6 +2261,27 @@ begin
|
|||||||
Last:=CreateSelfExpr(AParent);
|
Last:=CreateSelfExpr(AParent);
|
||||||
HandleSelf(Last);
|
HandleSelf(Last);
|
||||||
end;
|
end;
|
||||||
|
tkprocedure,tkfunction:
|
||||||
|
begin
|
||||||
|
if CurToken=tkprocedure then
|
||||||
|
ProcType:=ptAnonymousProcedure
|
||||||
|
else
|
||||||
|
ProcType:=ptAnonymousFunction;
|
||||||
|
if not IsAnonymousProcAllowed(AParent) then
|
||||||
|
ParseExcExpectedIdentifier;
|
||||||
|
ok:=false;
|
||||||
|
try
|
||||||
|
Result:=TProcedureExpr(CreateElement(TProcedureExpr,'',AParent,visPublic));
|
||||||
|
TProcedureExpr(Result).Proc:=TPasAnonymousProcedure(ParseProcedureOrFunctionDecl(Result,ProcType));
|
||||||
|
if CurToken=tkSemicolon then
|
||||||
|
NextToken; // skip optional semicolon
|
||||||
|
ok:=true;
|
||||||
|
finally
|
||||||
|
if not ok then
|
||||||
|
Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
|
||||||
|
end;
|
||||||
|
exit; // do not allow postfix operators . ^. [] ()
|
||||||
|
end;
|
||||||
tkCaret:
|
tkCaret:
|
||||||
begin
|
begin
|
||||||
// is this still needed?
|
// is this still needed?
|
||||||
@ -2329,6 +2381,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasParser.ParseExpIdent(AParent: TPasElement): TPasExpr;
|
||||||
|
begin
|
||||||
|
Result:=ParseExprOperand(AParent);
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasParser.OpLevel(t: TToken): Integer;
|
function TPasParser.OpLevel(t: TToken): Integer;
|
||||||
begin
|
begin
|
||||||
case t of
|
case t of
|
||||||
@ -2491,12 +2548,12 @@ begin
|
|||||||
if (CurToken=tkDot) then
|
if (CurToken=tkDot) then
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
x:=CreateBinaryExpr(AParent,x, ParseExpIdent(AParent), TokenToExprOp(tkDot));
|
x:=CreateBinaryExpr(AParent,x, ParseExprOperand(AParent), TokenToExprOp(tkDot));
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
x:=ParseExpIdent(AParent);
|
x:=ParseExprOperand(AParent);
|
||||||
if not Assigned(x) then
|
if not Assigned(x) then
|
||||||
ParseExcSyntaxError;
|
ParseExcSyntaxError;
|
||||||
end;
|
end;
|
||||||
@ -4584,12 +4641,11 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
function TPasParser.CheckProcedureArgs(Parent: TPasElement; Args: TFPList;
|
function TPasParser.CheckProcedureArgs(Parent: TPasElement; Args: TFPList;
|
||||||
Mandatory: Boolean): boolean;
|
ProcType: TProcType): boolean;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
case CurToken of
|
if CurToken=tkBraceOpen then
|
||||||
tkBraceOpen:
|
|
||||||
begin
|
begin
|
||||||
Result:=true;
|
Result:=true;
|
||||||
NextToken;
|
NextToken;
|
||||||
@ -4598,18 +4654,34 @@ begin
|
|||||||
UngetToken;
|
UngetToken;
|
||||||
ParseArgList(Parent, Args, tkBraceClose);
|
ParseArgList(Parent, Args, tkBraceClose);
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
tkSemicolon,tkColon,tkof,tkis,tkIdentifier:
|
|
||||||
begin
|
|
||||||
Result:=false;
|
|
||||||
if Mandatory then
|
|
||||||
ParseExc(nParserExpectedLBracketColon,SParserExpectedLBracketColon)
|
|
||||||
else
|
|
||||||
UngetToken;
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
ParseExcTokenError(';');
|
begin
|
||||||
end;
|
Result:=false;
|
||||||
|
case ProcType of
|
||||||
|
ptOperator,ptClassOperator:
|
||||||
|
ParseExc(nParserExpectedLBracketColon,SParserExpectedLBracketColon);
|
||||||
|
ptAnonymousProcedure,ptAnonymousFunction:
|
||||||
|
case CurToken of
|
||||||
|
tkIdentifier, // e.g. procedure assembler
|
||||||
|
tkbegin,tkvar,tkconst,tktype,tkprocedure,tkfunction:
|
||||||
|
UngetToken;
|
||||||
|
else
|
||||||
|
ParseExcTokenError('begin');
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
case CurToken of
|
||||||
|
tkSemicolon, // e.g. procedure;
|
||||||
|
tkColon, // e.g. function: id
|
||||||
|
tkof, // e.g. procedure of object
|
||||||
|
tkis, // e.g. procedure is nested
|
||||||
|
tkIdentifier: // e.g. procedure cdecl;
|
||||||
|
UngetToken;
|
||||||
|
else
|
||||||
|
ParseExcTokenError(';');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPasParser.HandleProcedureModifier(Parent: TPasElement; pm: TProcedureModifier);
|
procedure TPasParser.HandleProcedureModifier(Parent: TPasElement; pm: TProcedureModifier);
|
||||||
@ -4800,20 +4872,22 @@ Var
|
|||||||
Tok : String;
|
Tok : String;
|
||||||
CC : TCallingConvention;
|
CC : TCallingConvention;
|
||||||
PM : TProcedureModifier;
|
PM : TProcedureModifier;
|
||||||
Done: Boolean;
|
|
||||||
ResultEl: TPasResultElement;
|
ResultEl: TPasResultElement;
|
||||||
OK,IsProc : Boolean;
|
OK: Boolean;
|
||||||
|
IsProc: Boolean; // true = procedure, false = procedure type
|
||||||
|
IsAnonymProc: Boolean;
|
||||||
PTM: TProcTypeModifier;
|
PTM: TProcTypeModifier;
|
||||||
ModCount: Integer;
|
ModTokenCount: Integer;
|
||||||
LastToken: TToken;
|
LastToken: TToken;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
// Element must be non-nil. Removed all checks for not-nil.
|
// Element must be non-nil. Removed all checks for not-nil.
|
||||||
// If it is nil, the following fails anyway.
|
// If it is nil, the following fails anyway.
|
||||||
CheckProcedureArgs(Element,Element.Args,ProcType in [ptOperator,ptClassOperator]);
|
CheckProcedureArgs(Element,Element.Args,ProcType);
|
||||||
IsProc:=Parent is TPasProcedure;
|
IsProc:=Parent is TPasProcedure;
|
||||||
|
IsAnonymProc:=IsProc and (ProcType in [ptAnonymousProcedure,ptAnonymousFunction]);
|
||||||
case ProcType of
|
case ProcType of
|
||||||
ptFunction,ptClassFunction:
|
ptFunction,ptClassFunction,ptAnonymousFunction:
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
if CurToken = tkColon then
|
if CurToken = tkColon then
|
||||||
@ -4882,13 +4956,13 @@ begin
|
|||||||
else
|
else
|
||||||
UnGetToken;
|
UnGetToken;
|
||||||
end;
|
end;
|
||||||
ModCount:=0;
|
ModTokenCount:=0;
|
||||||
Repeat
|
Repeat
|
||||||
inc(ModCount);
|
inc(ModTokenCount);
|
||||||
// Writeln(modcount, curtokentext);
|
// Writeln(ModTokenCount, curtokentext);
|
||||||
LastToken:=CurToken;
|
LastToken:=CurToken;
|
||||||
NextToken;
|
NextToken;
|
||||||
if (ModCount<=3) and (CurToken = tkEqual) and not (Parent is TPasProcedure) then
|
if (CurToken = tkEqual) and not IsProc and (ModTokenCount<=3) then
|
||||||
begin
|
begin
|
||||||
// for example: const p: procedure = nil;
|
// for example: const p: procedure = nil;
|
||||||
UngetToken;
|
UngetToken;
|
||||||
@ -4899,6 +4973,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if LastToken=tkSemicolon then
|
if LastToken=tkSemicolon then
|
||||||
ParseExcSyntaxError;
|
ParseExcSyntaxError;
|
||||||
|
continue;
|
||||||
end
|
end
|
||||||
else if TokenIsCallingConvention(CurTokenString,cc) then
|
else if TokenIsCallingConvention(CurTokenString,cc) then
|
||||||
begin
|
begin
|
||||||
@ -4917,11 +4992,18 @@ begin
|
|||||||
NextToken; // remove offset
|
NextToken; // remove offset
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
ExpectTokens([tkSemicolon,tkEqual]);
|
if IsProc then
|
||||||
if CurToken=tkEqual then
|
ExpectTokens([tkSemicolon])
|
||||||
UngetToken;
|
else
|
||||||
|
begin
|
||||||
|
ExpectTokens([tkSemicolon,tkEqual]);
|
||||||
|
if CurToken=tkEqual then
|
||||||
|
UngetToken;
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
else if IsProc and TokenIsProcedureModifier(Parent,CurTokenString,PM) then
|
else if IsAnonymProc and TokenIsAnonymousProcedureModifier(Parent,CurTokenString,PM) then
|
||||||
|
HandleProcedureModifier(Parent,PM)
|
||||||
|
else if IsProc and not IsAnonymProc and TokenIsProcedureModifier(Parent,CurTokenString,PM) then
|
||||||
HandleProcedureModifier(Parent,PM)
|
HandleProcedureModifier(Parent,PM)
|
||||||
else if TokenIsProcedureTypeModifier(Parent,CurTokenString,PTM) then
|
else if TokenIsProcedureTypeModifier(Parent,CurTokenString,PTM) then
|
||||||
HandleProcedureTypeModifier(Element,PTM)
|
HandleProcedureTypeModifier(Element,PTM)
|
||||||
@ -4930,16 +5012,22 @@ begin
|
|||||||
Tok:=UpperCase(CurTokenString);
|
Tok:=UpperCase(CurTokenString);
|
||||||
NextToken;
|
NextToken;
|
||||||
If (tok<>'NAME') then
|
If (tok<>'NAME') then
|
||||||
Element.Hints:=Element.Hints+[hLibrary]
|
begin
|
||||||
|
if hLibrary in Element.Hints then
|
||||||
|
ParseExcSyntaxError;
|
||||||
|
Element.Hints:=Element.Hints+[hLibrary];
|
||||||
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
NextToken; // Should be export name string.
|
NextToken; // Should be "export name astring".
|
||||||
ExpectToken(tkSemicolon);
|
ExpectToken(tkSemicolon);
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else if DoCheckHint(Element) then
|
else if (not IsAnonymProc) and DoCheckHint(Element) then
|
||||||
|
// deprecated,platform,experimental,library, unimplemented etc
|
||||||
ConsumeSemi
|
ConsumeSemi
|
||||||
else if (CurToken=tkIdentifier) and (CompareText(CurTokenText,'alias')=0) then
|
else if (CurToken=tkIdentifier) and (not IsAnonymProc)
|
||||||
|
and (CompareText(CurTokenText,'alias')=0) then
|
||||||
begin
|
begin
|
||||||
ExpectToken(tkColon);
|
ExpectToken(tkColon);
|
||||||
ExpectToken(tkString);
|
ExpectToken(tkString);
|
||||||
@ -4959,44 +5047,48 @@ begin
|
|||||||
begin
|
begin
|
||||||
// ToDo: read FPC's [] modifiers, e.g. [public,alias:'']
|
// ToDo: read FPC's [] modifiers, e.g. [public,alias:'']
|
||||||
repeat
|
repeat
|
||||||
NextToken
|
NextToken;
|
||||||
|
if CurToken in [tkSquaredBraceOpen,tkSemicolon] then
|
||||||
|
CheckToken(tkSquaredBraceClose);
|
||||||
until CurToken = tkSquaredBraceClose;
|
until CurToken = tkSquaredBraceClose;
|
||||||
ExpectToken(tkSemicolon);
|
ExpectToken(tkSemicolon);
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
CheckToken(tkSemicolon);
|
|
||||||
Done:=(CurToken=tkSemiColon);
|
|
||||||
if Done then
|
|
||||||
begin
|
begin
|
||||||
NextToken;
|
// not a modifier/hint/calling convention
|
||||||
Done:=Not ((Curtoken=tkSquaredBraceOpen) or
|
if LastToken=tkSemicolon then
|
||||||
TokenIsProcedureModifier(Parent,CurtokenString,PM) or
|
begin
|
||||||
TokenIsProcedureTypeModifier(Parent,CurtokenString,PTM) or
|
UngetToken;
|
||||||
IsCurTokenHint() or
|
if IsAnonymProc and (ModTokenCount<=1) then
|
||||||
TokenIsCallingConvention(CurTokenString,cc) or
|
ParseExcSyntaxError;
|
||||||
(CurToken=tkIdentifier) and (CompareText(CurTokenText,'alias')=0));
|
break;
|
||||||
{$ifdef VerbosePasParser}
|
end
|
||||||
DumpCurToken('Done '+IntToStr(Ord(Done)));
|
else if IsAnonymProc then
|
||||||
{$endif}
|
begin
|
||||||
UngetToken;
|
UngetToken;
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
CheckToken(tkSemicolon);
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
// Writeln('Done: ',TokenInfos[Curtoken],' ',CurtokenString);
|
||||||
// Writeln('Done: ',TokenInfos[Curtoken],' ',CurtokenString);
|
Until false;
|
||||||
Until Done;
|
|
||||||
if DoCheckHint(Element) then // deprecated,platform,experimental,library, unimplemented etc
|
|
||||||
ConsumeSemi;
|
|
||||||
if (ProcType in [ptOperator,ptClassOperator]) and (Parent is TPasOperator) then
|
if (ProcType in [ptOperator,ptClassOperator]) and (Parent is TPasOperator) then
|
||||||
TPasOperator(Parent).CorrectName;
|
TPasOperator(Parent).CorrectName;
|
||||||
Engine.FinishScope(stProcedureHeader,Element);
|
Engine.FinishScope(stProcedureHeader,Element);
|
||||||
if (Parent is TPasProcedure)
|
if IsProc
|
||||||
and (not TPasProcedure(Parent).IsForward)
|
and (not TPasProcedure(Parent).IsForward)
|
||||||
and (not TPasProcedure(Parent).IsExternal)
|
and (not TPasProcedure(Parent).IsExternal)
|
||||||
and ((Parent.Parent is TImplementationSection)
|
and ((Parent.Parent is TImplementationSection)
|
||||||
or (Parent.Parent is TProcedureBody))
|
or (Parent.Parent is TProcedureBody)
|
||||||
|
or IsAnonymProc)
|
||||||
then
|
then
|
||||||
ParseProcedureBody(Parent);
|
ParseProcedureBody(Parent);
|
||||||
if Parent is TPasProcedure then
|
if IsProc then
|
||||||
Engine.FinishScope(stProcedure,Parent);
|
Engine.FinishScope(stProcedure,Parent);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -5257,6 +5349,7 @@ procedure TPasParser.ParseProcBeginBlock(Parent: TProcedureBody);
|
|||||||
var
|
var
|
||||||
BeginBlock: TPasImplBeginBlock;
|
BeginBlock: TPasImplBeginBlock;
|
||||||
SubBlock: TPasImplElement;
|
SubBlock: TPasImplElement;
|
||||||
|
Proc: TPasProcedure;
|
||||||
begin
|
begin
|
||||||
BeginBlock := TPasImplBeginBlock(CreateElement(TPasImplBeginBlock, '', Parent));
|
BeginBlock := TPasImplBeginBlock(CreateElement(TPasImplBeginBlock, '', Parent));
|
||||||
Parent.Body := BeginBlock;
|
Parent.Body := BeginBlock;
|
||||||
@ -5273,7 +5366,11 @@ begin
|
|||||||
ExpectToken(tkend);
|
ExpectToken(tkend);
|
||||||
end;
|
end;
|
||||||
until false;
|
until false;
|
||||||
ExpectToken(tkSemicolon);
|
Proc:=Parent.Parent as TPasProcedure;
|
||||||
|
if Proc.GetProcTypeEnum in [ptAnonymousProcedure,ptAnonymousFunction] then
|
||||||
|
NextToken
|
||||||
|
else
|
||||||
|
ExpectToken(tkSemicolon);
|
||||||
// writeln('TPasParser.ParseProcBeginBlock ended ',curtokenstring);
|
// writeln('TPasParser.ParseProcBeginBlock ended ',curtokenstring);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -5974,12 +6071,15 @@ begin
|
|||||||
ptDestructor : Result:=TPasDestructor;
|
ptDestructor : Result:=TPasDestructor;
|
||||||
ptOperator : Result:=TPasOperator;
|
ptOperator : Result:=TPasOperator;
|
||||||
ptClassOperator : Result:=TPasClassOperator;
|
ptClassOperator : Result:=TPasClassOperator;
|
||||||
|
ptAnonymousProcedure: Result:=TPasAnonymousProcedure;
|
||||||
|
ptAnonymousFunction: Result:=TPasAnonymousFunction;
|
||||||
else
|
else
|
||||||
ParseExc(nParserUnknownProcedureType,SParserUnknownProcedureType,[Ord(ProcType)]);
|
ParseExc(nParserUnknownProcedureType,SParserUnknownProcedureType,[Ord(ProcType)]);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPasParser.ParseProcedureOrFunctionDecl(Parent: TPasElement; ProcType: TProcType;AVisibility : TPasMemberVisibility = VisDefault): TPasProcedure;
|
function TPasParser.ParseProcedureOrFunctionDecl(Parent: TPasElement;
|
||||||
|
ProcType: TProcType; AVisibility: TPasMemberVisibility): TPasProcedure;
|
||||||
|
|
||||||
function ExpectProcName: string;
|
function ExpectProcName: string;
|
||||||
|
|
||||||
@ -6023,9 +6123,8 @@ var
|
|||||||
IsTokenBased , ok: Boolean;
|
IsTokenBased , ok: Boolean;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
If (Not (ProcType in [ptOperator,ptClassOperator])) then
|
case ProcType of
|
||||||
Name:=ExpectProcName
|
ptOperator,ptClassOperator:
|
||||||
else
|
|
||||||
begin
|
begin
|
||||||
NextToken;
|
NextToken;
|
||||||
IsTokenBased:=Curtoken<>tkIdentifier;
|
IsTokenBased:=Curtoken<>tkIdentifier;
|
||||||
@ -6037,14 +6136,19 @@ begin
|
|||||||
ParseExc(nErrUnknownOperatorType,SErrUnknownOperatorType,[CurTokenString]);
|
ParseExc(nErrUnknownOperatorType,SErrUnknownOperatorType,[CurTokenString]);
|
||||||
Name:=OperatorNames[Ot];
|
Name:=OperatorNames[Ot];
|
||||||
end;
|
end;
|
||||||
|
ptAnonymousProcedure,ptAnonymousFunction:
|
||||||
|
Name:='';
|
||||||
|
else
|
||||||
|
Name:=ExpectProcName;
|
||||||
|
end;
|
||||||
PC:=GetProcedureClass(ProcType);
|
PC:=GetProcedureClass(ProcType);
|
||||||
Parent:=CheckIfOverLoaded(Parent,Name);
|
if Name<>'' then
|
||||||
|
Parent:=CheckIfOverLoaded(Parent,Name);
|
||||||
Result:=TPasProcedure(CreateElement(PC,Name,Parent,AVisibility));
|
Result:=TPasProcedure(CreateElement(PC,Name,Parent,AVisibility));
|
||||||
ok:=false;
|
ok:=false;
|
||||||
try
|
try
|
||||||
if Not (ProcType in [ptFunction, ptClassFunction, ptOperator, ptClassOperator]) then
|
case ProcType of
|
||||||
Result.ProcType := TPasProcedureType(CreateElement(TPasProcedureType, '', Result))
|
ptFunction, ptClassFunction, ptOperator, ptClassOperator, ptAnonymousFunction:
|
||||||
else
|
|
||||||
begin
|
begin
|
||||||
Result.ProcType := CreateFunctionType('', 'Result', Result, False, CurTokenPos);
|
Result.ProcType := CreateFunctionType('', 'Result', Result, False, CurTokenPos);
|
||||||
if (ProcType in [ptOperator, ptClassOperator]) then
|
if (ProcType in [ptOperator, ptClassOperator]) then
|
||||||
@ -6054,6 +6158,9 @@ begin
|
|||||||
TPasOperator(Result).CorrectName;
|
TPasOperator(Result).CorrectName;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
else
|
||||||
|
Result.ProcType := TPasProcedureType(CreateElement(TPasProcedureType, '', Result));
|
||||||
|
end;
|
||||||
ParseProcedureOrFunctionHeader(Result, Result.ProcType, ProcType, False);
|
ParseProcedureOrFunctionHeader(Result, Result.ProcType, ProcType, False);
|
||||||
Result.Hints:=Result.ProcType.Hints;
|
Result.Hints:=Result.ProcType.Hints;
|
||||||
Result.HintMessage:=Result.ProcType.HintMessage;
|
Result.HintMessage:=Result.ProcType.HintMessage;
|
||||||
|
@ -32,7 +32,7 @@ type
|
|||||||
TSrcMarker = record
|
TSrcMarker = record
|
||||||
Kind: TSrcMarkerKind;
|
Kind: TSrcMarkerKind;
|
||||||
Filename: string;
|
Filename: string;
|
||||||
Row: integer;
|
Row: cardinal;
|
||||||
StartCol, EndCol: integer; // token start, end column
|
StartCol, EndCol: integer; // token start, end column
|
||||||
Identifier: string;
|
Identifier: string;
|
||||||
Next: PSrcMarker;
|
Next: PSrcMarker;
|
||||||
@ -447,6 +447,25 @@ type
|
|||||||
Procedure TestProc_ImplicitCalls;
|
Procedure TestProc_ImplicitCalls;
|
||||||
Procedure TestProc_Absolute;
|
Procedure TestProc_Absolute;
|
||||||
|
|
||||||
|
// anonymous procs
|
||||||
|
// ToDo: fppas2js: check "is TPasFunction", ".FuncType", "parent is TPasProcedureBody"
|
||||||
|
Procedure TestAnonymousProc_Assign;
|
||||||
|
// ToDo: does Delphi allow/require semicolon in assign?
|
||||||
|
Procedure TestAnonymousProc_Arg;
|
||||||
|
// ToDo: does Delphi allow/require semicolon in arg?
|
||||||
|
// ToDo: does Delphi allow calling directly?: function(i: word):word begin end(3)
|
||||||
|
Procedure TestAnonymousProc_EqualFail;
|
||||||
|
// ToDo: does Delphi allow ano proc in const?
|
||||||
|
Procedure TestAnonymousProc_ConstFail;
|
||||||
|
// ToDo: does Delphi allow assembler or calling conventions?
|
||||||
|
Procedure TestAnonymousProc_Assembler;
|
||||||
|
Procedure TestAnonymousProc_NameFail;
|
||||||
|
Procedure TestAnonymousProc_StatementFail;
|
||||||
|
Procedure TestAnonymousProc_Typecast;// ToDo
|
||||||
|
// ToDo: ano in with
|
||||||
|
// ToDo: ano in nested
|
||||||
|
// ToDo: ano in ano
|
||||||
|
|
||||||
// record
|
// record
|
||||||
Procedure TestRecord;
|
Procedure TestRecord;
|
||||||
Procedure TestRecordVariant;
|
Procedure TestRecordVariant;
|
||||||
@ -1411,7 +1430,7 @@ var
|
|||||||
DeclEl:=TPasAliasType(El).DestType;
|
DeclEl:=TPasAliasType(El).DestType;
|
||||||
ResolverEngine.UnmangleSourceLineNumber(DeclEl.SourceLinenumber,LabelLine,LabelCol);
|
ResolverEngine.UnmangleSourceLineNumber(DeclEl.SourceLinenumber,LabelLine,LabelCol);
|
||||||
if (aLabel^.Filename=DeclEl.SourceFilename)
|
if (aLabel^.Filename=DeclEl.SourceFilename)
|
||||||
and (aLabel^.Row=LabelLine)
|
and (integer(aLabel^.Row)=LabelLine)
|
||||||
and (aLabel^.StartCol<=LabelCol)
|
and (aLabel^.StartCol<=LabelCol)
|
||||||
and (aLabel^.EndCol>=LabelCol) then
|
and (aLabel^.EndCol>=LabelCol) then
|
||||||
exit; // success
|
exit; // success
|
||||||
@ -1491,8 +1510,8 @@ begin
|
|||||||
if (Marker<>nil) then
|
if (Marker<>nil) then
|
||||||
begin
|
begin
|
||||||
if Item.SourcePos.Row<>Marker^.Row then continue;
|
if Item.SourcePos.Row<>Marker^.Row then continue;
|
||||||
if (Item.SourcePos.Column<Marker^.StartCol)
|
if (integer(Item.SourcePos.Column)<Marker^.StartCol)
|
||||||
or (Item.SourcePos.Column>Marker^.EndCol) then continue;
|
or (integer(Item.SourcePos.Column)>Marker^.EndCol) then continue;
|
||||||
end;
|
end;
|
||||||
// found
|
// found
|
||||||
FResolverGoodMsgs.Add(Item);
|
FResolverGoodMsgs.Add(Item);
|
||||||
@ -7135,6 +7154,137 @@ begin
|
|||||||
'begin']);
|
'begin']);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestAnonymousProc_Assign;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TFunc = reference to function(x: word): word;',
|
||||||
|
'var Func: TFunc;',
|
||||||
|
'procedure DoIt(a: word);',
|
||||||
|
'begin',
|
||||||
|
' Func:=function(b:word): word',
|
||||||
|
' begin',
|
||||||
|
' Result:=a+b;',
|
||||||
|
' exit(b);',
|
||||||
|
' exit(Result);',
|
||||||
|
' end;',
|
||||||
|
' a:=3;',// test semicolon
|
||||||
|
'end;',
|
||||||
|
'begin']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestAnonymousProc_Arg;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TProc = reference to procedure;',
|
||||||
|
' TFunc = reference to function(x: word): word;',
|
||||||
|
'procedure DoMore(f,g: TProc);',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'procedure DoIt(f: TFunc);',
|
||||||
|
'begin',
|
||||||
|
' DoIt(function(b:word): word',
|
||||||
|
' begin',
|
||||||
|
' Result:=1+b;',
|
||||||
|
' end;);',
|
||||||
|
' DoMore(procedure begin end;, procedure begin end);',
|
||||||
|
'end;',
|
||||||
|
'begin']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestAnonymousProc_EqualFail;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TFunc = reference to function(x: word): word;',
|
||||||
|
'procedure DoIt(f: TFunc);',
|
||||||
|
'var w: word;',
|
||||||
|
'begin',
|
||||||
|
' if w=function(b:word): word',
|
||||||
|
' begin',
|
||||||
|
' Result:=1+b;',
|
||||||
|
' end; then ;',
|
||||||
|
'end;',
|
||||||
|
'begin']);
|
||||||
|
CheckResolverException('Incompatible types: got "Procedure/Function" expected "Word"',nIncompatibleTypesGotExpected);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestAnonymousProc_ConstFail;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TProc = reference to procedure;',
|
||||||
|
'const',
|
||||||
|
' p: TProc = procedure begin end;',
|
||||||
|
'begin']);
|
||||||
|
CheckParserException('Identifier expected at token "procedure" in file afile.pp at line 5 column 14',nParserExpectedIdentifier);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestAnonymousProc_Assembler;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TProc = reference to procedure;',
|
||||||
|
'procedure DoIt(p: TProc);',
|
||||||
|
'begin',
|
||||||
|
' p:=procedure assembler; asm end;',
|
||||||
|
' p:=procedure() assembler; asm end;',
|
||||||
|
'end;',
|
||||||
|
'begin']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestAnonymousProc_NameFail;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TProc = reference to procedure;',
|
||||||
|
'procedure DoIt(p: TProc);',
|
||||||
|
'begin',
|
||||||
|
' p:=procedure Bla() begin end;',
|
||||||
|
'end;',
|
||||||
|
'begin']);
|
||||||
|
CheckParserException(SParserSyntaxError,nParserSyntaxError);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestAnonymousProc_StatementFail;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'procedure DoIt;',
|
||||||
|
'begin',
|
||||||
|
' procedure () begin end;',
|
||||||
|
'end;',
|
||||||
|
'begin']);
|
||||||
|
CheckParserException(SParserSyntaxError,nParserSyntaxError);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestAnonymousProc_Typecast;
|
||||||
|
begin
|
||||||
|
exit;
|
||||||
|
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TProc = reference to procedure(w: word);',
|
||||||
|
'procedure DoIt(p: TProc);',
|
||||||
|
'begin',
|
||||||
|
' p:=TProc(procedure(b: byte) begin end);',
|
||||||
|
' p:=TProc(procedure(b: byte) begin end;);',
|
||||||
|
'end;',
|
||||||
|
'begin']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestResolver.TestRecord;
|
procedure TTestResolver.TestRecord;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user