public virtual void VisitBinaryExpression(BoundBinaryEx x) { Accept(x.Left); Accept(x.Right); }
protected virtual void Visit(BoundBinaryEx x, ConditionBranch branch) { base.VisitBinaryExpression(x); }
public virtual TResult VisitBinaryExpression(BoundBinaryEx x) => DefaultVisitOperation(x);
public sealed override void VisitBinaryExpression(BoundBinaryEx x) => Visit(x, ConditionBranch.Default);
TypeRefMask ResolveBinaryEx(BoundBinaryEx x, ConditionBranch branch) { if (x.Operation == Operations.And || x.Operation == Operations.Or) { this.VisitShortCircuitOp(x.Left, x.Right, x.Operation == Operations.And, branch); } else { Accept(x.Left); Accept(x.Right); } switch (x.Operation) { #region Arithmetic Operations case Operations.Add: return GetPlusOperationType(x.Left, x.Right); case Operations.Sub: case Operations.Div: case Operations.Mul: case Operations.Pow: if (IsDoubleOnly(x.Left.TypeRefMask) || IsDoubleOnly(x.Right.TypeRefMask)) // some operand is double and nothing else return TypeCtx.GetDoubleTypeMask(); // double if we are sure about operands return TypeCtx.GetNumberTypeMask(); case Operations.Mod: return TypeCtx.GetLongTypeMask(); case Operations.ShiftLeft: case Operations.ShiftRight: return TypeCtx.GetLongTypeMask(); #endregion #region Boolean and Bitwise Operations case Operations.And: case Operations.Or: case Operations.Xor: return TypeCtx.GetBooleanTypeMask(); case Operations.BitAnd: case Operations.BitOr: case Operations.BitXor: if (x.Left.ConstantValue.HasValue && x.Right.ConstantValue.HasValue) { x.ConstantValue = ResolveBitOperation(x.Left.ConstantValue.Value, x.Right.ConstantValue.Value, x.Operation); } return GetBitOperationType(x.Left.TypeRefMask, x.Right.TypeRefMask); // int or string #endregion #region Comparing Operations case Operations.Equal: case Operations.NotEqual: case Operations.GreaterThan: case Operations.LessThan: case Operations.GreaterThanOrEqual: case Operations.LessThanOrEqual: case Operations.Identical: case Operations.NotIdentical: if (branch == ConditionBranch.ToTrue) { if (x.Operation == Operations.LessThan && IsLongOnly(x.Right)) LTInt64Max(x.Left as BoundReferenceExpression, true); // $x < LONG } return TypeCtx.GetBooleanTypeMask(); #endregion case Operations.Concat: return TypeCtx.GetWritableStringTypeMask(); default: throw ExceptionUtilities.Unreachable; } }
protected override void Visit(BoundBinaryEx x, ConditionBranch branch) { x.TypeRefMask = ResolveBinaryEx(x, branch); }
public override void VisitCompoundAssign(BoundCompoundAssignEx x) { Debug.Assert(x.Target.Access.IsRead && x.Target.Access.IsWrite); Debug.Assert(x.Value.Access.IsRead); // Target X Value var tmp = new BoundBinaryEx(x.Target.WithAccess(BoundAccess.Read), x.Value, CompoundOpToBinaryOp(x.Operation)); Visit(tmp, ConditionBranch.AnyResult); // Target = Visit(x.Target, BoundAccess.Write.WithWrite(tmp.TypeRefMask)); // put read access back x.Target.Access = x.Target.Access.WithRead(); // x.TypeRefMask = tmp.TypeRefMask; }