Scalar operators
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<ProjectVersion>20.3</ProjectVersion>
|
||||
<FrameworkType>FMX</FrameworkType>
|
||||
<Base>True</Base>
|
||||
<Config Condition="'$(Config)'==''">Debug</Config>
|
||||
<Config Condition="'$(Config)'==''">Release</Config>
|
||||
<Platform Condition="'$(Platform)'==''">Win64</Platform>
|
||||
<ProjectName Condition="'$(ProjectName)'==''">ASTPlayground</ProjectName>
|
||||
<TargetedPlatforms>2</TargetedPlatforms>
|
||||
|
||||
@@ -395,7 +395,6 @@ end;
|
||||
function TEvaluatorVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
|
||||
var
|
||||
leftValue, rightValue: TDataValue;
|
||||
leftScalar, rightScalar: TScalar;
|
||||
begin
|
||||
leftValue := Node.Left.Accept(Self);
|
||||
rightValue := Node.Right.Accept(Self);
|
||||
@@ -403,51 +402,30 @@ begin
|
||||
if (leftValue.Kind <> vkScalar) or (rightValue.Kind <> vkScalar) then
|
||||
raise ENotSupportedException.Create('Binary operations are only supported for scalar types.');
|
||||
|
||||
leftScalar := leftValue.AsScalar;
|
||||
rightScalar := rightValue.AsScalar;
|
||||
|
||||
if not TScalar.IsBinaryOperatorSupported(Node.Operator, leftScalar.Kind, rightScalar.Kind) then
|
||||
raise ENotSupportedException.Create('Binary operation not supported for scalar type.');
|
||||
|
||||
case Node.Operator of
|
||||
boAdd: Result := leftScalar + rightScalar;
|
||||
boSubtract: Result := leftScalar - rightScalar;
|
||||
boMultiply: Result := leftScalar * rightScalar;
|
||||
boDivide: Result := leftScalar / rightScalar;
|
||||
boEqual: Result := TScalar.FromBoolean(leftScalar = rightScalar);
|
||||
boNotEqual: Result := TScalar.FromBoolean(leftScalar <> rightScalar);
|
||||
boLess: Result := TScalar.FromBoolean(leftScalar < rightScalar);
|
||||
boGreater: Result := TScalar.FromBoolean(leftScalar > rightScalar);
|
||||
boLessOrEqual: Result := TScalar.FromBoolean(leftScalar <= rightScalar);
|
||||
boGreaterOrEqual: Result := TScalar.FromBoolean(leftScalar >= rightScalar);
|
||||
else
|
||||
raise ENotSupportedException.Create('Unsupported binary operator.');
|
||||
end;
|
||||
var res: TScalar;
|
||||
if not TScalar.TryBinaryOperation(Node.Operator, leftValue.AsScalar, rightValue.AsScalar, res) then
|
||||
raise ENotSupportedException.Create(
|
||||
'Binary operation not supported for scalar types '
|
||||
+ leftValue.AsScalar.Kind.ToString
|
||||
+ ' and '
|
||||
+ rightValue.AsScalar.Kind.ToString
|
||||
+ ' .');
|
||||
Result := res;
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
|
||||
var
|
||||
rightValue: TDataValue;
|
||||
rightScalar: TScalar;
|
||||
begin
|
||||
rightValue := Node.Right.Accept(Self);
|
||||
|
||||
if not TScalar.IsUnaryOperatorSupported(Node.Operator, rightScalar.Kind) then
|
||||
raise ENotSupportedException.Create('Unary operation not supported for scalar type.');
|
||||
if rightValue.Kind <> vkScalar then
|
||||
raise ENotSupportedException.Create('Unary operations are only supported for scalar types.');
|
||||
|
||||
case Node.Operator of
|
||||
uoNegate:
|
||||
begin
|
||||
rightScalar := rightValue.AsScalar;
|
||||
Result := -rightScalar;
|
||||
end;
|
||||
uoNot:
|
||||
begin
|
||||
Result := TScalar.FromBoolean(not IsTruthy(rightValue));
|
||||
end;
|
||||
else
|
||||
raise ENotSupportedException.Create('Unary operator not supported');
|
||||
end;
|
||||
var res: TScalar;
|
||||
if not TScalar.TryUnaryOperation(Node.Operator, rightValue.AsScalar, res) then
|
||||
raise ENotSupportedException.Create('Unary operation not supported for scalar type' + rightValue.AsScalar.Kind.ToString + '.');
|
||||
Result := res;
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||
|
||||
@@ -100,6 +100,9 @@ type
|
||||
class function IsBinaryOperatorSupported(Op: TBinaryOperator; A, B: TScalarKind): Boolean; static;
|
||||
class function IsUnaryOperatorSupported(Op: TUnaryOperator; A: TScalarKind): Boolean; static;
|
||||
|
||||
class function TryBinaryOperation(Op: TBinaryOperator; const A, B: TScalar; out Res: TScalar): Boolean; static;
|
||||
class function TryUnaryOperation(Op: TUnaryOperator; const A: TScalar; out Res: TScalar): Boolean; static;
|
||||
|
||||
class operator Add(const A, B: TScalar): TScalar;
|
||||
class operator Divide(const A, B: TScalar): TScalar;
|
||||
class operator Equal(const A, B: TScalar): Boolean;
|
||||
@@ -107,6 +110,7 @@ type
|
||||
class operator GreaterThanOrEqual(const A, B: TScalar): Boolean;
|
||||
class operator LessThan(const A, B: TScalar): Boolean;
|
||||
class operator LessThanOrEqual(const A, B: TScalar): Boolean;
|
||||
class operator LogicalNot(const A: TScalar): TScalar;
|
||||
class operator Multiply(const A, B: TScalar): TScalar;
|
||||
class operator Negative(const A: TScalar): TScalar;
|
||||
class operator NotEqual(const A, B: TScalar): Boolean;
|
||||
@@ -471,31 +475,31 @@ end;
|
||||
|
||||
class function TScalar.StringToKind(const AName: string): TScalarKind;
|
||||
begin
|
||||
if SameText(AName, 'integer') then
|
||||
if SameText(AName, 'Integer') then
|
||||
Result := skInteger
|
||||
else if SameText(AName, 'int64') then
|
||||
else if SameText(AName, 'Int64') then
|
||||
Result := skInt64
|
||||
else if SameText(AName, 'uint64') then
|
||||
else if SameText(AName, 'UInt64') then
|
||||
Result := skUInt64
|
||||
else if SameText(AName, 'single') then
|
||||
else if SameText(AName, 'Single') then
|
||||
Result := skSingle
|
||||
else if SameText(AName, 'double') then
|
||||
else if SameText(AName, 'Double') then
|
||||
Result := skDouble
|
||||
else if SameText(AName, 'datetime') then
|
||||
else if SameText(AName, 'DateTime') then
|
||||
Result := skDateTime
|
||||
else if SameText(AName, 'timestamp') then
|
||||
else if SameText(AName, 'Timestamp') then
|
||||
Result := skTimestamp
|
||||
else if SameText(AName, 'boolean') then
|
||||
else if SameText(AName, 'Boolean') then
|
||||
Result := skBoolean
|
||||
else if SameText(AName, 'char') then
|
||||
else if SameText(AName, 'Char') then
|
||||
Result := skChar
|
||||
else if SameText(AName, 'pchar') then
|
||||
else if SameText(AName, 'PChar') then
|
||||
Result := skPChar
|
||||
else if SameText(AName, 'string') then
|
||||
else if SameText(AName, 'String') then
|
||||
Result := skString
|
||||
else if SameText(AName, 'bytes') then
|
||||
else if SameText(AName, 'Bytes') then
|
||||
Result := skBytes
|
||||
else if SameText(AName, 'decimal') then
|
||||
else if SameText(AName, 'Decimal') then
|
||||
Result := skDecimal
|
||||
else
|
||||
raise EArgumentException.CreateFmt('Unknown scalar type name: "%s"', [AName]);
|
||||
@@ -522,6 +526,58 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TScalar.TryBinaryOperation(Op: TBinaryOperator; const A, B: TScalar; out Res: TScalar): Boolean;
|
||||
begin
|
||||
if not IsBinaryOperatorSupported(Op, A.Kind, B.Kind) then
|
||||
begin
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
|
||||
try
|
||||
case Op of
|
||||
boAdd: Res := A + B;
|
||||
boSubtract: Res := A - B;
|
||||
boMultiply: Res := A * B;
|
||||
boDivide: Res := A / B;
|
||||
boEqual: Res := TScalar.FromBoolean(A = B);
|
||||
boNotEqual: Res := TScalar.FromBoolean(A <> B);
|
||||
boLess: Res := TScalar.FromBoolean(A < B);
|
||||
boGreater: Res := TScalar.FromBoolean(A > B);
|
||||
boLessOrEqual: Res := TScalar.FromBoolean(A <= B);
|
||||
boGreaterOrEqual: Res := TScalar.FromBoolean(A >= B);
|
||||
else
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TScalar.TryUnaryOperation(Op: TUnaryOperator; const A: TScalar; out Res: TScalar): Boolean;
|
||||
begin
|
||||
if not IsUnaryOperatorSupported(Op, A.Kind) then
|
||||
begin
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
|
||||
try
|
||||
case Op of
|
||||
uoNegate: Res := -A;
|
||||
uoNot: Res := not A;
|
||||
else
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
Result := True;
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
class operator TScalar.Add(const A, B: TScalar): TScalar;
|
||||
begin
|
||||
// Fast path for identical types
|
||||
@@ -916,6 +972,19 @@ begin
|
||||
Result := (A < B) or (A = B);
|
||||
end;
|
||||
|
||||
class operator TScalar.LogicalNot(const A: TScalar): TScalar;
|
||||
begin
|
||||
Result.Kind := A.Kind;
|
||||
case A.Kind of
|
||||
skBoolean: Result.Value.AsBoolean := not A.Value.AsBoolean;
|
||||
skInteger: Result.Value.AsInteger := not A.Value.AsInteger;
|
||||
skInt64: Result.Value.AsInt64 := not A.Value.AsInt64;
|
||||
skUInt64: Result.Value.AsUInt64 := not A.Value.AsUInt64;
|
||||
else
|
||||
raise EArgumentException.CreateFmt('Operator Not not supported for type %s', [A.Kind.ToString]);
|
||||
end;
|
||||
end;
|
||||
|
||||
class operator TScalar.Multiply(const A, B: TScalar): TScalar;
|
||||
begin
|
||||
// Fast path for identical types
|
||||
|
||||
Reference in New Issue
Block a user