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); } }