internal override object Eval() { var left = LeftOperand.Eval(); var right = RightOperand.Eval(); if (left is double lDbl && right is double rDbl) { return(lDbl - rDbl); } if (left is bool lBool && right is bool rBool) { return((lBool ? 1 : 0) - (rBool ? 1 : 0)); // Maybe throw an exception instead? } if (left is bool lBool2 && right is double rDbl2) { return((lBool2 ? 1 : 0) - rDbl2); } if (left is double lDbl2 && right is bool rBool2) { return(lDbl2 - (rBool2 ? 1 : 0)); } return(left.ToString().Replace(right.ToString(), "")); //Interesting concept... I wonder if other languages do this? }
public override void Generate(CodeGenerator cg) { Label ret1 = cg.generator.DefineLabel(); Label end = cg.generator.DefineLabel(); LeftOperand.Generate(cg); RightOperand.Generate(cg); if (LeftOperand.returnType.isString) { cg.generator.Emit(OpCodes.Call, typeof(string).GetMethod("Compare", new Type[] { typeof(string), typeof(string) })); cg.generator.Emit(OpCodes.Ldc_I4_0); } cg.generator.Emit(OperatorOpCode, ret1); cg.generator.Emit(OpCodes.Ldc_I4_0); cg.generator.Emit(OpCodes.Br, end); cg.generator.MarkLabel(ret1); cg.generator.Emit(OpCodes.Ldc_I4_1); cg.generator.MarkLabel(end); }
internal override object Eval() { var left = LeftOperand.Eval(); var right = RightOperand.Eval(); if (left is double lDbl && right is double rDbl) { return(lDbl * rDbl); } if (left is bool lBool && right is bool rBool) { return((lBool ? 1 : 0) * (rBool ? 1 : 0)); } if (left is bool lBool2 && right is double rDbl2) { return((lBool2 ? 1 : 0) * rDbl2); } if (left is double lDbl2 && right is bool rBool2) { return(lDbl2 * (rBool2 ? 1 : 0)); } throw new InvalidOperationException($"Multiplication can not be performed on the operands [{left}] and [{right}]"); }
public override BaseType ValidateSemantic() { var leftType = LeftOperand.ValidateSemantic(); var rightType = RightOperand.ValidateSemantic(); if (leftType is IntType && rightType is IntType) { return(leftType); } if (leftType is StringType && rightType is StringType) { return(leftType); } if (leftType is IntType && rightType is StringType) { return(rightType); } if (leftType is StringType && rightType is IntType) { return(leftType); } throw new SemanticException($"add is not supported for {leftType} and {rightType}"); }
internal override object Eval() { var left = LeftOperand.Eval(); var right = RightOperand.Eval(); if (left is double lDbl && right is double rDbl) { return(lDbl + rDbl); } if (left is bool lBool && right is bool rBool) { return((lBool ? 1 : 0) + (rBool ? 1 : 0)); } if (left is bool lBool2 && right is double rDbl2) { return((lBool2 ? 1 : 0) + rDbl2); } if (left is double lDbl2 && right is bool rBool2) { return(lDbl2 + (rBool2 ? 1 : 0)); } return(left.ToString() + right.ToString()); }
public override DataType staticTypeCheck() { DataType leftType = LeftOperand.staticTypeCheck(); DataType rightType = RightOperand.staticTypeCheck(); if (leftType == DataType.StringType && rightType == DataType.StringType) { return(DataType.StringType); } else if (leftType == DataType.FloatType || rightType == DataType.FloatType) { return(DataType.FloatType); } else if (leftType == DataType.IntegerType && rightType == DataType.IntegerType) { return(DataType.IntegerType); } Log.Error("Type mismatch", Filename, Line, Position); return(DataType.NoneType); }
protected BinaryRelationship ComputeTransitiveRelationship(BinaryRelationship other, BinaryRelationship factory) { if (LeftOperand.Equals(other.LeftOperand)) { return(factory.CreateNew(RightOperand, other.RightOperand)); } else if (RightOperand.Equals(other.LeftOperand)) { return(factory.CreateNew(LeftOperand, other.RightOperand)); } else if (LeftOperand.Equals(other.RightOperand)) { return(factory.CreateNew(other.LeftOperand, RightOperand)); } else if (RightOperand.Equals(other.RightOperand)) { return(factory.CreateNew(other.LeftOperand, LeftOperand)); } else { return(null); } }
private BinaryRelationship GetTransitiveRelationship(EqualsRelationship other) { if (LeftOperand.Equals(other.LeftOperand)) { return(new ComparisonRelationship(ComparisonKind, other.RightOperand, RightOperand)); } else if (RightOperand.Equals(other.LeftOperand)) { return(new ComparisonRelationship(ComparisonKind, LeftOperand, other.RightOperand)); } else if (LeftOperand.Equals(other.RightOperand)) { return(new ComparisonRelationship(ComparisonKind, other.LeftOperand, RightOperand)); } else if (RightOperand.Equals(other.RightOperand)) { return(new ComparisonRelationship(ComparisonKind, LeftOperand, other.LeftOperand)); } else { return(null); } }
public override void GenerateCode(ILGenerator gen, CodeFlow cf) { CodeFlow.LoadEvaluationContext(gen); var leftDesc = LeftOperand.ExitDescriptor; var rightDesc = RightOperand.ExitDescriptor; var leftPrim = CodeFlow.IsValueType(leftDesc); var rightPrim = CodeFlow.IsValueType(rightDesc); cf.EnterCompilationScope(); LeftOperand.GenerateCode(gen, cf); cf.ExitCompilationScope(); if (leftPrim) { CodeFlow.InsertBoxIfNecessary(gen, leftDesc); } cf.EnterCompilationScope(); RightOperand.GenerateCode(gen, cf); cf.ExitCompilationScope(); if (rightPrim) { CodeFlow.InsertBoxIfNecessary(gen, rightDesc); } // returns bool gen.Emit(OpCodes.Call, _equalityCheck); // Invert the boolean var result = gen.DeclareLocal(typeof(bool)); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Ceq); gen.Emit(OpCodes.Stloc, result); gen.Emit(OpCodes.Ldloc, result); cf.PushDescriptor(TypeDescriptor.Z); }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { ///check semantics al operando izquierdo LeftOperand.CheckSemantic(symbolTable, errors); ///check semantics al operando derecho RightOperand.CheckSemantic(symbolTable, errors); ///si alguno de los operandos evalúa de error este nodo también if (Object.Equals(LeftOperand.NodeInfo, SemanticInfo.SemanticError) || Object.Equals(RightOperand.NodeInfo, SemanticInfo.SemanticError)) { ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; return; } //los operandos tienen que ser compatibles if (!LeftOperand.NodeInfo.Type.IsCompatibleWith(RightOperand.NodeInfo.Type)) { errors.Add(new CompileError { Line = LeftOperand.Line, Column = LeftOperand.CharPositionInLine, ErrorMessage = string.Format("Operand '{0}' cannot be applied to operands of type '{1}' and '{2}'", this.Text, LeftOperand.NodeInfo.Type.Name, RightOperand.NodeInfo.Type.Name), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } ///seteamos la información del NodeInfo NodeInfo.BuiltInType = BuiltInType.Int; NodeInfo.Type = SemanticInfo.Int; NodeInfo.ILType = typeof(int); }
public override IEnumerable <ProgramState> TrySetConstraint(SymbolicValueConstraint constraint, ProgramState programState) { var boolConstraint = constraint as BoolConstraint; if (boolConstraint == null) { return(new[] { programState }); } if (constraint == BoolConstraint.False) { return(ThrowIfTooMany( LeftOperand.TrySetConstraint(BoolConstraint.False, programState) .SelectMany(ps => RightOperand.TrySetConstraint(BoolConstraint.False, ps)))); } return(ThrowIfTooMany( LeftOperand.TrySetConstraint(BoolConstraint.True, programState) .SelectMany(ps => RightOperand.TrySetConstraint(BoolConstraint.False, ps)) .Union(LeftOperand.TrySetConstraint(BoolConstraint.False, programState) .SelectMany(ps => RightOperand.TrySetConstraint(BoolConstraint.True, ps))) .Union(LeftOperand.TrySetConstraint(BoolConstraint.True, programState) .SelectMany(ps => RightOperand.TrySetConstraint(BoolConstraint.True, ps))))); }
public override ExpressionCode GenerateCode() { var leftType = LeftOperand.GenerateCode().Type; var rightType = RightOperand.GenerateCode().Type; if (leftType != null && rightType != null) { if (leftType == "float" || rightType == "float") { var s = " ( getFloatMultValue( " + LeftOperand.GenerateCode().Code + " , " + RightOperand.GenerateCode().Code + " ) )"; return(new ExpressionCode { Code = s, Type = "float" }); } var stringCode = "( getIntMultValue( " + LeftOperand.GenerateCode().Code + " , " + RightOperand.GenerateCode().Code + " ) )"; return(new ExpressionCode { Code = stringCode, Type = "int" }); } throw new GenerationException("Cannot generate code from null type operand"); }
public override void Generate(CodeGenerator cg) { Label push_false = cg.generator.DefineLabel(); Label end = cg.generator.DefineLabel(); LeftOperand.Generate(cg); cg.generator.Emit(OpCodes.Ldc_I4_0); cg.generator.Emit(OpCodes.Beq, push_false); //el primer operando era verdadero RightOperand.Generate(cg); cg.generator.Emit(OpCodes.Ldc_I4_0); cg.generator.Emit(OpCodes.Beq, push_false); //el segundo operando era verdadero cg.generator.Emit(OpCodes.Ldc_I4_1); cg.generator.Emit(OpCodes.Br, end); //el primer operando es falso cg.generator.MarkLabel(push_false); cg.generator.Emit(OpCodes.Ldc_I4_0); cg.generator.MarkLabel(end); }
public override void GenerateCode(ILGenerator gen, CodeFlow cf) { LeftOperand.GenerateCode(gen, cf); var leftDesc = LeftOperand.ExitDescriptor; var exitDesc = _exitTypeDescriptor; if (exitDesc == null) { throw new InvalidOperationException("No exit type descriptor"); } CodeFlow.InsertNumericUnboxOrPrimitiveTypeCoercion(gen, leftDesc, exitDesc); if (_children.Length > 1) { cf.EnterCompilationScope(); RightOperand.GenerateCode(gen, cf); var rightDesc = RightOperand.ExitDescriptor; cf.ExitCompilationScope(); CodeFlow.InsertNumericUnboxOrPrimitiveTypeCoercion(gen, rightDesc, exitDesc); gen.Emit(OpCodes.Rem); } cf.PushDescriptor(_exitTypeDescriptor); }
public override IQueryElement VisitWhere_operation([NotNull] QueryGrammarParser.Where_operationContext context) { IQueryElement leftValueTree = Visit(context.left); if (context.where_operator().is_null() != null) { OperationIsNull isNullTree = new OperationIsNull(); isNullTree.Add(leftValueTree); return(isNullTree); } else if (context.where_operator().is_not_null() != null) { OperationIsNotNull isNotNullTree = new OperationIsNotNull(); isNotNullTree.Add(leftValueTree); return(isNotNullTree); } OperationComperision comperasionTree = new OperationComperision(); LeftOperand left = new LeftOperand(); left.Add(leftValueTree); comperasionTree.Add(left); IQueryElement operatorTree = Visit(context.where_operator().comparison_operator()); comperasionTree.Add(operatorTree); RightOperand right = new RightOperand(); IQueryElement rightValueTree = Visit(context.right); right.Add(rightValueTree); comperasionTree.Add(right); return(comperasionTree); }
protected bool AreOperandsMatching(BinaryRelationship rel2) { return(LeftOperand.Equals(rel2.LeftOperand) && RightOperand.Equals(rel2.RightOperand) || RightOperand.Equals(rel2.LeftOperand) && LeftOperand.Equals(rel2.RightOperand)); }
public override double Compute(IReadOnlyDictionary <string, double> variableValues) => LeftOperand.Compute(variableValues) * RightOperand.Compute(variableValues);
/// <summary> /// Calculates the result of the binary operation. /// </summary> /// <param name="evalContext">Evaluation context</param> /// <returns>Result of the operation</returns> public override ushort Calculate(IEvaluationContext evalContext) => (ushort)(LeftOperand.Evaluate(evalContext) & RightOperand.Evaluate(evalContext));
public override string ToString() { return(String.Format("({0} \u2227 {1})", LeftOperand.ToString(), RightOperand.ToString())); }
internal bool AreOperandsMatching(BinaryRelationship other) { return(LeftOperand.Equals(other.LeftOperand) && RightOperand.Equals(other.RightOperand) || RightOperand.Equals(other.LeftOperand) && LeftOperand.Equals(other.RightOperand)); }
protected override Type ResolveInternal(Context ctx, bool mustReturn) { var leftType = LeftOperand.Resolve(ctx); var rightType = RightOperand.Resolve(ctx); var result = ResolveOperatorType(ctx, leftType, rightType); if (result != null) { return(result); } if (OverloadedMethodName != null) { try { OverloadedMethod = ctx.ResolveMethod(leftType, OverloadedMethodName, new[] { leftType, rightType }); } catch { try { OverloadedMethod = ctx.ResolveMethod(rightType, OverloadedMethodName, new[] { leftType, rightType }); } catch { } } // cannot be generic if (OverloadedMethod != null) { return(OverloadedMethod.ReturnType); } } if (IsNumericOperator) { if (leftType.IsNullableType() || rightType.IsNullableType()) { var leftNullable = leftType.IsNullableType() ? leftType.GetGenericArguments()[0] : leftType; var rightNullable = rightType.IsNullableType() ? rightType.GetGenericArguments()[0] : rightType; var commonNumericType = TypeExtensions.GetNumericOperationType(leftNullable, rightNullable); if (commonNumericType == null) { Error(CompilerMessages.OperatorTypesSignednessMismatch); } return(typeof(Nullable <>).MakeGenericType(commonNumericType)); } if (leftType.IsNumericType() && rightType.IsNumericType()) { var commonNumericType = TypeExtensions.GetNumericOperationType(leftType, rightType); if (commonNumericType == null) { Error(CompilerMessages.OperatorTypesSignednessMismatch); } return(commonNumericType); } } Error(this, CompilerMessages.OperatorBinaryTypesMismatch, OperatorRepresentation, leftType, rightType); return(null); }
public override double Evaluate() { return(LeftOperand.Evaluate() - RightOperand.Evaluate()); }
/// <summary>Creates a string representation of this binary operator.</summary> /// <returns>String representation of this binary operator.</returns> public override string ToString() { string operatorString = Member.ToString(); switch (Member) { case MethodNames.Add: operatorString = "+"; break; case MethodNames.AddAndAssign: operatorString = "+="; break; case MethodNames.Substract: operatorString = "-"; break; case MethodNames.SubstractAndAssign: operatorString = "-="; break; case MethodNames.Multiply: operatorString = "*"; break; case MethodNames.MultiplyAndAssign: operatorString = "*="; break; case MethodNames.Divide: operatorString = "/"; break; case MethodNames.DivideAndAssign: operatorString = "/="; break; case MethodNames.Modulo: operatorString = "%"; break; case MethodNames.ModuloAndAssign: operatorString = "%="; break; case MethodNames.Equal: operatorString = "=="; break; case MethodNames.NotEqual: operatorString = "!="; break; case MethodNames.GreaterThan: operatorString = ">"; break; case MethodNames.GreaterThanOrEqual: operatorString = ">="; break; case MethodNames.LessThan: operatorString = "<"; break; case MethodNames.LessThanOrEqual: operatorString = "<="; break; case MethodNames.BitwiseAnd: operatorString = "&"; break; case MethodNames.BitwiseAndAndAssign: operatorString = "&="; break; case MethodNames.BitwiseOr: operatorString = "|"; break; case MethodNames.BitwiseOrAndAssign: operatorString = "|="; break; case MethodNames.BitwiseXor: operatorString = "^"; break; case MethodNames.BitwiseXorAndAssign: operatorString = "^="; break; case MethodNames.BitwiseNot: operatorString = "~"; break; case MethodNames.BitwiseNotAndAssign: operatorString = "~="; break; case MethodNames.And: operatorString = "&&"; break; case MethodNames.Or: operatorString = "||"; break; case MethodNames.Xor: operatorString = "^^"; break; case MethodNames.BitwiseShiftLeft: operatorString = "<<"; break; case MethodNames.BitwiseShiftLeftAndAssign: operatorString = "<<="; break; case MethodNames.BitwiseShiftRight: operatorString = ">>"; break; case MethodNames.BitwiseShiftRightAndAssign: operatorString = ">>="; break; } return(System.String.Format( "{0}{1}{2}", LeftOperand != null ? LeftOperand.ToString() : System.String.Empty, operatorString, RightOperand != null ? RightOperand.ToString() : System.String.Empty)); }
/// <summary>Serves as the default hash function.</summary> /// <returns>Type: <see cref="System.Int32" /> /// A hash code for the current object.</returns> public override int GetHashCode() { return(typeof(BinaryOperator).FullName.GetHashCode() ^ (LeftOperand != null ? LeftOperand.GetHashCode() : 0) ^ (RightOperand != null ? RightOperand.GetHashCode() : 0)); }
/// <summary>Determines whether the specified object is equal to the current object.</summary> /// <param name="operand">Type: <see cref="System.Object" /> /// The object to compare with the current object.</param> /// <returns>Type: <see cref="System.Boolean" /> /// <b>true</b> if the specified object is equal to the current object; otherwise, <b>false</b>.</returns> public override bool Equals(object operand) { return((!Object.Equals(operand, null)) && (operand.GetType() == typeof(BinaryOperator)) && (LeftOperand != null ? LeftOperand.Equals(((BinaryOperator)operand).LeftOperand) : Object.Equals(((BinaryOperator)operand).LeftOperand, null)) && (RightOperand != null ? RightOperand.Equals(((BinaryOperator)operand).RightOperand) : Object.Equals(((BinaryOperator)operand).RightOperand, null))); }
/// <summary> /// Emits code for equality and inequality comparison. /// </summary> private void EmitEqualityComparison(Context ctx, Type left, Type right) { var gen = ctx.CurrentMethod.Generator; // compare two strings if (left == right && left == typeof(string)) { LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); var method = typeof(string).GetMethod("Equals", new[] { typeof(string), typeof(string) }); gen.EmitCall(method); if (Kind == ComparisonOperatorKind.NotEquals) { EmitInversion(gen); } return; } // compare primitive types if ((left.IsNumericType() && right.IsNumericType()) || (left == right && left == typeof(bool))) { if (left == typeof(bool)) { LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); } else { LoadAndConvertNumerics(ctx); } gen.EmitCompareEqual(); if (Kind == ComparisonOperatorKind.NotEquals) { EmitInversion(gen); } return; } // compare nullable against another nullable, it's base type or null if (left.IsNullableType()) { if (left == right || Nullable.GetUnderlyingType(left) == right) { EmitNullableComparison(ctx, LeftOperand, RightOperand); } else if (right == typeof(NullType)) { EmitHasValueCheck(ctx, LeftOperand); } return; } if (right.IsNullableType()) { if (Nullable.GetUnderlyingType(right) == left) { EmitNullableComparison(ctx, RightOperand, LeftOperand); } else if (left == typeof(NullType)) { EmitHasValueCheck(ctx, RightOperand); } return; } // compare a reftype against a null if (left == typeof(NullType) || right == typeof(NullType)) { LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); gen.EmitCompareEqual(); if (Kind == ComparisonOperatorKind.NotEquals) { EmitInversion(gen); } return; } if (left is TypeBuilder && left == right) { var equals = ctx.ResolveMethod(left, "Equals", new[] { typeof(object) }); LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); gen.EmitCall(equals.MethodInfo); if (Kind == ComparisonOperatorKind.NotEquals) { EmitInversion(gen); } return; } throw new ArgumentException("Unknown types to compare!"); }
/// <summary> /// Returns a <see cref="System.String" /> that represents this instance. /// </summary> /// <returns> /// A <see cref="System.String" /> that represents this instance. /// </returns> public override string ToString() { return(string.Format("({0}) OR ({1})", LeftOperand != null ? LeftOperand.ToString() : string.Empty, RightOperand != null ? RightOperand.ToString() : string.Empty)); }
public override string GenerateCode() { return($"{LeftOperand.GenerateCode()} > {RightOperand.GenerateCode()}"); }
internal bool AreOperandsSwapped(ComparisonRelationship rel) { return(LeftOperand.Equals(rel.RightOperand) && RightOperand.Equals(rel.LeftOperand)); }
/// <summary> /// Calculates the result of the binary operation. /// </summary> /// <param name="evalContext">Evaluation context</param> /// <returns>Result of the operation</returns> public override ExpressionValue Calculate(IEvaluationContext evalContext) { var left = LeftOperand.Evaluate(evalContext); var right = RightOperand.Evaluate(evalContext); switch (right.Type) { case ExpressionValueType.Bool: case ExpressionValueType.Integer: var rightNum = right.AsLong(); if (rightNum == 0) { EvaluationError = DIV_BY_ZERO_ERROR; return(ExpressionValue.Error); } switch (left.Type) { case ExpressionValueType.Bool: case ExpressionValueType.Integer: return(new ExpressionValue(left.AsLong() / rightNum)); case ExpressionValueType.Real: return(new ExpressionValue(left.AsReal() / rightNum)); case ExpressionValueType.String: EvaluationError = LEFT_STRING_ERROR; return(ExpressionValue.Error); default: return(ExpressionValue.Error); } case ExpressionValueType.Real: var rightReal = right.AsReal(); if (Math.Abs(rightReal) < double.Epsilon) { EvaluationError = DIV_BY_ZERO_ERROR; return(ExpressionValue.Error); } switch (left.Type) { case ExpressionValueType.Bool: case ExpressionValueType.Integer: return(new ExpressionValue(left.AsLong() / rightReal)); case ExpressionValueType.Real: return(new ExpressionValue(left.AsReal() / rightReal)); case ExpressionValueType.String: EvaluationError = LEFT_STRING_ERROR; return(ExpressionValue.Error); default: return(ExpressionValue.Error); } case ExpressionValueType.String: EvaluationError = RIGHT_STRING_ERROR; return(ExpressionValue.Error); default: return(ExpressionValue.Error); } }