|
@@ -85,7 +85,7 @@ Type
|
|
|
|
|
|
EExprScanner = Class(Exception);
|
|
|
|
|
|
- TResultType = (rtBoolean,rtInteger,rtFloat,rtDateTime,rtString);
|
|
|
+ TResultType = (rtBoolean,rtInteger,rtFloat,rtDateTime,rtString,rtCurrency);
|
|
|
TResultTypes = set of TResultType;
|
|
|
|
|
|
TFPExpressionResult = record
|
|
@@ -94,6 +94,7 @@ Type
|
|
|
rtBoolean : (ResBoolean : Boolean);
|
|
|
rtInteger : (ResInteger : Int64);
|
|
|
rtFloat : (ResFloat : TExprFloat);
|
|
|
+ rtCurrency : (ResCurrency : Currency);
|
|
|
rtDateTime : (ResDateTime : TDatetime);
|
|
|
rtString : ();
|
|
|
end;
|
|
@@ -389,12 +390,21 @@ Type
|
|
|
end;
|
|
|
|
|
|
{ TIntToFloatNode }
|
|
|
+
|
|
|
TIntToFloatNode = Class(TIntConvertNode)
|
|
|
Public
|
|
|
Function NodeType : TResultType; override;
|
|
|
Procedure GetNodeValue(var Result : TFPExpressionResult); override;
|
|
|
end;
|
|
|
|
|
|
+ { TIntToCurrencyNode }
|
|
|
+
|
|
|
+ TIntToCurrencyNode = Class(TIntConvertNode)
|
|
|
+ Public
|
|
|
+ Function NodeType : TResultType; override;
|
|
|
+ Procedure GetNodeValue(var Result : TFPExpressionResult); override;
|
|
|
+ end;
|
|
|
+
|
|
|
{ TIntToDateTimeNode }
|
|
|
|
|
|
TIntToDateTimeNode = Class(TIntConvertNode)
|
|
@@ -412,6 +422,34 @@ Type
|
|
|
Procedure GetNodeValue(var Result : TFPExpressionResult); override;
|
|
|
end;
|
|
|
|
|
|
+ { TFloatToCurrencyNode }
|
|
|
+
|
|
|
+ TFloatToCurrencyNode = Class(TFPConvertNode)
|
|
|
+ Public
|
|
|
+ Procedure Check; override;
|
|
|
+ Function NodeType : TResultType; override;
|
|
|
+ Procedure GetNodeValue(var Result : TFPExpressionResult); override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { TCurrencyToDateTimeNode }
|
|
|
+
|
|
|
+ TCurrencyToDateTimeNode = Class(TFPConvertNode)
|
|
|
+ Public
|
|
|
+ Procedure Check; override;
|
|
|
+ Function NodeType : TResultType; override;
|
|
|
+ Procedure GetNodeValue(var Result : TFPExpressionResult); override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { TCurrencyToFloatNode }
|
|
|
+
|
|
|
+ TCurrencyToFloatNode = Class(TFPConvertNode)
|
|
|
+ Public
|
|
|
+ Procedure Check; override;
|
|
|
+ Function NodeType : TResultType; override;
|
|
|
+ Procedure GetNodeValue(var Result : TFPExpressionResult); override;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
{ TFPNegateOperation }
|
|
|
|
|
|
TFPNegateOperation = Class(TFPUnaryOperator)
|
|
@@ -433,6 +471,7 @@ Type
|
|
|
Constructor CreateDateTime(AValue : TDateTime);
|
|
|
Constructor CreateFloat(AValue : TExprFloat);
|
|
|
Constructor CreateBoolean(AValue : Boolean);
|
|
|
+ constructor CreateCurrency(AValue: Currency);
|
|
|
Procedure Check; override;
|
|
|
Function NodeType : TResultType; override;
|
|
|
Procedure GetNodeValue(var Result : TFPExpressionResult); override;
|
|
@@ -465,6 +504,7 @@ Type
|
|
|
function GetAsBoolean: Boolean;
|
|
|
function GetAsDateTime: TDateTime;
|
|
|
function GetAsFloat: TExprFloat;
|
|
|
+ function GetAsCurrency : Currency;
|
|
|
function GetAsInteger: Int64;
|
|
|
function GetAsString: String;
|
|
|
function GetResultType: TResultType;
|
|
@@ -473,6 +513,7 @@ Type
|
|
|
procedure SetAsBoolean(const AValue: Boolean);
|
|
|
procedure SetAsDateTime(const AValue: TDateTime);
|
|
|
procedure SetAsFloat(const AValue: TExprFloat);
|
|
|
+ procedure SetAsCurrency(const AValue: Currency);
|
|
|
procedure SetAsInteger(const AValue: Int64);
|
|
|
procedure SetAsString(const AValue: String);
|
|
|
procedure SetName(const AValue: ShortString);
|
|
@@ -487,6 +528,7 @@ Type
|
|
|
Procedure Assign(Source : TPersistent); override;
|
|
|
Function EventBasedVariable : Boolean; Inline;
|
|
|
Property AsFloat : TExprFloat Read GetAsFloat Write SetAsFloat;
|
|
|
+ Property AsCurrency : Currency Read GetAsCurrency Write SetAsCurrency;
|
|
|
Property AsInteger : Int64 Read GetAsInteger Write SetAsInteger;
|
|
|
Property AsString : String Read GetAsString Write SetAsString;
|
|
|
Property AsBoolean : Boolean Read GetAsBoolean Write SetAsBoolean;
|
|
@@ -539,6 +581,7 @@ Type
|
|
|
Function AddBooleanVariable(Const AName : ShortString; AValue : Boolean) : TFPExprIdentifierDef;
|
|
|
Function AddIntegerVariable(Const AName : ShortString; AValue : Integer) : TFPExprIdentifierDef;
|
|
|
Function AddFloatVariable(Const AName : ShortString; AValue : TExprFloat) : TFPExprIdentifierDef;
|
|
|
+ Function AddCurrencyVariable(Const AName : ShortString; AValue : Currency) : TFPExprIdentifierDef;
|
|
|
Function AddStringVariable(Const AName : ShortString; AValue : String) : TFPExprIdentifierDef;
|
|
|
Function AddDateTimeVariable(Const AName : ShortString; AValue : TDateTime) : TFPExprIdentifierDef;
|
|
|
Function AddFunction(Const AName : ShortString; Const AResultType : Char; Const AParamTypes : String; ACallBack : TFPExprFunctionCallBack) : TFPExprIdentifierDef;
|
|
@@ -576,6 +619,7 @@ Type
|
|
|
FargumentParams : TExprParameterArray;
|
|
|
Protected
|
|
|
Procedure CalcParams;
|
|
|
+ function ConvertArgument(aIndex: Integer; aNode: TFPExprNode; aType: TResultType): TFPExprNode; virtual;
|
|
|
Public
|
|
|
Procedure Check; override;
|
|
|
Constructor CreateFunction(AID : TFPExprIdentifierDef; Const Args : TExprArgumentArray); virtual;
|
|
@@ -622,6 +666,7 @@ Type
|
|
|
|
|
|
TAggregateSum = Class(TAggregateExpr)
|
|
|
Public
|
|
|
+ function ConvertArgument(aIndex: Integer; aNode: TFPExprNode; aType: TResultType): TFPExprNode; override;
|
|
|
Procedure InitAggregate; override;
|
|
|
Procedure UpdateAggregate; override;
|
|
|
end;
|
|
@@ -679,10 +724,10 @@ Type
|
|
|
FHashList : TFPHashObjectlist;
|
|
|
FDirty : Boolean;
|
|
|
procedure CheckEOF;
|
|
|
- function ConvertNode(Todo: TFPExprNode; ToType: TResultType): TFPExprNode;
|
|
|
function GetAsBoolean: Boolean;
|
|
|
function GetAsDateTime: TDateTime;
|
|
|
function GetAsFloat: TExprFloat;
|
|
|
+ function GetAsCurrency: Currency;
|
|
|
function GetAsInteger: Int64;
|
|
|
function GetAsString: String;
|
|
|
function MatchNodes(Todo, Match: TFPExprNode): TFPExprNode;
|
|
@@ -693,6 +738,8 @@ Type
|
|
|
procedure ParserError(Msg: String);
|
|
|
procedure SetExpression(const AValue: String); virtual;
|
|
|
Procedure CheckResultType(Const Res :TFPExpressionResult; AType : TResultType); inline;
|
|
|
+ Procedure CheckResultTypes(Const Res :TFPExpressionResult; ATypes : TResultTypes); inline;
|
|
|
+ Class function ConvertNode(Todo: TFPExprNode; ToType: TResultType): TFPExprNode;
|
|
|
class Function BuiltinsManager : TExprBuiltInManager;
|
|
|
Function Level1 : TFPExprNode;
|
|
|
Function Level2 : TFPExprNode;
|
|
@@ -714,7 +761,7 @@ Type
|
|
|
Destructor Destroy; override;
|
|
|
Function IdentifierByName(const AName : ShortString) : TFPExprIdentifierDef; virtual;
|
|
|
Procedure Clear;
|
|
|
- Procedure EvaluateExpression(Var Result : TFPExpressionResult);
|
|
|
+ Procedure EvaluateExpression(Out Result : TFPExpressionResult);
|
|
|
function ExtractNode(var N: TFPExprNode): Boolean;
|
|
|
Function Evaluate : TFPExpressionResult;
|
|
|
Function ResultType : TResultType;
|
|
@@ -722,6 +769,7 @@ Type
|
|
|
Procedure InitAggregate;
|
|
|
Procedure UpdateAggregate;
|
|
|
Property AsFloat : TExprFloat Read GetAsFloat;
|
|
|
+ Property AsCurrency : Currency Read GetAsCurrency;
|
|
|
Property AsInteger : Int64 Read GetAsInteger;
|
|
|
Property AsString : String Read GetAsString;
|
|
|
Property AsBoolean : Boolean Read GetAsBoolean;
|
|
@@ -752,6 +800,7 @@ Type
|
|
|
Function AddBooleanVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : Boolean) : TFPBuiltInExprIdentifierDef;
|
|
|
Function AddIntegerVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : Integer) : TFPBuiltInExprIdentifierDef;
|
|
|
Function AddFloatVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : TExprFloat) : TFPBuiltInExprIdentifierDef;
|
|
|
+ Function AddCurrencyVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : Currency) : TFPBuiltInExprIdentifierDef;
|
|
|
Function AddStringVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : String) : TFPBuiltInExprIdentifierDef;
|
|
|
Function AddDateTimeVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : TDateTime) : TFPBuiltInExprIdentifierDef;
|
|
|
Function AddFunction(Const ACategory : TBuiltInCategory; Const AName : ShortString; Const AResultType : Char; Const AParamTypes : String; ACallBack : TFPExprFunctionCallBack) : TFPBuiltInExprIdentifierDef;
|
|
@@ -877,6 +926,7 @@ begin
|
|
|
'B' : Result:=rtBoolean;
|
|
|
'I' : Result:=rtInteger;
|
|
|
'F' : Result:=rtFloat;
|
|
|
+ 'C' : Result:=rtCurrency;
|
|
|
else
|
|
|
RaiseParserError(SErrInvalidResultCharacter,[C]);
|
|
|
end;
|
|
@@ -899,6 +949,39 @@ begin
|
|
|
FreeAndNil(Builtins);
|
|
|
end;
|
|
|
|
|
|
+{ TFloatToCurrencyNode }
|
|
|
+
|
|
|
+procedure TFloatToCurrencyNode.Check;
|
|
|
+begin
|
|
|
+ CheckNodeType(Operand,[rtFloat]);
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloatToCurrencyNode.NodeType: TResultType;
|
|
|
+begin
|
|
|
+ Result:=rtCurrency;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TFloatToCurrencyNode.GetNodeValue(var Result: TFPExpressionResult);
|
|
|
+begin
|
|
|
+ Operand.GetNodeValue(Result);
|
|
|
+ Result.ResultType:=rtCurrency;
|
|
|
+ Result.ResCurrency:=Result.ResFloat;
|
|
|
+end;
|
|
|
+
|
|
|
+{ TIntToCurrencyNode }
|
|
|
+
|
|
|
+function TIntToCurrencyNode.NodeType: TResultType;
|
|
|
+begin
|
|
|
+ Result:=rtCurrency;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TIntToCurrencyNode.GetNodeValue(var Result: TFPExpressionResult);
|
|
|
+begin
|
|
|
+ Operand.GetNodeValue(Result);
|
|
|
+ Result.ResCurrency:=Result.ResInteger;
|
|
|
+ Result.ResultType:=rtCurrency;
|
|
|
+end;
|
|
|
+
|
|
|
{ TFPModuloOperation }
|
|
|
|
|
|
procedure TFPModuloOperation.Check;
|
|
@@ -936,8 +1019,12 @@ procedure TAggregateMax.InitAggregate;
|
|
|
begin
|
|
|
inherited InitAggregate;
|
|
|
FFirst:=True;
|
|
|
- FResult.ResultType:=rtFloat;
|
|
|
- FResult.resFloat:=0;
|
|
|
+ FResult.ResultType:=FArgumentNodes[0].NodeType;
|
|
|
+ Case FResult.ResultType of
|
|
|
+ rtFloat : FResult.resFloat:=0.0;
|
|
|
+ rtCurrency : FResult.resCurrency:=0.0;
|
|
|
+ rtInteger : FResult.resInteger:=0;
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
procedure TAggregateMax.UpdateAggregate;
|
|
@@ -950,18 +1037,21 @@ begin
|
|
|
FArgumentNodes[0].GetNodeValue(N);
|
|
|
if FFirst then
|
|
|
begin
|
|
|
+ FResult.ResultType:=N.ResultType;
|
|
|
FFirst:=False;
|
|
|
OK:=True;
|
|
|
end
|
|
|
else
|
|
|
Case N.ResultType of
|
|
|
rtFloat: OK:=N.ResFloat>FResult.ResFloat;
|
|
|
+ rtCurrency: OK:=N.ResCurrency>FResult.ResCurrency;
|
|
|
rtinteger: OK:=N.ResInteger>FResult.ResFloat;
|
|
|
end;
|
|
|
if OK then
|
|
|
Case N.ResultType of
|
|
|
rtFloat: FResult.ResFloat:=N.ResFloat;
|
|
|
rtinteger: FResult.ResFloat:=N.ResInteger;
|
|
|
+ rtCurrency: FResult.ResCurrency:=N.ResCurrency;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -971,8 +1061,12 @@ procedure TAggregateMin.InitAggregate;
|
|
|
begin
|
|
|
inherited InitAggregate;
|
|
|
FFirst:=True;
|
|
|
- FResult.ResultType:=rtFloat;
|
|
|
- FResult.resFloat:=0;
|
|
|
+ FResult.ResultType:=FArgumentNodes[0].NodeType;
|
|
|
+ Case FResult.ResultType of
|
|
|
+ rtFloat : FResult.resFloat:=0.0;
|
|
|
+ rtCurrency : FResult.resCurrency:=0.0;
|
|
|
+ rtInteger : FResult.resInteger:=0;
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
procedure TAggregateMin.UpdateAggregate;
|
|
@@ -985,18 +1079,19 @@ begin
|
|
|
FArgumentNodes[0].GetNodeValue(N);
|
|
|
if FFirst then
|
|
|
begin
|
|
|
- FResult.ResultType:=N.ResultType;
|
|
|
FFirst:=False;
|
|
|
OK:=True;
|
|
|
end
|
|
|
else
|
|
|
Case N.ResultType of
|
|
|
rtFloat: OK:=N.ResFloat<FResult.ResFloat;
|
|
|
+ rtCurrency: OK:=N.ResCurrency<FResult.ResCurrency;
|
|
|
rtinteger: OK:=N.ResInteger<FResult.ResFloat;
|
|
|
end;
|
|
|
if OK then
|
|
|
Case FResult.ResultType of
|
|
|
rtFloat: FResult.ResFloat:=N.ResFloat;
|
|
|
+ rtCurrency: FResult.ResCurrency:=N.ResCurrency;
|
|
|
rtinteger: FResult.ResFloat:=N.ResInteger;
|
|
|
end;
|
|
|
inherited UpdateAggregate;
|
|
@@ -1007,7 +1102,6 @@ end;
|
|
|
procedure TAggregateAvg.InitAggregate;
|
|
|
begin
|
|
|
inherited InitAggregate;
|
|
|
- FCount:=0;
|
|
|
end;
|
|
|
|
|
|
procedure TAggregateAvg.UpdateAggregate;
|
|
@@ -1019,15 +1113,30 @@ end;
|
|
|
procedure TAggregateAvg.GetNodeValue(var Result: TFPExpressionResult);
|
|
|
begin
|
|
|
inherited GetNodeValue(Result);
|
|
|
- Result.ResultType:=rtFloat;
|
|
|
+ Result.ResultType:=FResult.ResultType;
|
|
|
if FCount=0 then
|
|
|
- Result.ResFloat:=0
|
|
|
+ Case FResult.ResultType of
|
|
|
+ rtInteger:
|
|
|
+ begin
|
|
|
+ Result.ResultType:=rtFloat;
|
|
|
+ Result.ResFloat:=0.0;
|
|
|
+ end;
|
|
|
+ rtFloat:
|
|
|
+ Result.ResFloat:=0.0;
|
|
|
+ rtCurrency:
|
|
|
+ Result.ResCurrency:=0.0;
|
|
|
+ end
|
|
|
else
|
|
|
Case FResult.ResultType of
|
|
|
rtInteger:
|
|
|
+ begin
|
|
|
+ Result.ResultType:=rtFloat;
|
|
|
Result.ResFloat:=FResult.ResInteger/FCount;
|
|
|
+ end;
|
|
|
rtFloat:
|
|
|
Result.ResFloat:=FResult.ResFloat/FCount;
|
|
|
+ rtCurrency:
|
|
|
+ Result.ResCurrency:=FResult.ResCurrency/FCount;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -1058,12 +1167,20 @@ end;
|
|
|
|
|
|
{ TAggregateSum }
|
|
|
|
|
|
+function TAggregateSum.ConvertArgument(aIndex: Integer; aNode: TFPExprNode; aType: TResultType): TFPExprNode;
|
|
|
+begin
|
|
|
+ if not (aNode.NodeType in [rtFloat,rtInteger,rtCurrency]) then
|
|
|
+ RaiseParserError(SErrInvalidArgumentType,[aIndex,ResultTypeName(aType),ResultTypeName(aNode.NodeType)]);
|
|
|
+ Result:=aNode;
|
|
|
+end;
|
|
|
|
|
|
procedure TAggregateSum.InitAggregate;
|
|
|
+
|
|
|
begin
|
|
|
FResult.ResultType:=FArgumentNodes[0].NodeType;
|
|
|
Case FResult.ResultType of
|
|
|
rtFloat: FResult.ResFloat:=0.0;
|
|
|
+ rtCurrency : FResult.ResCurrency:=0.0;
|
|
|
rtinteger: FResult.ResInteger:=0;
|
|
|
end;
|
|
|
end;
|
|
@@ -1077,6 +1194,7 @@ begin
|
|
|
FArgumentNodes[0].GetNodeValue(R);
|
|
|
Case FResult.ResultType of
|
|
|
rtFloat: FResult.ResFloat:=FResult.ResFloat+R.ResFloat;
|
|
|
+ rtCurrency: FResult.ResCurrency:=FResult.ResCurrency+R.ResCurrency;
|
|
|
rtinteger: FResult.ResInteger:=FResult.ResInteger+R.ResInteger;
|
|
|
end;
|
|
|
end;
|
|
@@ -1468,7 +1586,7 @@ begin
|
|
|
FIdentifiers.Assign(AValue)
|
|
|
end;
|
|
|
|
|
|
-procedure TFPExpressionParser.EvaluateExpression(var Result: TFPExpressionResult);
|
|
|
+procedure TFPExpressionParser.EvaluateExpression(Out Result: TFPExpressionResult);
|
|
|
begin
|
|
|
If (FExpression='') then
|
|
|
ParserError(SErrInExpressionEmpty);
|
|
@@ -1493,19 +1611,26 @@ begin
|
|
|
Raise EExprParser.Create(Msg);
|
|
|
end;
|
|
|
|
|
|
-function TFPExpressionParser.ConvertNode(Todo : TFPExprNode; ToType : TResultType): TFPExprNode;
|
|
|
+Class function TFPExpressionParser.ConvertNode(Todo : TFPExprNode; ToType : TResultType): TFPExprNode;
|
|
|
begin
|
|
|
Result:=ToDo;
|
|
|
Case ToDo.NodeType of
|
|
|
rtInteger :
|
|
|
Case ToType of
|
|
|
rtFloat : Result:=TIntToFloatNode.Create(Result);
|
|
|
+ rtCurrency : Result:=TIntToCurrencyNode.Create(Result);
|
|
|
rtDateTime : Result:=TIntToDateTimeNode.Create(Result);
|
|
|
end;
|
|
|
rtFloat :
|
|
|
Case ToType of
|
|
|
+ rtCurrency : Result:=TFloatToCurrencyNode.Create(Result);
|
|
|
rtDateTime : Result:=TFloatToDateTimeNode.Create(Result);
|
|
|
end;
|
|
|
+ rtCurrency :
|
|
|
+ Case ToType of
|
|
|
+ rtFloat : Result:=TCurrencyToFloatNode.Create(Result);
|
|
|
+ rtDateTime : Result:=TCurrencyToDateTimeNode.Create(Result);
|
|
|
+ end;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -1537,8 +1662,26 @@ var
|
|
|
|
|
|
begin
|
|
|
EvaluateExpression(Res);
|
|
|
- CheckResultType(Res,rtFloat);
|
|
|
- Result:=Res.ResFloat;
|
|
|
+ CheckResultTypes(Res,[rtFloat,rtCurrency,rtInteger]);
|
|
|
+ case Res.ResultType of
|
|
|
+ rtInteger : Result:=Res.ResInteger;
|
|
|
+ rtFloat : Result:=Res.ResFloat;
|
|
|
+ rtCurrency : Result:=res.ResCurrency;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+function TFPExpressionParser.GetAsCurrency: Currency;
|
|
|
+var
|
|
|
+ Res: TFPExpressionResult;
|
|
|
+
|
|
|
+begin
|
|
|
+ EvaluateExpression(Res);
|
|
|
+ CheckResultTypes(Res,[rtFloat,rtCurrency,rtInteger]);
|
|
|
+ case Res.ResultType of
|
|
|
+ rtInteger : Result:=Res.ResInteger;
|
|
|
+ rtFloat : Result:=Res.ResFloat;
|
|
|
+ rtCurrency : Result:=res.ResCurrency;
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
function TFPExpressionParser.GetAsInteger: Int64;
|
|
@@ -1572,24 +1715,23 @@ end;
|
|
|
function TFPExpressionParser.MatchNodes(Todo,Match : TFPExprNode): TFPExprNode;
|
|
|
|
|
|
Var
|
|
|
- TT,MT : TResultType;
|
|
|
+ FromType,ToType : TResultType;
|
|
|
|
|
|
begin
|
|
|
Result:=Todo;
|
|
|
- TT:=Todo.NodeType;
|
|
|
- MT:=Match.NodeType;
|
|
|
- If (TT<>MT) then
|
|
|
- begin
|
|
|
- if (TT=rtInteger) then
|
|
|
- begin
|
|
|
- if (MT in [rtFloat,rtDateTime]) then
|
|
|
- Result:=ConvertNode(Todo,MT);
|
|
|
- end
|
|
|
- else if (TT=rtFloat) then
|
|
|
- begin
|
|
|
- if (MT=rtDateTime) then
|
|
|
- Result:=ConvertNode(Todo,rtDateTime);
|
|
|
- end;
|
|
|
+ FromType:=Todo.NodeType;
|
|
|
+ ToType:=Match.NodeType;
|
|
|
+ If (FromType<>ToType) then
|
|
|
+ Case FromType of
|
|
|
+ rtInteger:
|
|
|
+ if (ToType in [rtFloat,rtCurrency,rtDateTime]) then
|
|
|
+ Result:=ConvertNode(Todo,toType);
|
|
|
+ rtFloat:
|
|
|
+ if (ToType in [rtCurrency,rtDateTime]) then
|
|
|
+ Result:=ConvertNode(Todo,toType);
|
|
|
+ rtCurrency:
|
|
|
+ if (ToType in [rtFloat,rtDateTime]) then
|
|
|
+ Result:=ConvertNode(Todo,toType);
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -1937,6 +2079,12 @@ begin
|
|
|
RaiseParserError(SErrInvalidResultType,[ResultTypeName(Res.ResultType)]);
|
|
|
end;
|
|
|
|
|
|
+procedure TFPExpressionParser.CheckResultTypes(const Res: TFPExpressionResult; ATypes: TResultTypes);
|
|
|
+begin
|
|
|
+ If Not (Res.ResultType in ATypes) then
|
|
|
+ RaiseParserError(SErrInvalidResultType,[ResultTypeName(Res.ResultType)]);
|
|
|
+end;
|
|
|
+
|
|
|
class function TFPExpressionParser.BuiltinsManager: TExprBuiltInManager;
|
|
|
begin
|
|
|
Result:=BuiltinIdentifiers;
|
|
@@ -2085,6 +2233,15 @@ begin
|
|
|
Result.FValue.ResFloat:=AValue;
|
|
|
end;
|
|
|
|
|
|
+function TFPExprIdentifierDefs.AddCurrencyVariable(const AName: ShortString; AValue: Currency): TFPExprIdentifierDef;
|
|
|
+begin
|
|
|
+ Result:=Add as TFPExprIdentifierDef;
|
|
|
+ Result.IdentifierType:=itVariable;
|
|
|
+ Result.Name:=AName;
|
|
|
+ Result.ResultType:=rtCurrency;
|
|
|
+ Result.FValue.ResCurrency:=AValue;
|
|
|
+end;
|
|
|
+
|
|
|
function TFPExprIdentifierDefs.AddStringVariable(const AName: ShortString;
|
|
|
AValue: String): TFPExprIdentifierDef;
|
|
|
begin
|
|
@@ -2172,6 +2329,7 @@ begin
|
|
|
rtBoolean : FValue.ResBoolean:=FStringValue='True';
|
|
|
rtInteger : FValue.ResInteger:=StrToInt(AValue);
|
|
|
rtFloat : FValue.ResFloat:=StrToFloat(AValue, FileFormatSettings);
|
|
|
+ rtCurrency : FValue.ResFloat:=StrToCurr(AValue, FileFormatSettings);
|
|
|
rtDateTime : FValue.ResDateTime:=StrToDateTime(AValue, FileFormatSettings);
|
|
|
rtString : FValue.ResString:=AValue;
|
|
|
end
|
|
@@ -2180,6 +2338,7 @@ begin
|
|
|
rtBoolean : FValue.ResBoolean:=False;
|
|
|
rtInteger : FValue.ResInteger:=0;
|
|
|
rtFloat : FValue.ResFloat:=0.0;
|
|
|
+ rtCurrency : FValue.ResCurrency:=0.0;
|
|
|
rtDateTime : FValue.ResDateTime:=0;
|
|
|
rtString : FValue.ResString:='';
|
|
|
end
|
|
@@ -2260,6 +2419,13 @@ begin
|
|
|
FValue.ResFloat:=AValue;
|
|
|
end;
|
|
|
|
|
|
+procedure TFPExprIdentifierDef.SetAsCurrency(const AValue: Currency);
|
|
|
+begin
|
|
|
+ CheckVariable;
|
|
|
+ CheckResultType(rtCurrency);
|
|
|
+ FValue.ResCurrency:=AValue;
|
|
|
+end;
|
|
|
+
|
|
|
procedure TFPExprIdentifierDef.SetAsInteger(const AValue: Int64);
|
|
|
begin
|
|
|
CheckVariable;
|
|
@@ -2283,6 +2449,7 @@ begin
|
|
|
Result:='False';
|
|
|
rtInteger : Result:=IntToStr(FValue.ResInteger);
|
|
|
rtFloat : Result:=FloatToStr(FValue.ResFloat, FileFormatSettings);
|
|
|
+ rtCurrency : Result:=CurrToStr(FValue.ResCurrency, FileFormatSettings);
|
|
|
rtDateTime : Result:=FormatDateTime('cccc',FValue.ResDateTime, FileFormatSettings);
|
|
|
rtString : Result:=FValue.ResString;
|
|
|
end;
|
|
@@ -2304,7 +2471,7 @@ begin
|
|
|
if RT2<>RT then
|
|
|
begin
|
|
|
// Automatically convert integer to float.
|
|
|
- if (rt2=rtInteger) and (rt=rtFLoat) then
|
|
|
+ if (rt2=rtInteger) and (rt=rtFloat) then
|
|
|
begin
|
|
|
FValue.ResultType:=RT;
|
|
|
I:=FValue.resInteger;
|
|
@@ -2340,6 +2507,13 @@ begin
|
|
|
Result:=FValue.ResFloat;
|
|
|
end;
|
|
|
|
|
|
+function TFPExprIdentifierDef.GetAsCurrency: Currency;
|
|
|
+begin
|
|
|
+ CheckResultType(rtCurrency);
|
|
|
+ CheckVariable;
|
|
|
+ Result:=FValue.ResCurrency;
|
|
|
+end;
|
|
|
+
|
|
|
function TFPExprIdentifierDef.GetAsBoolean: Boolean;
|
|
|
begin
|
|
|
CheckResultType(rtBoolean);
|
|
@@ -2445,6 +2619,13 @@ begin
|
|
|
Result.Category:=ACategory;
|
|
|
end;
|
|
|
|
|
|
+function TExprBuiltInManager.AddCurrencyVariable(const ACategory: TBuiltInCategory; const AName: ShortString; AValue: Currency
|
|
|
+ ): TFPBuiltInExprIdentifierDef;
|
|
|
+begin
|
|
|
+ Result:=TFPBuiltInExprIdentifierDef(FDefs.AddCurrencyVariable(AName,AValue));
|
|
|
+ Result.Category:=ACategory;
|
|
|
+end;
|
|
|
+
|
|
|
function TExprBuiltInManager.AddStringVariable(
|
|
|
const ACategory: TBuiltInCategory; const AName: ShortString; AValue: String
|
|
|
): TFPBuiltInExprIdentifierDef;
|
|
@@ -2621,6 +2802,13 @@ begin
|
|
|
FValue.ResFloat:=AValue;
|
|
|
end;
|
|
|
|
|
|
+constructor TFPConstExpression.CreateCurrency(AValue: Currency);
|
|
|
+begin
|
|
|
+ Inherited create;
|
|
|
+ FValue.ResultType:=rtCurrency;
|
|
|
+ FValue.ResCurrency:=AValue;
|
|
|
+end;
|
|
|
+
|
|
|
constructor TFPConstExpression.CreateBoolean(AValue: Boolean);
|
|
|
begin
|
|
|
FValue.ResultType:=rtBoolean;
|
|
@@ -2650,6 +2838,7 @@ begin
|
|
|
rtDateTime : Result:=''''+FormatDateTime('cccc',FValue.resDateTime)+'''';
|
|
|
rtBoolean : If FValue.ResBoolean then Result:='True' else Result:='False';
|
|
|
rtFloat : Str(FValue.ResFloat,Result);
|
|
|
+ rtCurrency : Str(FValue.ResCurrency,Result);
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -2659,7 +2848,7 @@ end;
|
|
|
procedure TFPNegateOperation.Check;
|
|
|
begin
|
|
|
Inherited;
|
|
|
- If Not (Operand.NodeType in [rtInteger,rtFloat]) then
|
|
|
+ If Not (Operand.NodeType in [rtInteger,rtFloat,rtCurrency]) then
|
|
|
RaiseParserError(SErrNoNegation,[ResultTypeName(Operand.NodeType),Operand.AsString])
|
|
|
end;
|
|
|
|
|
@@ -2674,6 +2863,7 @@ begin
|
|
|
Case Result.ResultType of
|
|
|
rtInteger : Result.resInteger:=-Result.ResInteger;
|
|
|
rtFloat : Result.resFloat:=-Result.ResFloat;
|
|
|
+ rtCurrency : Result.resCurrency:=-Result.ResCurrency;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -2917,7 +3107,8 @@ begin
|
|
|
Case RT.ResultType of
|
|
|
rtBoolean : B:=RT.ResBoolean=RV.ResBoolean;
|
|
|
rtInteger : B:=RT.ResInteger=RV.ResInteger;
|
|
|
- rtFloat : B:=RT.ResFloat=RV.ResFLoat;
|
|
|
+ rtFloat : B:=RT.ResFloat=RV.ResFloat;
|
|
|
+ rtCurrency : B:=RT.resCurrency=RV.resCurrency;
|
|
|
rtDateTime : B:=RT.ResDateTime=RV.ResDateTime;
|
|
|
rtString : B:=RT.ResString=RV.ResString;
|
|
|
end;
|
|
@@ -3072,7 +3263,8 @@ begin
|
|
|
Case Result.ResultType of
|
|
|
rtBoolean : Result.resBoolean:=Result.ResBoolean=RRes.ResBoolean;
|
|
|
rtInteger : Result.resBoolean:=Result.ResInteger=RRes.ResInteger;
|
|
|
- rtFloat : Result.resBoolean:=Result.ResFloat=RRes.ResFLoat;
|
|
|
+ rtFloat : Result.resBoolean:=Result.ResFloat=RRes.ResFloat;
|
|
|
+ rtCurrency : Result.resBoolean:=Result.resCurrency=RRes.resCurrency;
|
|
|
rtDateTime : Result.resBoolean:=Result.ResDateTime=RRes.ResDateTime;
|
|
|
rtString : Result.resBoolean:=Result.ResString=RRes.ResString;
|
|
|
end;
|
|
@@ -3109,7 +3301,8 @@ begin
|
|
|
Right.GetNodeValue(RRes);
|
|
|
Case Result.ResultType of
|
|
|
rtInteger : Result.resBoolean:=Result.ResInteger<RRes.ResInteger;
|
|
|
- rtFloat : Result.resBoolean:=Result.ResFloat<RRes.ResFLoat;
|
|
|
+ rtFloat : Result.resBoolean:=Result.ResFloat<RRes.ResFloat;
|
|
|
+ rtCurrency : Result.resBoolean:=Result.resCurrency<RRes.resCurrency;
|
|
|
rtDateTime : Result.resBoolean:=Result.ResDateTime<RRes.ResDateTime;
|
|
|
rtString : Result.resBoolean:=Result.ResString<RRes.ResString;
|
|
|
end;
|
|
@@ -3135,10 +3328,17 @@ begin
|
|
|
rtInteger : case Right.NodeType of
|
|
|
rtInteger : Result.resBoolean:=Result.ResInteger>RRes.ResInteger;
|
|
|
rtFloat : Result.resBoolean:=Result.ResInteger>RRes.ResFloat;
|
|
|
+ rtCurrency : Result.resBoolean:=Result.ResInteger>RRes.resCurrency;
|
|
|
end;
|
|
|
rtFloat : case Right.NodeType of
|
|
|
rtInteger : Result.resBoolean:=Result.ResFloat>RRes.ResInteger;
|
|
|
- rtFloat : Result.resBoolean:=Result.ResFloat>RRes.ResFLoat;
|
|
|
+ rtFloat : Result.resBoolean:=Result.ResFloat>RRes.ResFloat;
|
|
|
+ rtCurrency : Result.resBoolean:=Result.ResFloat>RRes.ResCurrency;
|
|
|
+ end;
|
|
|
+ rtCurrency : case Right.NodeType of
|
|
|
+ rtInteger : Result.resBoolean:=Result.ResCurrency>RRes.ResInteger;
|
|
|
+ rtFloat : Result.resBoolean:=Result.ResCurrency>RRes.ResFloat;
|
|
|
+ rtCurrency : Result.resBoolean:=Result.ResCurrency>RRes.ResCurrency;
|
|
|
end;
|
|
|
rtDateTime : Result.resBoolean:=Result.ResDateTime>RRes.ResDateTime;
|
|
|
rtString : Result.resBoolean:=Result.ResString>RRes.ResString;
|
|
@@ -3177,7 +3377,7 @@ end;
|
|
|
procedure TFPOrderingOperation.Check;
|
|
|
|
|
|
Const
|
|
|
- AllowedTypes =[rtInteger,rtfloat,rtDateTime,rtString];
|
|
|
+ AllowedTypes =[rtInteger,rtfloat,rtCurrency,rtDateTime,rtString];
|
|
|
|
|
|
begin
|
|
|
CheckNodeType(Left,AllowedTypes);
|
|
@@ -3190,7 +3390,7 @@ end;
|
|
|
procedure TMathOperation.Check;
|
|
|
|
|
|
Const
|
|
|
- AllowedTypes =[rtInteger,rtfloat,rtDateTime,rtString];
|
|
|
+ AllowedTypes =[rtInteger,rtfloat,rtCurrency,rtDateTime,rtString];
|
|
|
|
|
|
begin
|
|
|
inherited Check;
|
|
@@ -3223,7 +3423,8 @@ begin
|
|
|
rtInteger : Result.ResInteger:=Result.ResInteger+RRes.ResInteger;
|
|
|
rtString : Result.ResString:=Result.ResString+RRes.ResString;
|
|
|
rtDateTime : Result.ResDateTime:=Result.ResDateTime+RRes.ResDateTime;
|
|
|
- rtFloat : Result.ResFLoat:=Result.ResFLoat+RRes.ResFLoat;
|
|
|
+ rtFloat : Result.ResFloat:=Result.ResFloat+RRes.ResFloat;
|
|
|
+ rtCurrency : Result.ResCurrency:=Result.ResCurrency+RRes.ResCurrency;
|
|
|
end;
|
|
|
Result.ResultType:=NodeType;
|
|
|
end;
|
|
@@ -3233,7 +3434,7 @@ end;
|
|
|
procedure TFPSubtractOperation.check;
|
|
|
|
|
|
Const
|
|
|
- AllowedTypes =[rtInteger,rtfloat,rtDateTime];
|
|
|
+ AllowedTypes =[rtInteger,rtfloat,rtCurrency,rtDateTime];
|
|
|
|
|
|
begin
|
|
|
CheckNodeType(Left,AllowedTypes);
|
|
@@ -3257,7 +3458,8 @@ begin
|
|
|
case Result.ResultType of
|
|
|
rtInteger : Result.ResInteger:=Result.ResInteger-RRes.ResInteger;
|
|
|
rtDateTime : Result.ResDateTime:=Result.ResDateTime-RRes.ResDateTime;
|
|
|
- rtFloat : Result.ResFLoat:=Result.ResFLoat-RRes.ResFLoat;
|
|
|
+ rtFloat : Result.ResFloat:=Result.ResFloat-RRes.ResFloat;
|
|
|
+ rtCurrency : Result.resCurrency:=Result.resCurrency-RRes.ResCurrency;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -3266,7 +3468,7 @@ end;
|
|
|
procedure TFPMultiplyOperation.check;
|
|
|
|
|
|
Const
|
|
|
- AllowedTypes =[rtInteger,rtfloat];
|
|
|
+ AllowedTypes =[rtInteger,rtCurrency,rtfloat];
|
|
|
|
|
|
begin
|
|
|
CheckNodeType(Left,AllowedTypes);
|
|
@@ -3288,7 +3490,8 @@ begin
|
|
|
Right.GetNodeValue(RRes);
|
|
|
case Result.ResultType of
|
|
|
rtInteger : Result.ResInteger:=Result.ResInteger*RRes.ResInteger;
|
|
|
- rtFloat : Result.ResFLoat:=Result.ResFLoat*RRes.ResFLoat;
|
|
|
+ rtFloat : Result.ResFloat:=Result.ResFloat*RRes.ResFloat;
|
|
|
+ rtCurrency : Result.ResCurrency:=Result.ResCurrency*RRes.ResCurrency;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -3296,7 +3499,7 @@ end;
|
|
|
|
|
|
procedure TFPDivideOperation.check;
|
|
|
Const
|
|
|
- AllowedTypes =[rtInteger,rtfloat];
|
|
|
+ AllowedTypes =[rtInteger,rtCurrency,rtfloat];
|
|
|
|
|
|
begin
|
|
|
CheckNodeType(Left,AllowedTypes);
|
|
@@ -3310,8 +3513,12 @@ begin
|
|
|
end;
|
|
|
|
|
|
function TFPDivideOperation.NodeType: TResultType;
|
|
|
+
|
|
|
begin
|
|
|
- Result:=rtFLoat;
|
|
|
+ if (Left.NodeType=rtCurrency) and (Right.NodeType=rtCurrency) then
|
|
|
+ Result:=rtCurrency
|
|
|
+ else
|
|
|
+ Result:=rtFloat;
|
|
|
end;
|
|
|
|
|
|
Procedure TFPDivideOperation.GetNodeValue(var Result : TFPExpressionResult);
|
|
@@ -3324,16 +3531,21 @@ begin
|
|
|
Right.GetNodeValue(RRes);
|
|
|
case Result.ResultType of
|
|
|
rtInteger : Result.ResFloat:=Result.ResInteger/RRes.ResInteger;
|
|
|
- rtFloat : Result.ResFLoat:=Result.ResFLoat/RRes.ResFLoat;
|
|
|
+ rtFloat : Result.ResFloat:=Result.ResFloat/RRes.ResFloat;
|
|
|
+ rtCurrency :
|
|
|
+ if NodeType=rtCurrency then
|
|
|
+ Result.ResCurrency:=Result.ResCurrency/RRes.ResCurrency
|
|
|
+ else
|
|
|
+ Result.ResFloat:=Result.ResFloat/RRes.ResFloat;
|
|
|
end;
|
|
|
- Result.ResultType:=rtFloat;
|
|
|
+ Result.ResultType:=NodeType;
|
|
|
end;
|
|
|
|
|
|
{ TFPPowerOperation }
|
|
|
|
|
|
procedure TFPPowerOperation.Check;
|
|
|
const
|
|
|
- AllowedTypes = [rtInteger, rtFloat];
|
|
|
+ AllowedTypes = [rtInteger, rtCurrency, rtFloat];
|
|
|
begin
|
|
|
CheckNodeType(Left, AllowedTypes);
|
|
|
CheckNodeType(Right, AllowedTypes);
|
|
@@ -3440,6 +3652,46 @@ begin
|
|
|
Result.ResultType:=rtDateTime;
|
|
|
end;
|
|
|
|
|
|
+{ TCurrencyToDateTimeNode }
|
|
|
+
|
|
|
+procedure TCurrencyToDateTimeNode.Check;
|
|
|
+begin
|
|
|
+ inherited Check;
|
|
|
+ CheckNodeType(Operand,[rtCurrency]);
|
|
|
+end;
|
|
|
+
|
|
|
+function TCurrencyToDateTimeNode.NodeType: TResultType;
|
|
|
+begin
|
|
|
+ Result:=rtDateTime;
|
|
|
+end;
|
|
|
+
|
|
|
+Procedure TCurrencyToDateTimeNode.GetNodeValue(var Result : TFPExpressionResult);
|
|
|
+begin
|
|
|
+ Operand.GetNodeValue(Result);
|
|
|
+ Result.ResDateTime:=Result.ResCurrency;
|
|
|
+ Result.ResultType:=rtDateTime;
|
|
|
+end;
|
|
|
+
|
|
|
+{ TCurrencyToFloatNode }
|
|
|
+
|
|
|
+procedure TCurrencyToFloatNode.Check;
|
|
|
+begin
|
|
|
+ inherited Check;
|
|
|
+ CheckNodeType(Operand,[rtCurrency]);
|
|
|
+end;
|
|
|
+
|
|
|
+function TCurrencyToFloatNode.NodeType: TResultType;
|
|
|
+begin
|
|
|
+ Result:=rtFloat;
|
|
|
+end;
|
|
|
+
|
|
|
+Procedure TCurrencyToFloatNode.GetNodeValue(var Result : TFPExpressionResult);
|
|
|
+begin
|
|
|
+ Operand.GetNodeValue(Result);
|
|
|
+ Result.ResFloat:=Result.ResCurrency;
|
|
|
+ Result.ResultType:=rtFloat;
|
|
|
+end;
|
|
|
+
|
|
|
{ TFPExprIdentifierNode }
|
|
|
|
|
|
constructor TFPExprIdentifierNode.CreateIdentifier(AID: TFPExprIdentifierDef);
|
|
@@ -3489,6 +3741,20 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
+Function TFPExprFunction.ConvertArgument(aIndex : Integer; aNode : TFPExprNode; aType : TResultType) : TFPExprNode;
|
|
|
+
|
|
|
+Var
|
|
|
+ N : TFPExprNode;
|
|
|
+
|
|
|
+begin
|
|
|
+ // Automatically convert integers to floats for float/currency parameters
|
|
|
+ N:=TFPExpressionParser.ConvertNode(aNode,aType);
|
|
|
+ if (aNode=N) then
|
|
|
+ // No conversion was performed, raise error
|
|
|
+ RaiseParserError(SErrInvalidArgumentType,[aIndex,ResultTypeName(aType),ResultTypeName(aNode.NodeType)]);
|
|
|
+ Result:=N;
|
|
|
+end;
|
|
|
+
|
|
|
function TFPExprFunction.HasAggregate: Boolean;
|
|
|
var
|
|
|
I: Integer;
|
|
@@ -3515,22 +3781,13 @@ begin
|
|
|
begin
|
|
|
rtp:=CharToResultType(FID.ParameterTypes[i+1]);
|
|
|
rta:=FArgumentNodes[i].NodeType;
|
|
|
- If (rtp<>rta) then begin
|
|
|
-
|
|
|
- // Automatically convert integers to floats in functions that return
|
|
|
- // a float
|
|
|
- if (rta = rtInteger) and (rtp = rtFloat) then begin
|
|
|
- FArgumentNodes[i] := TIntToFloatNode.Create(FArgumentNodes[i]);
|
|
|
- exit;
|
|
|
- end;
|
|
|
-
|
|
|
- RaiseParserError(SErrInvalidArgumentType,[I+1,ResultTypeName(rtp),ResultTypeName(rta)])
|
|
|
- end;
|
|
|
+ If (rtp<>rta) then
|
|
|
+ FArgumentNodes[i]:=ConvertArgument(I+1,FArgumentNodes[i],rtp);
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-constructor TFPExprFunction.CreateFunction(AID: TFPExprIdentifierDef;
|
|
|
- const Args: TExprArgumentArray);
|
|
|
+constructor TFPExprFunction.CreateFunction(AID: TFPExprIdentifierDef; const Args: TExprArgumentArray);
|
|
|
+
|
|
|
begin
|
|
|
Inherited CreateIdentifier(AID);
|
|
|
FArgumentNodes:=Args;
|
|
@@ -3637,6 +3894,8 @@ function ArgToFloat(Arg: TFPExpressionResult): TExprFloat;
|
|
|
begin
|
|
|
if Arg.ResultType = rtInteger then
|
|
|
result := Arg.resInteger
|
|
|
+ else if Arg.ResultType = rtCurrency then
|
|
|
+ result := Arg.resCurrency
|
|
|
else
|
|
|
result := Arg.resFloat;
|
|
|
end;
|