Beispiel #1
0
        /// <summary>
        /// Emits expression and converts it to required type.
        /// </summary>
        public void EmitConvert(BoundExpression expr, TypeSymbol to)
        {
            Debug.Assert(expr != null);
            Debug.Assert(to != null);

            // pop effectively
            if (to.IsVoid())
            {
                expr.Access = BoundAccess.None;

                if (!expr.IsConstant())
                {
                    // POP LOAD <expr>
                    EmitPop(Emit(expr));
                }

                return;
            }

            // bind target expression type
            expr.Access = expr.Access.WithRead(to);

            if (!expr.Access.IsReadRef)
            {
                // constants
                if (expr.ConstantValue.HasValue && to != null)
                {
                    EmitConvert(EmitLoadConstant(expr.ConstantValue.Value, to), 0, to);
                    return;
                }

                // loads value from place most effectively without runtime type checking
                var place = PlaceOrNull(expr);
                if (place != null && place.Type != to)
                {
                    var type = TryEmitVariableSpecialize(place, expr.TypeRefMask);
                    if (type != null)
                    {
                        EmitConvert(type, 0, to);
                        return;
                    }
                }

                // avoiding of load of full value
                if (place != null && place.HasAddress && place.Type != null && place.Type.IsValueType)
                {
                    var conv = DeclaringCompilation.ClassifyCommonConversion(place.Type, to);
                    if (conv.Exists && conv.IsUserDefined && !conv.MethodSymbol.IsStatic)
                    {
                        // (ADDR expr).Method()
                        this.EmitImplicitConversion(EmitCall(ILOpCode.Call, (MethodSymbol)conv.MethodSymbol, expr, ImmutableArray <BoundArgument> .Empty), to, @checked: true);
                        return;
                    }
                }
            }

            //
            EmitConvert(expr.Emit(this), expr.TypeRefMask, to);
        }
Beispiel #2
0
        public TypeSymbol EmitConvertToPhpValue(TypeSymbol from, TypeRefMask fromHint)
        {
            // Nullable<T> -> HasValue ? T : NULL
            if (from.IsNullableType())
            {
                from = EmitNullableCastToNull(from, false); // (HasValue ? Value : NULL)
            }

            var conv = DeclaringCompilation.ClassifyCommonConversion(from, CoreTypes.PhpValue.Symbol);

            if (conv.IsImplicit)
            {
                this.EmitConversion(conv, from, CoreTypes.PhpValue.Symbol);
            }
            else
            {
                // some conversion we did not implement as operator yet:

                if (from.IsReferenceType)
                {
                    EmitCall(ILOpCode.Call, CoreMethods.PhpValue.FromClass_Object).Expect(CoreTypes.PhpValue);
                }
                else if (from.SpecialType == SpecialType.System_Void)
                {
                    // PhpValue.Void
                    Emit_PhpValue_Void();
                }
                else
                {
                    // box & wrap to PhpValue.Object
                    // Template: PhpValue.FromStruct<T>( STACK )
                    EmitCall(ILOpCode.Call, CoreMethods.PhpValue.FromStruct_T.Symbol.Construct(from)).Expect(CoreTypes.PhpValue);
                }
            }
            //
            return(CoreTypes.PhpValue);
        }
        public TypeSymbol EmitConvertToPhpValue(TypeSymbol from, TypeRefMask fromHint)
        {
            // Nullable<T> -> HasValue ? T : NULL
            if (from.IsNullableType())
            {
                from = EmitNullableCastToNull(from, false); // (HasValue ? Value : NULL)
            }

            var conv = DeclaringCompilation.ClassifyCommonConversion(from, CoreTypes.PhpValue.Symbol);

            if (conv.IsImplicit)
            {
                this.EmitConversion(conv, from, CoreTypes.PhpValue.Symbol);
            }
            else
            {
                // some conversion we did not implement as operator yet:

                if (from.IsReferenceType)
                {
                    EmitCall(ILOpCode.Call, CoreMethods.PhpValue.FromClass_Object)
                    .Expect(CoreTypes.PhpValue);
                }
                else if (from.SpecialType == SpecialType.System_Void)
                {
                    // PhpValue.Void
                    Emit_PhpValue_Void();
                }
                else
                {
                    throw ExceptionUtilities.NotImplementedException(this, $"{from.Name} -> PhpValue");
                }
            }
            //
            return(CoreTypes.PhpValue);
        }