Scalar operators
This commit is contained in:
@@ -385,15 +385,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
function TEvaluatorVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
||||||
var
|
|
||||||
value: TDataValue;
|
|
||||||
begin
|
begin
|
||||||
if Assigned(Node.Initializer) then
|
if Assigned(Node.Initializer) then
|
||||||
value := Node.Initializer.Accept(Self);
|
Result := Node.Initializer.Accept(Self);
|
||||||
|
|
||||||
FScope[Node.Identifier.Address] := value;
|
FScope[Node.Identifier.Address] := Result;
|
||||||
|
|
||||||
Result := value;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
|
function TEvaluatorVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
|
||||||
@@ -410,58 +406,22 @@ begin
|
|||||||
leftScalar := leftValue.AsScalar;
|
leftScalar := leftValue.AsScalar;
|
||||||
rightScalar := rightValue.AsScalar;
|
rightScalar := rightValue.AsScalar;
|
||||||
|
|
||||||
if (leftScalar.Kind <> rightScalar.Kind) then
|
if not TScalar.IsBinaryOperatorSupported(Node.Operator, leftScalar.Kind, rightScalar.Kind) then
|
||||||
begin
|
raise ENotSupportedException.Create('Binary operation not supported for scalar type.');
|
||||||
if (leftScalar.Kind = skInt64) and (rightScalar.Kind = skDouble) then
|
|
||||||
leftScalar := TScalar.FromDouble(leftScalar.Value.AsInt64)
|
|
||||||
else if (leftScalar.Kind = skDouble) and (rightScalar.Kind = skInt64) then
|
|
||||||
rightScalar := TScalar.FromDouble(rightScalar.Value.AsInt64)
|
|
||||||
else
|
|
||||||
raise ENotSupportedException.Create(
|
|
||||||
'Binary operations are only supported for compatible types. ' + leftScalar.ToString + ' ' + rightScalar.ToString);
|
|
||||||
end;
|
|
||||||
|
|
||||||
case leftScalar.Kind of
|
case Node.Operator of
|
||||||
skInt64:
|
boAdd: Result := leftScalar + rightScalar;
|
||||||
begin
|
boSubtract: Result := leftScalar - rightScalar;
|
||||||
var leftVal := leftScalar.Value.AsInt64;
|
boMultiply: Result := leftScalar * rightScalar;
|
||||||
var rightVal := rightScalar.Value.AsInt64;
|
boDivide: Result := leftScalar / rightScalar;
|
||||||
case Node.Operator of
|
boEqual: Result := TScalar.FromBoolean(leftScalar = rightScalar);
|
||||||
boAdd: Result := TScalar.FromInt64(leftVal + rightVal);
|
boNotEqual: Result := TScalar.FromBoolean(leftScalar <> rightScalar);
|
||||||
boSubtract: Result := TScalar.FromInt64(leftVal - rightVal);
|
boLess: Result := TScalar.FromBoolean(leftScalar < rightScalar);
|
||||||
boMultiply: Result := TScalar.FromInt64(leftVal * rightVal);
|
boGreater: Result := TScalar.FromBoolean(leftScalar > rightScalar);
|
||||||
boDivide: Result := TScalar.FromInt64(leftVal div rightVal);
|
boLessOrEqual: Result := TScalar.FromBoolean(leftScalar <= rightScalar);
|
||||||
boEqual: Result := TScalar.FromBoolean(leftVal = rightVal);
|
boGreaterOrEqual: Result := TScalar.FromBoolean(leftScalar >= rightScalar);
|
||||||
boNotEqual: Result := TScalar.FromBoolean(leftVal <> rightVal);
|
|
||||||
boLess: Result := TScalar.FromBoolean(leftVal < rightVal);
|
|
||||||
boGreater: Result := TScalar.FromBoolean(leftVal > rightVal);
|
|
||||||
boLessOrEqual: Result := TScalar.FromBoolean(leftVal <= rightVal);
|
|
||||||
boGreaterOrEqual: Result := TScalar.FromBoolean(leftVal >= rightVal);
|
|
||||||
else
|
|
||||||
raise ENotSupportedException.Create('Operator not supported for Int64.');
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
skDouble:
|
|
||||||
begin
|
|
||||||
var leftVal := leftScalar.Value.AsDouble;
|
|
||||||
var rightVal := rightScalar.Value.AsDouble;
|
|
||||||
case Node.Operator of
|
|
||||||
boAdd: Result := TScalar.FromDouble(leftVal + rightVal);
|
|
||||||
boSubtract: Result := TScalar.FromDouble(leftVal - rightVal);
|
|
||||||
boMultiply: Result := TScalar.FromDouble(leftVal * rightVal);
|
|
||||||
boDivide: Result := TScalar.FromDouble(leftVal / rightVal);
|
|
||||||
boEqual: Result := TScalar.FromBoolean(leftVal = rightVal);
|
|
||||||
boNotEqual: Result := TScalar.FromBoolean(leftVal <> rightVal);
|
|
||||||
boLess: Result := TScalar.FromBoolean(leftVal < rightVal);
|
|
||||||
boGreater: Result := TScalar.FromBoolean(leftVal > rightVal);
|
|
||||||
boLessOrEqual: Result := TScalar.FromBoolean(leftVal <= rightVal);
|
|
||||||
boGreaterOrEqual: Result := TScalar.FromBoolean(leftVal >= rightVal);
|
|
||||||
else
|
|
||||||
raise ENotSupportedException.Create('Operator not supported for Double.');
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
else
|
else
|
||||||
raise ENotSupportedException.Create('Binary operations are not supported for this scalar type.');
|
raise ENotSupportedException.Create('Unsupported binary operator.');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -472,18 +432,14 @@ var
|
|||||||
begin
|
begin
|
||||||
rightValue := Node.Right.Accept(Self);
|
rightValue := Node.Right.Accept(Self);
|
||||||
|
|
||||||
|
if not TScalar.IsUnaryOperatorSupported(Node.Operator, rightScalar.Kind) then
|
||||||
|
raise ENotSupportedException.Create('Unary operation not supported for scalar type.');
|
||||||
|
|
||||||
case Node.Operator of
|
case Node.Operator of
|
||||||
uoNegate:
|
uoNegate:
|
||||||
begin
|
begin
|
||||||
if (rightValue.Kind <> vkScalar) then
|
|
||||||
raise ENotSupportedException.Create('Unary "-" is only supported for scalar types.');
|
|
||||||
rightScalar := rightValue.AsScalar;
|
rightScalar := rightValue.AsScalar;
|
||||||
case rightScalar.Kind of
|
Result := -rightScalar;
|
||||||
skInt64: Result := TScalar.FromInt64(-rightScalar.Value.AsInt64);
|
|
||||||
skDouble: Result := TScalar.FromDouble(-rightScalar.Value.AsDouble);
|
|
||||||
else
|
|
||||||
raise ENotSupportedException.Create('Unary "-" is not supported for this scalar type.');
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
uoNot:
|
uoNot:
|
||||||
begin
|
begin
|
||||||
@@ -495,27 +451,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function TEvaluatorVisitor.VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
var
|
|
||||||
conditionValue: TDataValue;
|
|
||||||
begin
|
begin
|
||||||
conditionValue := Node.Condition.Accept(Self);
|
if IsTruthy(Node.Condition.Accept(Self)) then
|
||||||
if IsTruthy(conditionValue) then
|
|
||||||
Result := Node.ThenBranch.Accept(Self)
|
Result := Node.ThenBranch.Accept(Self)
|
||||||
else
|
else if Assigned(Node.ElseBranch) then
|
||||||
begin
|
Result := Node.ElseBranch.Accept(Self);
|
||||||
if Assigned(Node.ElseBranch) then
|
|
||||||
Result := Node.ElseBranch.Accept(Self)
|
|
||||||
else
|
|
||||||
Result := TDataValue.Void;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function TEvaluatorVisitor.VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
||||||
var
|
|
||||||
conditionValue: TDataValue;
|
|
||||||
begin
|
begin
|
||||||
conditionValue := Node.Condition.Accept(Self);
|
if IsTruthy(Node.Condition.Accept(Self)) then
|
||||||
if IsTruthy(conditionValue) then
|
|
||||||
Result := Node.ThenBranch.Accept(Self)
|
Result := Node.ThenBranch.Accept(Self)
|
||||||
else
|
else
|
||||||
Result := Node.ElseBranch.Accept(Self);
|
Result := Node.ElseBranch.Accept(Self);
|
||||||
@@ -527,9 +472,7 @@ var
|
|||||||
begin
|
begin
|
||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
for expression in Node.Expressions do
|
for expression in Node.Expressions do
|
||||||
begin
|
|
||||||
Result := expression.Accept(Self);
|
Result := expression.Accept(Self);
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
function TEvaluatorVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ uses
|
|||||||
Myc.Data.Value;
|
Myc.Data.Value;
|
||||||
|
|
||||||
type
|
type
|
||||||
// Operators and helpers
|
|
||||||
TBinaryOperator = (boAdd, boSubtract, boMultiply, boDivide, boEqual, boNotEqual, boLess, boGreater, boLessOrEqual, boGreaterOrEqual);
|
|
||||||
TUnaryOperator = (uoNegate, uoNot);
|
|
||||||
|
|
||||||
TBinaryOperatorHelper = record helper for TBinaryOperator
|
TBinaryOperatorHelper = record helper for TBinaryOperator
|
||||||
function ToString: string;
|
function ToString: string;
|
||||||
end;
|
end;
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ type
|
|||||||
skDecimal
|
skDecimal
|
||||||
);
|
);
|
||||||
|
|
||||||
|
TBinaryOperator = (boAdd, boSubtract, boMultiply, boDivide, boEqual, boNotEqual, boLess, boGreater, boLessOrEqual, boGreaterOrEqual);
|
||||||
|
TUnaryOperator = (uoNegate, uoNot);
|
||||||
|
|
||||||
TScalarBytes = array[0..7] of Byte;
|
TScalarBytes = array[0..7] of Byte;
|
||||||
TScalarPChar = array[0..3] of Char;
|
TScalarPChar = array[0..3] of Char;
|
||||||
TScalarString = String[7];
|
TScalarString = String[7];
|
||||||
@@ -94,11 +97,12 @@ type
|
|||||||
|
|
||||||
function ToString: String;
|
function ToString: String;
|
||||||
|
|
||||||
|
class function IsBinaryOperatorSupported(Op: TBinaryOperator; A, B: TScalarKind): Boolean; static;
|
||||||
|
class function IsUnaryOperatorSupported(Op: TUnaryOperator; A: TScalarKind): Boolean; static;
|
||||||
|
|
||||||
class operator Add(const A, B: TScalar): TScalar;
|
class operator Add(const A, B: TScalar): TScalar;
|
||||||
class operator Divide(const A, B: TScalar): TScalar;
|
class operator Divide(const A, B: TScalar): TScalar;
|
||||||
class operator Equal(const A, B: TScalar): Boolean;
|
class operator Equal(const A, B: TScalar): Boolean;
|
||||||
|
|
||||||
//TODO implementieren
|
|
||||||
class operator GreaterThan(const A, B: TScalar): Boolean;
|
class operator GreaterThan(const A, B: TScalar): Boolean;
|
||||||
class operator GreaterThanOrEqual(const A, B: TScalar): Boolean;
|
class operator GreaterThanOrEqual(const A, B: TScalar): Boolean;
|
||||||
class operator LessThan(const A, B: TScalar): Boolean;
|
class operator LessThan(const A, B: TScalar): Boolean;
|
||||||
@@ -406,6 +410,65 @@ begin
|
|||||||
Result.Value := TScalarValue.FromUInt64(AValue);
|
Result.Value := TScalarValue.FromUInt64(AValue);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TScalar.IsBinaryOperatorSupported(Op: TBinaryOperator; A, B: TScalarKind): Boolean;
|
||||||
|
begin
|
||||||
|
const FLOAT_KINDS: set of TScalarKind = [skSingle, skDouble];
|
||||||
|
const ORDINAL_KINDS: set of TScalarKind = [skInteger, skInt64, skUInt64];
|
||||||
|
const NUMERIC_KINDS: set of TScalarKind = FLOAT_KINDS + ORDINAL_KINDS + [skDecimal];
|
||||||
|
const COMPARABLE_KINDS: set of TScalarKind = NUMERIC_KINDS + [skDateTime, skChar, skString];
|
||||||
|
|
||||||
|
// General check for incompatible types
|
||||||
|
if (A = B) then
|
||||||
|
begin
|
||||||
|
case Op of
|
||||||
|
boAdd, boSubtract, boMultiply, boDivide: Result := A in NUMERIC_KINDS + [skDateTime];
|
||||||
|
boEqual, boNotEqual, boLess, boGreater, boLessOrEqual, boGreaterOrEqual: Result := A in COMPARABLE_KINDS;
|
||||||
|
else
|
||||||
|
Result := False;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// Mixed-type checks
|
||||||
|
case Op of
|
||||||
|
boAdd:
|
||||||
|
Result :=
|
||||||
|
(((A in NUMERIC_KINDS) and (B in NUMERIC_KINDS))
|
||||||
|
or ((A = skDateTime) and (B in ORDINAL_KINDS + FLOAT_KINDS))
|
||||||
|
or ((B = skDateTime) and (A in ORDINAL_KINDS + FLOAT_KINDS)));
|
||||||
|
boSubtract:
|
||||||
|
Result := (((A in NUMERIC_KINDS) and (B in NUMERIC_KINDS)) or ((A = skDateTime) and (B in NUMERIC_KINDS + [skDateTime])));
|
||||||
|
boMultiply, boDivide: Result := (A in NUMERIC_KINDS) and (B in NUMERIC_KINDS);
|
||||||
|
boEqual, boNotEqual, boLess, boGreater, boLessOrEqual, boGreaterOrEqual:
|
||||||
|
Result := (A in NUMERIC_KINDS) and (B in NUMERIC_KINDS);
|
||||||
|
else
|
||||||
|
Result := False;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Specific exclusion rules
|
||||||
|
if Result then
|
||||||
|
begin
|
||||||
|
// Decimal cannot be mixed with floats for any operator
|
||||||
|
if ((A = skDecimal) and (B in FLOAT_KINDS)) or ((B = skDecimal) and (A in FLOAT_KINDS)) then
|
||||||
|
Result :=
|
||||||
|
False
|
||||||
|
// Cannot subtract a DateTime from a Numeric type
|
||||||
|
else if (Op = boSubtract) and (A in NUMERIC_KINDS) and (B = skDateTime) then
|
||||||
|
Result := False;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TScalar.IsUnaryOperatorSupported(Op: TUnaryOperator; A: TScalarKind): Boolean;
|
||||||
|
begin
|
||||||
|
case Op of
|
||||||
|
uoNegate: Result := A in [skInteger, skInt64, skSingle, skDouble, skDecimal];
|
||||||
|
uoNot: Result := A in [skBoolean, skInteger, skInt64, skUInt64];
|
||||||
|
else
|
||||||
|
Result := False;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
class function TScalar.StringToKind(const AName: string): TScalarKind;
|
class function TScalar.StringToKind(const AName: string): TScalarKind;
|
||||||
begin
|
begin
|
||||||
if SameText(AName, 'integer') then
|
if SameText(AName, 'integer') then
|
||||||
|
|||||||
Reference in New Issue
Block a user