|
@@ -276,6 +276,7 @@ type
|
|
|
btVariant, // variant
|
|
|
btNil, // nil = pointer, class, procedure, method, ...
|
|
|
btProc, // TPasProcedure
|
|
|
+ btBuiltInProc,
|
|
|
btSet,
|
|
|
btRange
|
|
|
);
|
|
@@ -363,7 +364,8 @@ const
|
|
|
'Text',
|
|
|
'Variant',
|
|
|
'Nil',
|
|
|
- 'PasProcedure',
|
|
|
+ 'Procedure/Function',
|
|
|
+ 'BuiltInProc',
|
|
|
'[set]',
|
|
|
'..range..'
|
|
|
);
|
|
@@ -707,8 +709,9 @@ type
|
|
|
end;
|
|
|
|
|
|
TResolvedReferenceFlag = (
|
|
|
- rrfVMT, // use VMT for call
|
|
|
- rrfNewInstance // constructor call
|
|
|
+ rrfCallWithoutParams, // a TPrimitiveExpr is a call without params
|
|
|
+ rrfNewInstance, // constructor call (without it call a constructor as normal method)
|
|
|
+ rrfVMT // use VMT for call
|
|
|
);
|
|
|
TResolvedReferenceFlags = set of TResolvedReferenceFlag;
|
|
|
|
|
@@ -872,6 +875,7 @@ type
|
|
|
procedure ResolveImplForLoop(Loop: TPasImplForLoop);
|
|
|
procedure ResolveImplWithDo(El: TPasImplWithDo);
|
|
|
procedure ResolveImplAssign(El: TPasImplAssign);
|
|
|
+ procedure ResolveImplSimple(El: TPasImplSimple);
|
|
|
procedure ResolveImplRaise(El: TPasImplRaise);
|
|
|
procedure ResolveExpr(El: TPasExpr);
|
|
|
procedure ResolveBooleanExpr(El: TPasExpr);
|
|
@@ -2058,7 +2062,7 @@ begin
|
|
|
Item:=FindLocalIdentifier(aName);
|
|
|
while Item<>nil do
|
|
|
begin
|
|
|
- writeln('TPasIdentifierScope.IterateElements ',ClassName,' ',Item.Identifier,' ',GetObjName(Item.Element));
|
|
|
+ //writeln('TPasIdentifierScope.IterateElements ',ClassName,' ',Item.Identifier,' ',GetObjName(Item.Element));
|
|
|
{$IFDEF VerbosePasResolver}
|
|
|
OldElement:=Item.Element;
|
|
|
{$ENDIF}
|
|
@@ -3391,7 +3395,7 @@ begin
|
|
|
else if El.ClassType=TPasImplAssign then
|
|
|
ResolveImplAssign(TPasImplAssign(El))
|
|
|
else if El.ClassType=TPasImplSimple then
|
|
|
- ResolveExpr(TPasImplSimple(El).expr)
|
|
|
+ ResolveImplSimple(TPasImplSimple(El))
|
|
|
else if El.ClassType=TPasImplBlock then
|
|
|
ResolveImplBlock(TPasImplBlock(El))
|
|
|
else if El.ClassType=TPasImplRepeatUntil then
|
|
@@ -3591,7 +3595,10 @@ begin
|
|
|
ComputeElement(El.right,RightResolved,[rcSkipTypeAlias]);
|
|
|
|
|
|
if RightResolved.BaseType=btProc then
|
|
|
+ begin
|
|
|
+ // ToDo: Delphi also uses left side to decide whether use function reference or function result
|
|
|
ComputeProcWithoutParams(RightResolved,El.right);
|
|
|
+ end;
|
|
|
|
|
|
case El.Kind of
|
|
|
akDefault:
|
|
@@ -3642,6 +3649,14 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
+procedure TPasResolver.ResolveImplSimple(El: TPasImplSimple);
|
|
|
+var
|
|
|
+ ExprResolved: TPasResolverResult;
|
|
|
+begin
|
|
|
+ ResolveExpr(El.expr);
|
|
|
+ ComputeElement(El.expr,ExprResolved,[rcSkipTypeAlias,rcReturnFuncResult]);
|
|
|
+end;
|
|
|
+
|
|
|
procedure TPasResolver.ResolveImplRaise(El: TPasImplRaise);
|
|
|
var
|
|
|
ResolvedEl: TPasResolverResult;
|
|
@@ -3717,14 +3732,15 @@ begin
|
|
|
DeclEl:=FindElementWithoutParams(aName,FindData,El,false);
|
|
|
if DeclEl is TPasProcedure then
|
|
|
begin
|
|
|
- // identifier is a call and args brackets are missing
|
|
|
+ // identifier is a proc and args brackets are missing
|
|
|
if El.Parent.ClassType=TPasProperty then
|
|
|
// a property accessor does not need args -> ok
|
|
|
else
|
|
|
begin
|
|
|
+ // examples: funca or @proca or a.funca or @a.funca ...
|
|
|
Proc:=TPasProcedure(DeclEl);
|
|
|
if (Proc.ProcType.Args.Count>0)
|
|
|
- and (TPasArgument(Proc.ProcType.Args[0]).ValueExpr=nil)
|
|
|
+ and (TPasArgument(Proc.ProcType.Args[0]).ValueExpr=nil) // no default value -> param needed
|
|
|
and not ExprIsAddrTarget(El)
|
|
|
then
|
|
|
RaiseMsg(nWrongNumberOfParametersForCallTo,
|
|
@@ -4608,10 +4624,19 @@ procedure TPasResolver.ComputeBinaryExpr(Bin: TBinaryExpr; out
|
|
|
var
|
|
|
LeftResolved, RightResolved: TPasResolverResult;
|
|
|
begin
|
|
|
+ if (Bin.OpCode=eopSubIdent)
|
|
|
+ or ((Bin.OpCode=eopNone) and (Bin.left is TInheritedExpr)) then
|
|
|
+ begin
|
|
|
+ ComputeElement(Bin.right,ResolvedEl,Flags);
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+
|
|
|
ComputeElement(Bin.left,LeftResolved,Flags);
|
|
|
ComputeElement(Bin.right,RightResolved,Flags);
|
|
|
// ToDo: check operator overloading
|
|
|
|
|
|
+ //writeln('TPasResolver.ComputeBinaryExpr ',OpcodeStrings[Bin.OpCode],' Left=',GetResolverResultDesc(LeftResolved),' Right=',GetResolverResultDesc(RightResolved));
|
|
|
+
|
|
|
if LeftResolved.BaseType=btProc then
|
|
|
ComputeProcWithoutParams(LeftResolved,Bin.left);
|
|
|
if RightResolved.BaseType=btProc then
|
|
@@ -5185,7 +5210,7 @@ var
|
|
|
Proc: TPasProcedure;
|
|
|
begin
|
|
|
if ExprIsAddrTarget(Expr) then exit;
|
|
|
- // call without arguments
|
|
|
+
|
|
|
if ResolvedEl.IdentEl=nil then
|
|
|
RaiseNotYetImplemented(20160928183455,Expr,GetResolverResultDesc(ResolvedEl));
|
|
|
if not (ResolvedEl.IdentEl is TPasProcedure) then
|
|
@@ -5195,6 +5220,9 @@ begin
|
|
|
and (TPasArgument(Proc.ProcType.Args[0]).ValueExpr=nil) then
|
|
|
RaiseMsg(nWrongNumberOfParametersForCallTo,sWrongNumberOfParametersForCallTo,
|
|
|
[GetProcDesc(Proc.ProcType)],Expr);
|
|
|
+
|
|
|
+ if Expr.CustomData is TResolvedReference then
|
|
|
+ Include(TResolvedReference(Expr.CustomData).Flags,rrfCallWithoutParams);
|
|
|
if (ResolvedEl.IdentEl is TPasFunction) then
|
|
|
ComputeElement(TPasFunction(ResolvedEl.IdentEl).FuncType.ResultEl,ResolvedEl,[])
|
|
|
else if ResolvedEl.IdentEl.ClassType=TPasConstructor then
|
|
@@ -5203,7 +5231,7 @@ begin
|
|
|
SetResolverValueExpr(ResolvedEl,btContext,aClass,Expr,[rrfReadable]);
|
|
|
end
|
|
|
else
|
|
|
- RaiseXExpectedButYFound('function',ResolvedEl.IdentEl.ElementTypeName,Expr);
|
|
|
+ ; // simple procedure call -> keep ResolvedEl as btProc
|
|
|
end;
|
|
|
|
|
|
procedure TPasResolver.CheckIsClass(El: TPasElement;
|
|
@@ -7582,6 +7610,7 @@ begin
|
|
|
begin
|
|
|
if rcConstant in Flags then
|
|
|
RaiseConstantExprExp(El);
|
|
|
+ Include(TResolvedReference(El.CustomData).Flags,rrfCallWithoutParams);
|
|
|
if ResolvedEl.IdentEl is TPasFunction then
|
|
|
// function => return result
|
|
|
ComputeElement(TPasFunction(ResolvedEl.IdentEl).FuncType.ResultEl,ResolvedEl,Flags-[rcReturnFuncResult])
|
|
@@ -7624,7 +7653,7 @@ begin
|
|
|
SetResolverIdentifier(ResolvedEl,TResElDataBaseType(El.CustomData).BaseType,
|
|
|
El,TPasUnresolvedSymbolRef(El),[])
|
|
|
else if El.CustomData is TResElDataBuiltInProc then
|
|
|
- RaiseInternalError(20161003174747) // should have been computed in El.ClassType=TParamsExpr
|
|
|
+ SetResolverIdentifier(ResolvedEl,btBuiltInProc,El,TPasUnresolvedSymbolRef(El),[])
|
|
|
else
|
|
|
RaiseNotYetImplemented(20160926194756,El);
|
|
|
end
|
|
@@ -7810,6 +7839,18 @@ begin
|
|
|
SetResolverIdentifier(ResolvedEl,btContext,El,TPasProcedureType(El),[])
|
|
|
else if El.ClassType=TPasArrayType then
|
|
|
SetResolverIdentifier(ResolvedEl,btContext,El,TPasArrayType(El),[])
|
|
|
+ else if El.ClassType=TInheritedExpr then
|
|
|
+ begin
|
|
|
+ if El.CustomData is TResolvedReference then
|
|
|
+ begin
|
|
|
+ DeclEl:=TResolvedReference(El.CustomData).Declaration as TPasProcedure;
|
|
|
+ SetResolverIdentifier(ResolvedEl,btProc,DeclEl,
|
|
|
+ TPasProcedure(DeclEl).ProcType,[]);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ // no ancestor proc
|
|
|
+ SetResolverIdentifier(ResolvedEl,btBuiltInProc,nil,nil,[]);
|
|
|
+ end
|
|
|
else
|
|
|
RaiseNotYetImplemented(20160922163705,El);
|
|
|
end;
|
|
@@ -7855,7 +7896,7 @@ begin
|
|
|
end;
|
|
|
|
|
|
function TPasResolver.ExprIsAddrTarget(El: TPasExpr): boolean;
|
|
|
-// returns true of El is the last element of an @ operator expression
|
|
|
+// returns true if El is the last element of an @ operator expression
|
|
|
// e.g. the OnClick in '@p().o[].OnClick'
|
|
|
// or '@s[]'
|
|
|
var
|