Beispiel #1
0
        private BoundExpression VisitObjectCreationExpressionInternal(BoundObjectCreationExpression node)
        {
            if (node.ConstantValue != null)
            {
                // typically a decimal constant.
                return(Constant(node));
            }

            if ((object)node.Constructor == null ||
                (node.Arguments.Length == 0 && !node.Type.IsStructType()) ||
                node.Constructor.IsDefaultValueTypeConstructor())
            {
                return(ExprFactory("New", _bound.Typeof(node.Type)));
            }

            var ctor = _bound.ConstructorInfo(node.Constructor);
            var args = _bound.Convert(_IEnumerableType.Construct(ExpressionType), Expressions(node.Arguments));

            if (node.Type.IsAnonymousType && node.Arguments.Length != 0)
            {
                var anonType       = (NamedTypeSymbol)node.Type;
                var membersBuilder = ArrayBuilder <BoundExpression> .GetInstance();

                for (int i = 0; i < node.Arguments.Length; i++)
                {
                    membersBuilder.Add(_bound.MethodInfo(AnonymousTypeManager.GetAnonymousTypeProperty(anonType, i).GetMethod));
                }

                return(ExprFactory("New", ctor, args, _bound.ArrayOrEmpty(MemberInfoType, membersBuilder.ToImmutableAndFree())));
            }
            else
            {
                return(ExprFactory("New", ctor, args));
            }
        }
Beispiel #2
0
        public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node)
        {
            Debug.Assert(node.InitializerExpressionOpt == null);
            BoundSpillSequenceBuilder builder = null;
            var arguments = this.VisitExpressionList(ref builder, node.Arguments, node.ArgumentRefKindsOpt);

            return(UpdateExpression(builder, node.Update(node.Constructor, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.Expanded, node.ArgsToParamsOpt, node.ConstantValueOpt, node.InitializerExpressionOpt, node.BinderOpt, node.Type)));
        }
Beispiel #3
0
        public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node)
        {
            Debug.Assert(node != null);

            // Rewrite the arguments.
            // NOTE: We may need additional argument rewriting such as generating a params array,
            //       re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
            // NOTE: This is done later by MakeArguments, for now we just lower each argument.
            var rewrittenArguments = VisitList(node.Arguments);

            // We have already lowered each argument, but we may need some additional rewriting for the arguments,
            // such as generating a params array, re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
            ImmutableArray <LocalSymbol> temps;
            ImmutableArray <RefKind>     argumentRefKindsOpt = node.ArgumentRefKindsOpt;

            rewrittenArguments = MakeArguments(
                node.Syntax,
                rewrittenArguments,
                node.Constructor,
                node.Constructor,
                node.Expanded,
                node.ArgsToParamsOpt,
                ref argumentRefKindsOpt,
                out temps);

            BoundExpression rewrittenObjectCreation;

            rewrittenObjectCreation = node.UpdateArgumentsAndInitializer(rewrittenArguments, argumentRefKindsOpt, newInitializerExpression: null, changeTypeOpt: node.Type);

            // replace "new S()" with a default struct ctor with "default(S)"
            if (node.Constructor.IsDefaultValueTypeConstructor())
            {
                rewrittenObjectCreation = new BoundDefaultExpression(rewrittenObjectCreation.Syntax, rewrittenObjectCreation.Type);
            }

            if (!temps.IsDefaultOrEmpty)
            {
                rewrittenObjectCreation = new BoundSequence(
                    node.Syntax,
                    temps,
                    ImmutableArray <BoundExpression> .Empty,
                    rewrittenObjectCreation,
                    node.Type);
            }

            if (node.Type.IsInterfaceType())
            {
                rewrittenObjectCreation = MakeConversionNode(rewrittenObjectCreation, node.Type, false, false);
            }

            if (node.InitializerExpressionOpt == null || node.InitializerExpressionOpt.HasErrors)
            {
                return(rewrittenObjectCreation);
            }

            return(MakeObjectCreationWithInitializer(node.Syntax, rewrittenObjectCreation, node.InitializerExpressionOpt, node.Type));
        }
                public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node)
                {
                    // perhaps we are passing a variable by ref and mutating it that way
                    if (!node.ArgumentRefKindsOpt.IsDefault)
                    {
                        _mightAssignSomething = true;
                    }
                    else
                    {
                        base.VisitObjectCreationExpression(node);
                    }

                    return(null);
                }
Beispiel #5
0
        private BoundExpression GetLiftedUnaryOperatorConsequence(UnaryOperatorKind kind, SyntaxNode syntax, MethodSymbol method, TypeSymbol type, BoundExpression nonNullOperand)
        {
            MethodSymbol ctor = UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor);

            // OP(temp.GetValueOrDefault())
            BoundExpression unliftedOp = MakeUnaryOperator(
                oldNode: null,
                kind: kind.Unlifted(),
                syntax: syntax,
                method: method,
                loweredOperand: nonNullOperand,
                type: type.GetNullableUnderlyingType());

            // new R?(OP(temp.GetValueOrDefault()))
            BoundExpression consequence = new BoundObjectCreationExpression(
                syntax,
                ctor,
                null,
                unliftedOp);

            return(consequence);
        }
Beispiel #6
0
        private BoundExpression MakeBuiltInIncrementOperator(BoundIncrementOperator node, BoundExpression rewrittenValueToIncrement)
        {
            BoundExpression result;
            // If we have a built-in increment or decrement then things get a bit trickier. Suppose for example we have
            // a user-defined conversion from X to short and from short to X, but no user-defined increment operator on
            // X.  The increment portion of "++x" is then: (X)(short)((int)(short)x + 1). That is, first x must be
            // converted to short via an implicit user- defined conversion, then to int via an implicit numeric
            // conversion, then the addition is performed in integers. The resulting integer is converted back to short,
            // and then the short is converted to X.

            // This is the input and output type of the unary increment operator we're going to call.
            // That is, "short" in the example above.
            TypeSymbol unaryOperandType = GetUnaryOperatorType(node);

            // This is the kind of binary operator that we're going to realize the unary operator
            // as. That is, "int + int --> int" in the example above.
            BinaryOperatorKind binaryOperatorKind = GetCorrespondingBinaryOperator(node);

            binaryOperatorKind |= IsIncrement(node) ? BinaryOperatorKind.Addition : BinaryOperatorKind.Subtraction;

            // The "1" in the example above.
            ConstantValue constantOne = GetConstantOneForBinOp(binaryOperatorKind);

            Debug.Assert(constantOne != null);
            Debug.Assert(constantOne.SpecialType != SpecialType.None);
            Debug.Assert(binaryOperatorKind.OperandTypes() != 0);

            // The input/output type of the binary operand. "int" in the example.
            TypeSymbol binaryOperandType = _compilation.GetSpecialType(constantOne.SpecialType);

            // 1
            BoundExpression boundOne = MakeLiteral(
                syntax: node.Syntax,
                constantValue: constantOne,
                type: binaryOperandType);

            if (binaryOperatorKind.IsLifted())
            {
                binaryOperandType = _compilation.GetSpecialType(SpecialType.core_Option_T).Construct(binaryOperandType);
                MethodSymbol ctor = UnsafeGetNullableMethod(node.Syntax, binaryOperandType, SpecialMember.System_Nullable_T__ctor);
                boundOne = new BoundObjectCreationExpression(node.Syntax, ctor, null, boundOne);
            }

            // Now we construct the other operand to the binary addition. We start with just plain "x".
            BoundExpression binaryOperand = rewrittenValueToIncrement;

            bool @checked = node.OperatorKind.IsChecked();

            // If we need to make a conversion from the original operand type to the operand type of the
            // underlying increment operation, do it now.
            if (!node.OperandConversion.IsIdentity)
            {
                // (short)x
                binaryOperand = MakeConversionNode(
                    syntax: node.Syntax,
                    rewrittenOperand: binaryOperand,
                    conversion: node.OperandConversion,
                    rewrittenType: unaryOperandType,
                    @checked: @checked);
            }

            // Early-out for pointer increment - we don't need to convert the operands to a common type.
            if (node.OperatorKind.OperandTypes() == UnaryOperatorKind.Pointer)
            {
                Debug.Assert(binaryOperatorKind.OperandTypes() == BinaryOperatorKind.PointerAndInt32);
                Debug.Assert(binaryOperand.Type.IsPointerType());
                Debug.Assert(boundOne.Type.SpecialType == SpecialType.System_Int32);
                return(MakeBinaryOperator(node.Syntax, binaryOperatorKind, binaryOperand, boundOne, binaryOperand.Type, method: null));
            }

            // If we need to make a conversion from the unary operator type to the binary operator type,
            // do it now.

            // (int)(short)x
            binaryOperand = MakeConversionNode(binaryOperand, binaryOperandType, @checked);

            // Perform the addition.

            // (int)(short)x + 1
            BoundExpression binOp;

            binOp = MakeBinaryOperator(node.Syntax, binaryOperatorKind, binaryOperand, boundOne, binaryOperandType, method: null);

            // Generate the conversion back to the type of the unary operator.

            // (short)((int)(short)x + 1)
            result = MakeConversionNode(binOp, unaryOperandType, @checked);
            return(result);
        }
Beispiel #7
0
        private BoundExpression MakeUserDefinedIncrementOperator(BoundIncrementOperator node, BoundExpression rewrittenValueToIncrement)
        {
            Debug.Assert((object)node.MethodOpt != null);
            Debug.Assert(node.MethodOpt.ParameterCount == 1);

            bool isLifted = node.OperatorKind.IsLifted();
            bool @checked = node.OperatorKind.IsChecked();

            BoundExpression rewrittenArgument = rewrittenValueToIncrement;
            SyntaxNode      syntax            = node.Syntax;

            TypeSymbol type = node.MethodOpt.ParameterTypes[0].TypeSymbol;

            if (isLifted)
            {
                type = _compilation.GetSpecialType(SpecialType.core_Option_T).Construct(type);
                Debug.Assert(TypeSymbol.Equals(node.MethodOpt.ParameterTypes[0].TypeSymbol, node.MethodOpt.ReturnType.TypeSymbol, TypeCompareKind.ConsiderEverything2));
            }

            if (!node.OperandConversion.IsIdentity)
            {
                rewrittenArgument = MakeConversionNode(
                    syntax: syntax,
                    rewrittenOperand: rewrittenValueToIncrement,
                    conversion: node.OperandConversion,
                    rewrittenType: type,
                    @checked: @checked);
            }

            if (!isLifted)
            {
                return(BoundCall.Synthesized(syntax, null, node.MethodOpt, rewrittenArgument));
            }

            // S? temp = operand;
            // S? r = temp.HasValue ?
            //        new S?(op_Increment(temp.GetValueOrDefault())) :
            //        default(S?);

            // Unlike the other unary operators, we do not attempt to optimize nullable user-defined
            // increment or decrement. The operand is a variable (or property), and so we do not know if
            // it is always null/never null.

            BoundAssignmentOperator tempAssignment;
            BoundLocal boundTemp = _factory.StoreToTemp(rewrittenArgument, out tempAssignment);

            MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T_GetValueOrDefault);
            MethodSymbol ctor = UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor);

            // temp.HasValue
            BoundExpression condition = MakeNullableHasValue(node.Syntax, boundTemp);

            // temp.GetValueOrDefault()
            BoundExpression call_GetValueOrDefault = BoundCall.Synthesized(syntax, boundTemp, getValueOrDefault);

            // op_Increment(temp.GetValueOrDefault())
            BoundExpression userDefinedCall = BoundCall.Synthesized(syntax, null, node.MethodOpt, call_GetValueOrDefault);

            // new S?(op_Increment(temp.GetValueOrDefault()))
            BoundExpression consequence = new BoundObjectCreationExpression(syntax, ctor, null, userDefinedCall);

            // default(S?)
            BoundExpression alternative = new BoundDefaultExpression(syntax, null, type);

            // temp.HasValue ?
            //          new S?(op_Increment(temp.GetValueOrDefault())) :
            //          default(S?);
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: type,
                isRef: false);

            // temp = operand;
            // temp.HasValue ?
            //          new S?(op_Increment(temp.GetValueOrDefault())) :
            //          default(S?);
            return(new BoundSequence(
                       syntax: syntax,
                       locals: ImmutableArray.Create <LocalSymbol>(boundTemp.LocalSymbol),
                       sideEffects: ImmutableArray.Create <BoundExpression>(tempAssignment),
                       value: conditionalExpression,
                       type: type));
        }
Beispiel #8
0
 public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node)
 {
     VisitCall(node.Constructor, null, node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt, node.Expanded, node);
     return(base.VisitObjectCreationExpression(node));
 }
        private BoundExpression MakeTupleCreationExpression(SyntaxNode syntax, NamedTypeSymbol type, ImmutableArray <BoundExpression> rewrittenArguments)
        {
            NamedTypeSymbol underlyingTupleType = type.TupleUnderlyingType ?? type;

            Debug.Assert(underlyingTupleType.IsTupleCompatible());

            ArrayBuilder <NamedTypeSymbol> underlyingTupleTypeChain = ArrayBuilder <NamedTypeSymbol> .GetInstance();

            TupleTypeSymbol.GetUnderlyingTypeChain(underlyingTupleType, underlyingTupleTypeChain);

            try
            {
                // make a creation expression for the smallest type
                NamedTypeSymbol smallestType = underlyingTupleTypeChain.Pop();
                ImmutableArray <BoundExpression> smallestCtorArguments = ImmutableArray.Create(rewrittenArguments,
                                                                                               underlyingTupleTypeChain.Count * (TupleTypeSymbol.RestPosition - 1),
                                                                                               smallestType.Arity);
                var smallestCtor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(smallestType.OriginalDefinition,
                                                                                          TupleTypeSymbol.GetTupleCtor(smallestType.Arity),
                                                                                          _diagnostics,
                                                                                          syntax);
                if ((object)smallestCtor == null)
                {
                    return(_factory.BadExpression(type));
                }

                MethodSymbol smallestConstructor = smallestCtor.AsMember(smallestType);
                BoundObjectCreationExpression currentCreation = new BoundObjectCreationExpression(syntax, smallestConstructor, null, smallestCtorArguments);

                if (underlyingTupleTypeChain.Count > 0)
                {
                    NamedTypeSymbol tuple8Type = underlyingTupleTypeChain.Peek();
                    var             tuple8Ctor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(tuple8Type.OriginalDefinition,
                                                                                                        TupleTypeSymbol.GetTupleCtor(TupleTypeSymbol.RestPosition),
                                                                                                        _diagnostics,
                                                                                                        syntax);
                    if ((object)tuple8Ctor == null)
                    {
                        return(_factory.BadExpression(type));
                    }

                    // make successively larger creation expressions containing the previous one
                    do
                    {
                        ImmutableArray <BoundExpression> ctorArguments = ImmutableArray.Create(rewrittenArguments,
                                                                                               (underlyingTupleTypeChain.Count - 1) * (TupleTypeSymbol.RestPosition - 1),
                                                                                               TupleTypeSymbol.RestPosition - 1)
                                                                         .Add(currentCreation);

                        MethodSymbol constructor = tuple8Ctor.AsMember(underlyingTupleTypeChain.Pop());
                        currentCreation = new BoundObjectCreationExpression(syntax, constructor, null, ctorArguments);
                    }while (underlyingTupleTypeChain.Count > 0);
                }

                currentCreation = currentCreation.Update(
                    currentCreation.Constructor,
                    currentCreation.Arguments,
                    currentCreation.ArgumentNamesOpt,
                    currentCreation.ArgumentRefKindsOpt,
                    currentCreation.Expanded,
                    currentCreation.ArgsToParamsOpt,
                    currentCreation.ConstantValue,
                    currentCreation.InitializerExpressionOpt,
                    currentCreation.BinderOpt,
                    type);

                return(currentCreation);
            }
            finally
            {
                underlyingTupleTypeChain.Free();
            }
        }
Beispiel #10
0
 private BoundExpression VisitObjectCreationExpression(BoundObjectCreationExpression node)
 {
     return(VisitObjectCreationContinued(VisitObjectCreationExpressionInternal(node), node.InitializerExpressionOpt));
 }
Beispiel #11
0
        public override BoundNode VisitFromEndIndexExpression(BoundFromEndIndexExpression node)
        {
            Debug.Assert(node.MethodOpt != null);

            //NamedTypeSymbol booleanType = _compilation.GetSpecialType(SpecialType.System_Boolean);
            //BoundExpression fromEnd = MakeLiteral(node.Syntax, ConstantValue.Create(true), booleanType);

            BoundExpression operand = VisitExpression(node.Operand);

            if (NullableNeverHasValue(operand))
            {
                operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType());
            }

            operand = NullableAlwaysHasValue(operand) ?? operand;

            if (!node.Type.IsNullableType())
            {
                var notOperand = new BoundUnaryOperator(node.Syntax, UnaryOperatorKind.IntBitwiseComplement, operand, null, null, LookupResultKind.Viable, ImmutableArray <MethodSymbol> .Empty, operand.Type);
                return(new BoundObjectCreationExpression(node.Syntax, node.MethodOpt, binderOpt: null, notOperand));
            }

            throw new NotImplementedException("TODO: rewriter of BoundFromEndIndexExpression for ?int is not implemented");

            ArrayBuilder <BoundExpression> sideeffects = ArrayBuilder <BoundExpression> .GetInstance();

            ArrayBuilder <LocalSymbol> locals = ArrayBuilder <LocalSymbol> .GetInstance();

            // operand.HasValue
            operand = CaptureExpressionInTempIfNeeded(operand, sideeffects, locals);
            BoundExpression condition = MakeOptimizedHasValue(operand.Syntax, operand);


            // new Index(operand, fromEnd: true)
            BoundExpression boundOperandGetValueOrDefault = MakeOptimizedGetValueOrDefault(operand.Syntax, operand);
            BoundExpression indexCreation = new BoundObjectCreationExpression(node.Syntax, node.MethodOpt, binderOpt: null, boundOperandGetValueOrDefault);

            if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor))
            {
                return(BadExpression(node.Syntax, node.Type, operand));
            }

            // new Nullable(new Index(operand, fromEnd: true))
            BoundExpression consequence = new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, indexCreation);

            // default
            BoundExpression alternative = new BoundDefaultExpression(node.Syntax, constantValueOpt: null, node.Type);

            // operand.HasValue ? new Nullable(new Index(operand, fromEnd: true)) : default
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: node.Syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: node.Type,
                isRef: false);

            return(new BoundSequence(
                       syntax: node.Syntax,
                       locals: locals.ToImmutableAndFree(),
                       sideEffects: sideeffects.ToImmutableAndFree(),
                       value: conditionalExpression,
                       type: node.Type));
        }
Beispiel #12
0
        private BoundExpression LiftRangeExpression(BoundRangeExpression node, ImmutableArray <BoundExpression> operands)
        {
            Debug.Assert(node.Type.IsNullableType());
            Debug.Assert(operands.Any(operand => operand.Type.IsNullableType()));
            Debug.Assert(operands.Length == 1 || operands.Length == 2);

            ArrayBuilder <BoundExpression> sideeffects = ArrayBuilder <BoundExpression> .GetInstance();

            ArrayBuilder <LocalSymbol> locals = ArrayBuilder <LocalSymbol> .GetInstance();

            ArrayBuilder <BoundExpression> arguments = ArrayBuilder <BoundExpression> .GetInstance();

            // left.HasValue && right.HasValue
            BoundExpression condition = null;

            foreach (var operand in operands)
            {
                BoundExpression tempOperand = CaptureExpressionInTempIfNeeded(operand, sideeffects, locals);

                if (tempOperand.Type.IsNullableType())
                {
                    BoundExpression operandHasValue = MakeOptimizedHasValue(tempOperand.Syntax, tempOperand);

                    if (condition is null)
                    {
                        condition = operandHasValue;
                    }
                    else
                    {
                        TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);
                        condition = MakeBinaryOperator(node.Syntax, BinaryOperatorKind.BoolAnd, condition, operandHasValue, boolType, method: null);
                    }

                    arguments.Add(MakeOptimizedGetValueOrDefault(tempOperand.Syntax, tempOperand));
                }
                else
                {
                    arguments.Add(tempOperand);
                }
            }

            Debug.Assert(condition != null);

            // method(left.GetValueOrDefault(), right.GetValueOrDefault())
            BoundExpression rangeCall = MakeCall(
                node.Syntax,
                rewrittenReceiver: null,
                node.MethodOpt,
                arguments.ToImmutableArray(),
                node.MethodOpt.ReturnType.TypeSymbol);

            if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor))
            {
                return(BadExpression(node.Syntax, node.Type, node));
            }

            // new Nullable(method(left.GetValueOrDefault(), right.GetValueOrDefault()))
            BoundExpression consequence = new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeCall);

            // default
            BoundExpression alternative = new BoundDefaultExpression(node.Syntax, constantValueOpt: null, node.Type);

            // left.HasValue && right.HasValue ? new Nullable(method(left.GetValueOrDefault(), right.GetValueOrDefault())) : default
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: node.Syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: node.Type,
                isRef: false);

            return(new BoundSequence(
                       syntax: node.Syntax,
                       locals: locals.ToImmutableAndFree(),
                       sideEffects: sideeffects.ToImmutableAndFree(),
                       value: conditionalExpression,
                       type: node.Type));
        }