| File: Binder\Semantics\Operators\OperatorKindExtensions.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System.Diagnostics; using System.Linq.Expressions; using System.Text; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp { internal static partial class OperatorKindExtensions { public static int OperatorIndex(this UnaryOperatorKind kind) { return ((int)kind.Operator() >> 8) - 16; } public static UnaryOperatorKind Operator(this UnaryOperatorKind kind) { return kind & UnaryOperatorKind.OpMask; } public static UnaryOperatorKind Unlifted(this UnaryOperatorKind kind) { return kind & ~UnaryOperatorKind.Lifted; } public static bool IsLifted(this UnaryOperatorKind kind) { return 0 != (kind & UnaryOperatorKind.Lifted); } public static bool IsChecked(this UnaryOperatorKind kind) { return 0 != (kind & UnaryOperatorKind.Checked); } public static bool IsUserDefined(this UnaryOperatorKind kind) { return (kind & UnaryOperatorKind.TypeMask) == UnaryOperatorKind.UserDefined; } public static UnaryOperatorKind OverflowChecks(this UnaryOperatorKind kind) { return kind & UnaryOperatorKind.Checked; } public static UnaryOperatorKind WithOverflowChecksIfApplicable(this UnaryOperatorKind kind, bool enabled) { if (enabled) { // If it's dynamic and we're in a checked context then just mark it as checked, // regardless of whether it is +x -x !x ~x ++x --x x++ or x--. Let the lowering // pass sort out what to do with it. if (kind.IsDynamic()) { return kind | UnaryOperatorKind.Checked; } if (kind.IsIntegral()) { switch (kind.Operator()) { case UnaryOperatorKind.PrefixIncrement: case UnaryOperatorKind.PostfixIncrement: case UnaryOperatorKind.PrefixDecrement: case UnaryOperatorKind.PostfixDecrement: case UnaryOperatorKind.UnaryMinus: return kind | UnaryOperatorKind.Checked; } } return kind; } else { return kind & ~UnaryOperatorKind.Checked; } } public static UnaryOperatorKind OperandTypes(this UnaryOperatorKind kind) { return kind & UnaryOperatorKind.TypeMask; } public static bool IsDynamic(this UnaryOperatorKind kind) { return kind.OperandTypes() == UnaryOperatorKind.Dynamic; } public static bool IsIntegral(this UnaryOperatorKind kind) { switch (kind.OperandTypes()) { case UnaryOperatorKind.SByte: case UnaryOperatorKind.Byte: case UnaryOperatorKind.Short: case UnaryOperatorKind.UShort: case UnaryOperatorKind.Int: case UnaryOperatorKind.UInt: case UnaryOperatorKind.Long: case UnaryOperatorKind.ULong: case UnaryOperatorKind.NInt: case UnaryOperatorKind.NUInt: case UnaryOperatorKind.Char: case UnaryOperatorKind.Enum: case UnaryOperatorKind.Pointer: return true; } return false; } public static UnaryOperatorKind WithType(this UnaryOperatorKind kind, UnaryOperatorKind type) { Debug.Assert(kind == (kind & ~UnaryOperatorKind.TypeMask)); Debug.Assert(type == (type & UnaryOperatorKind.TypeMask)); return kind | type; } public static int OperatorIndex(this BinaryOperatorKind kind) { return ((int)kind.Operator() >> 8) - 16; } public static BinaryOperatorKind Operator(this BinaryOperatorKind kind) { return kind & BinaryOperatorKind.OpMask; } public static BinaryOperatorKind Unlifted(this BinaryOperatorKind kind) { return kind & ~BinaryOperatorKind.Lifted; } public static BinaryOperatorKind OperatorWithLogical(this BinaryOperatorKind kind) { return kind & (BinaryOperatorKind.OpMask | BinaryOperatorKind.Logical); } public static BinaryOperatorKind WithType(this BinaryOperatorKind kind, SpecialType type) { Debug.Assert(kind == (kind & ~BinaryOperatorKind.TypeMask)); switch (type) { case SpecialType.System_Int32: return kind | BinaryOperatorKind.Int; case SpecialType.System_UInt32: return kind | BinaryOperatorKind.UInt; case SpecialType.System_Int64: return kind | BinaryOperatorKind.Long; case SpecialType.System_UInt64: return kind | BinaryOperatorKind.ULong; default: throw ExceptionUtilities.UnexpectedValue(type); } } public static UnaryOperatorKind WithType(this UnaryOperatorKind kind, SpecialType type) { Debug.Assert(kind == (kind & ~UnaryOperatorKind.TypeMask)); switch (type) { case SpecialType.System_Int32: return kind | UnaryOperatorKind.Int; case SpecialType.System_UInt32: return kind | UnaryOperatorKind.UInt; case SpecialType.System_Int64: return kind | UnaryOperatorKind.Long; case SpecialType.System_UInt64: return kind | UnaryOperatorKind.ULong; default: throw ExceptionUtilities.UnexpectedValue(type); } } public static BinaryOperatorKind WithType(this BinaryOperatorKind kind, BinaryOperatorKind type) { Debug.Assert(kind == (kind & ~BinaryOperatorKind.TypeMask)); Debug.Assert(type == (type & BinaryOperatorKind.TypeMask)); return kind | type; } public static bool IsLifted(this BinaryOperatorKind kind) { return 0 != (kind & BinaryOperatorKind.Lifted); } public static bool IsDynamic(this BinaryOperatorKind kind) { return kind.OperandTypes() == BinaryOperatorKind.Dynamic; } public static bool IsComparison(this BinaryOperatorKind kind) { switch (kind.Operator()) { case BinaryOperatorKind.Equal: case BinaryOperatorKind.NotEqual: case BinaryOperatorKind.GreaterThan: case BinaryOperatorKind.GreaterThanOrEqual: case BinaryOperatorKind.LessThan: case BinaryOperatorKind.LessThanOrEqual: return true; } return false; } public static bool IsChecked(this BinaryOperatorKind kind) { return 0 != (kind & BinaryOperatorKind.Checked); } public static bool EmitsAsCheckedInstruction(this BinaryOperatorKind kind) { if (!kind.IsChecked()) { return false; } switch (kind.Operator()) { case BinaryOperatorKind.Addition: case BinaryOperatorKind.Subtraction: case BinaryOperatorKind.Multiplication: return true; } return false; } public static BinaryOperatorKind WithOverflowChecksIfApplicable(this BinaryOperatorKind kind, bool enabled) { if (enabled) { // If it's a dynamic binop then make it checked. Let the lowering // pass sort out what to do with it. if (kind.IsDynamic()) { return kind | BinaryOperatorKind.Checked; } if (kind.IsIntegral()) { switch (kind.Operator()) { case BinaryOperatorKind.Addition: case BinaryOperatorKind.Subtraction: case BinaryOperatorKind.Multiplication: case BinaryOperatorKind.Division: return kind | BinaryOperatorKind.Checked; } } return kind; } else { return kind & ~BinaryOperatorKind.Checked; } } public static bool IsEnum(this BinaryOperatorKind kind) { switch (kind.OperandTypes()) { case BinaryOperatorKind.Enum: case BinaryOperatorKind.EnumAndUnderlying: case BinaryOperatorKind.UnderlyingAndEnum: return true; } return false; } public static bool IsEnum(this UnaryOperatorKind kind) { return kind.OperandTypes() == UnaryOperatorKind.Enum; } public static bool IsIntegral(this BinaryOperatorKind kind) { switch (kind.OperandTypes()) { case BinaryOperatorKind.Int: case BinaryOperatorKind.UInt: case BinaryOperatorKind.Long: case BinaryOperatorKind.ULong: case BinaryOperatorKind.NInt: case BinaryOperatorKind.NUInt: case BinaryOperatorKind.Char: case BinaryOperatorKind.Enum: case BinaryOperatorKind.EnumAndUnderlying: case BinaryOperatorKind.UnderlyingAndEnum: case BinaryOperatorKind.Pointer: case BinaryOperatorKind.PointerAndInt: case BinaryOperatorKind.PointerAndUInt: case BinaryOperatorKind.PointerAndLong: case BinaryOperatorKind.PointerAndULong: case BinaryOperatorKind.IntAndPointer: case BinaryOperatorKind.UIntAndPointer: case BinaryOperatorKind.LongAndPointer: case BinaryOperatorKind.ULongAndPointer: return true; } return false; } public static bool IsLogical(this BinaryOperatorKind kind) { return 0 != (kind & BinaryOperatorKind.Logical); } public static BinaryOperatorKind OperandTypes(this BinaryOperatorKind kind) { return kind & BinaryOperatorKind.TypeMask; } public static bool IsUserDefined(this BinaryOperatorKind kind) { return (kind & BinaryOperatorKind.TypeMask) == BinaryOperatorKind.UserDefined; } public static bool IsShift(this BinaryOperatorKind kind) { BinaryOperatorKind type = kind.Operator(); return type == BinaryOperatorKind.LeftShift || type == BinaryOperatorKind.RightShift || type == BinaryOperatorKind.UnsignedRightShift; } public static ExpressionType ToExpressionType(this BinaryOperatorKind kind, bool isCompoundAssignment) { if (isCompoundAssignment) { switch (kind.Operator()) { case BinaryOperatorKind.Multiplication: return ExpressionType.MultiplyAssign; case BinaryOperatorKind.Addition: return ExpressionType.AddAssign; case BinaryOperatorKind.Subtraction: return ExpressionType.SubtractAssign; case BinaryOperatorKind.Division: return ExpressionType.DivideAssign; case BinaryOperatorKind.Remainder: return ExpressionType.ModuloAssign; case BinaryOperatorKind.LeftShift: return ExpressionType.LeftShiftAssign; case BinaryOperatorKind.RightShift: return ExpressionType.RightShiftAssign; case BinaryOperatorKind.And: return ExpressionType.AndAssign; case BinaryOperatorKind.Xor: return ExpressionType.ExclusiveOrAssign; case BinaryOperatorKind.Or: return ExpressionType.OrAssign; } } else { switch (kind.Operator()) { case BinaryOperatorKind.Multiplication: return ExpressionType.Multiply; case BinaryOperatorKind.Addition: return ExpressionType.Add; case BinaryOperatorKind.Subtraction: return ExpressionType.Subtract; case BinaryOperatorKind.Division: return ExpressionType.Divide; case BinaryOperatorKind.Remainder: return ExpressionType.Modulo; case BinaryOperatorKind.LeftShift: return ExpressionType.LeftShift; case BinaryOperatorKind.RightShift: return ExpressionType.RightShift; case BinaryOperatorKind.Equal: return ExpressionType.Equal; case BinaryOperatorKind.NotEqual: return ExpressionType.NotEqual; case BinaryOperatorKind.GreaterThan: return ExpressionType.GreaterThan; case BinaryOperatorKind.LessThan: return ExpressionType.LessThan; case BinaryOperatorKind.GreaterThanOrEqual: return ExpressionType.GreaterThanOrEqual; case BinaryOperatorKind.LessThanOrEqual: return ExpressionType.LessThanOrEqual; case BinaryOperatorKind.And: return ExpressionType.And; case BinaryOperatorKind.Xor: return ExpressionType.ExclusiveOr; case BinaryOperatorKind.Or: return ExpressionType.Or; } } throw ExceptionUtilities.UnexpectedValue(kind.Operator()); } public static ExpressionType ToExpressionType(this UnaryOperatorKind kind) { switch (kind.Operator()) { case UnaryOperatorKind.PrefixIncrement: case UnaryOperatorKind.PostfixIncrement: return ExpressionType.Increment; case UnaryOperatorKind.PostfixDecrement: case UnaryOperatorKind.PrefixDecrement: return ExpressionType.Decrement; case UnaryOperatorKind.UnaryPlus: return ExpressionType.UnaryPlus; case UnaryOperatorKind.UnaryMinus: return ExpressionType.Negate; case UnaryOperatorKind.LogicalNegation: return ExpressionType.Not; case UnaryOperatorKind.BitwiseComplement: return ExpressionType.OnesComplement; case UnaryOperatorKind.True: return ExpressionType.IsTrue; case UnaryOperatorKind.False: return ExpressionType.IsFalse; default: throw ExceptionUtilities.UnexpectedValue(kind.Operator()); } } #if DEBUG public static string Dump(this BinaryOperatorKind kind) { var b = new StringBuilder(); if ((kind & BinaryOperatorKind.Lifted) != 0) b.Append("Lifted"); if ((kind & BinaryOperatorKind.Logical) != 0) b.Append("Logical"); if ((kind & BinaryOperatorKind.Checked) != 0) b.Append("Checked"); var type = kind & BinaryOperatorKind.TypeMask; if (type != 0) b.Append(type.ToString()); var op = kind & BinaryOperatorKind.OpMask; if (op != 0) b.Append(op.ToString()); return b.ToString(); } public static string Dump(this UnaryOperatorKind kind) { var b = new StringBuilder(); if ((kind & UnaryOperatorKind.Lifted) != 0) b.Append("Lifted"); if ((kind & UnaryOperatorKind.Checked) != 0) b.Append("Checked"); var type = kind & UnaryOperatorKind.TypeMask; if (type != 0) b.Append(type.ToString()); var op = kind & UnaryOperatorKind.OpMask; if (op != 0) b.Append(op.ToString()); return b.ToString(); } #endif } }