Ejemplo n.º 1
0
            private void LowerDecisionTree(DecisionTree.ByType byType)
            {
                var inputConstant = byType.Expression.ConstantValue;

                if (inputConstant != null)
                {
                    if (inputConstant.IsNull)
                    {
                        // input is the constant null
                        LowerDecisionTree(byType.Expression, byType.WhenNull);
                        if (byType.WhenNull?.MatchIsComplete != true)
                        {
                            LowerDecisionTree(byType.Expression, byType.Default);
                        }
                    }
                    else
                    {
                        // input is a non-null constant
                        foreach (var kvp in byType.TypeAndDecision)
                        {
                            LowerDecisionTree(byType.Expression, kvp.Value);
                            if (kvp.Value.MatchIsComplete)
                            {
                                return;
                            }
                        }

                        LowerDecisionTree(byType.Expression, byType.Default);
                    }
                }
                else
                {
                    var defaultLabel = _factory.GenerateLabel("byTypeDefault");

                    // input is not a constant
                    if (byType.Type.CanContainNull())
                    {
                        // first test for null
                        var             notNullLabel    = _factory.GenerateLabel("notNull");
                        var             inputExpression = byType.Expression;
                        var             objectType      = _factory.SpecialType(SpecialType.System_Object);
                        var             nullValue       = _factory.Null(objectType);
                        BoundExpression notNull         = byType.Type.IsNullableType()
                            ? _localRewriter.RewriteNullableNullEquality(_factory.Syntax, BinaryOperatorKind.NullableNullNotEqual, byType.Expression, nullValue, _factory.SpecialType(SpecialType.System_Boolean))
                            : _factory.ObjectNotEqual(nullValue, _factory.Convert(objectType, byType.Expression));
                        _loweredDecisionTree.Add(_factory.ConditionalGoto(notNull, notNullLabel, true));
                        LowerDecisionTree(byType.Expression, byType.WhenNull);
                        if (byType.WhenNull?.MatchIsComplete != true)
                        {
                            _loweredDecisionTree.Add(_factory.Goto(defaultLabel));
                        }

                        _loweredDecisionTree.Add(_factory.Label(notNullLabel));
                    }
                    else
                    {
                        Debug.Assert(byType.WhenNull == null);
                    }

                    foreach (var td in byType.TypeAndDecision)
                    {
                        // then test for each type, sequentially
                        var type        = td.Key;
                        var decision    = td.Value;
                        var failLabel   = _factory.GenerateLabel("failedDecision");
                        var testAndCopy = TypeTestAndCopyToTemp(byType.Expression, decision.Expression);
                        _loweredDecisionTree.Add(_factory.ConditionalGoto(testAndCopy, failLabel, false));
                        LowerDecisionTree(decision.Expression, decision);
                        _loweredDecisionTree.Add(_factory.Label(failLabel));
                    }

                    // finally, the default for when no type matches
                    _loweredDecisionTree.Add(_factory.Label(defaultLabel));
                    LowerDecisionTree(byType.Expression, byType.Default);
                }
            }