Scalar operators

This commit is contained in:
Michael Schimmel
2025-09-15 17:13:45 +02:00
parent a83d3bf9fc
commit f5c7121e26
3 changed files with 98 additions and 51 deletions
+82 -13
View File
@@ -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