示例#1
0
            /// <summary>
            /// Return the boolean expression to be evaluated for the given test. Returns `null` if the test is trivially true.
            /// </summary>
            protected BoundExpression LowerTest(BoundDagTest test)
            {
                _factory.Syntax = test.Syntax;
                BoundExpression input = _tempAllocator.GetTemp(test.Input);

                switch (test)
                {
                case BoundDagNonNullTest d:
                    return(_localRewriter.MakeNullCheck(d.Syntax, input, input.Type.IsNullableType() ? BinaryOperatorKind.NullableNullNotEqual : BinaryOperatorKind.NotEqual));

                case BoundDagTypeTest d:
                    // Note that this tests for non-null as a side-effect. We depend on that to sometimes avoid the null check.
                    return(_factory.Is(input, d.Type));

                case BoundDagNullTest d:
                    return(_localRewriter.MakeNullCheck(d.Syntax, input, input.Type.IsNullableType() ? BinaryOperatorKind.NullableNullEqual : BinaryOperatorKind.Equal));

                case BoundDagValueTest d:
                    Debug.Assert(!input.Type.IsNullableType());
                    return(MakeEqual(_localRewriter.MakeLiteral(d.Syntax, d.Value, input.Type), input));

                default:
                    throw ExceptionUtilities.UnexpectedValue(test);
                }
            }
示例#2
0
            /// <summary>
            /// Lower a test followed by an evaluation into a side-effect followed by a test. This permits us to optimize
            /// a type test followed by a cast into an `as` expression followed by a null check. Returns true if the optimization
            /// applies and the results are placed into <paramref name="sideEffect"/> and <paramref name="test"/>. The caller
            /// should place the side-effect before the test in the generated code.
            /// </summary>
            /// <param name="evaluation"></param>
            /// <param name="test"></param>
            /// <param name="sideEffect"></param>
            /// <param name="testExpression"></param>
            /// <returns>true if the optimization is applied</returns>
            protected bool TryLowerTypeTestAndCast(
                BoundDagTest test,
                BoundDagEvaluation evaluation,
                out BoundExpression sideEffect,
                out BoundExpression testExpression)
            {
                if (test is BoundDagTypeTest typeDecision &&
                    evaluation is BoundDagTypeEvaluation typeEvaluation &&
                    typeDecision.Type.IsReferenceType &&
                    typeEvaluation.Type.Equals(typeDecision.Type, TypeCompareKind.AllIgnoreOptions) &&
                    typeEvaluation.Input == typeDecision.Input
                    )
                {
                    BoundExpression input  = _tempAllocator.GetTemp(test.Input);
                    BoundExpression output = _tempAllocator.GetTemp(new BoundDagTemp(evaluation.Syntax, typeEvaluation.Type, evaluation, index: 0));
                    sideEffect     = _factory.AssignmentExpression(output, _factory.As(input, typeEvaluation.Type));
                    testExpression = _factory.ObjectNotEqual(output, _factory.Null(output.Type));
                    return(true);
                }

                sideEffect = testExpression = null;
                return(false);
            }
            /// <summary>
            /// Translate the single test into _sideEffectBuilder and _conjunctBuilder.
            /// </summary>
            private void LowerOneTest(BoundDagTest test)
            {
                _factory.Syntax = test.Syntax;
                switch (test)
                {
                case BoundDagEvaluation eval:
                {
                    var sideEffect = LowerEvaluation(eval);
                    _sideEffectBuilder.Add(sideEffect);
                    return;
                }

                case var _:
                {
                    var testExpression = LowerTest(test);
                    if (testExpression != null)
                    {
                        AddConjunct(testExpression);
                    }

                    return;
                }
                }
            }