Exemplo n.º 1
0
        /// <summary>
        /// Emits expression and converts it to required type.
        /// </summary>
        public void EmitConvert(BoundExpression expr, TypeSymbol to, ConversionKind conversion = ConversionKind.Implicit, bool notNull = false)
        {
            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)
                {
                    // TODO: ConversionKind.Strict ?
                    EmitConvert(EmitLoadConstant(expr.ConstantValue.Value, to, notNull), 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.Conversions.ClassifyConversion(place.Type, to, conversion);
                    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, conversion);
        }
Exemplo n.º 2
0
        public void EmitClassName(CodeGenerator cg)
        {
            if (ObjectTypeInfoSemantic)
            {
                // Template: (<expr> as object).GetPhpTypeInfo().Name
                cg.EmitAsObject(_typeExpression.Emit(cg), out var isnull);

                if (isnull)
                {
                    // ERR
                }

                cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Dynamic.GetPhpTypeInfo_Object); // PhpTypeInfo
                cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.GetName_PhpTypeInfo.Getter)
                .Expect(SpecialType.System_String);
            }
            else
            {
                // (string)
                cg.EmitConvert(_typeExpression, cg.CoreTypes.String);
            }
        }
Exemplo n.º 3
0
        public void EmitConvert(BoundExpression expr, TypeSymbol to)
        {
            // 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.TypeOpt != 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)
                {
                    if (place.TypeOpt == CoreTypes.PhpNumber)
                    {
                        if (to.SpecialType == SpecialType.System_Int64)
                        {
                            // <place>.ToLong()
                            place.EmitLoadAddress(_il);
                            EmitCall(ILOpCode.Call, CoreMethods.PhpNumber.ToLong);
                            return;
                        }
                        if (to.SpecialType == SpecialType.System_Double)
                        {
                            // <place>.ToDouble()
                            place.EmitLoadAddress(_il);
                            EmitCall(ILOpCode.Call, CoreMethods.PhpNumber.ToDouble);
                            return;
                        }
                        if (to.SpecialType == SpecialType.System_Boolean)
                        {
                            // <place>.ToBoolean()
                            place.EmitLoadAddress(_il);
                            EmitCall(ILOpCode.Call, CoreMethods.PhpNumber.ToBoolean);
                            return;
                        }
                        if (to.SpecialType == SpecialType.System_String)
                        {
                            // <place>.ToString(<ctx>)
                            place.EmitLoadAddress(_il);
                            EmitLoadContext();
                            EmitCall(ILOpCode.Call, CoreMethods.PhpNumber.ToString_Context);
                            return;
                        }
                        if (to == CoreTypes.PhpValue)
                        {
                            // TODO
                        }

                        // TODO: Object, Array
                    }
                    else if (place.TypeOpt == CoreTypes.PhpValue)
                    {
                        if (to.SpecialType == SpecialType.System_Int64)
                        {
                            // <place>.ToLong()
                            place.EmitLoadAddress(_il);
                            EmitCall(ILOpCode.Call, CoreMethods.PhpValue.ToLong);
                            return;
                        }
                        if (to.SpecialType == SpecialType.System_Double)
                        {
                            // <place>.ToDouble()
                            place.EmitLoadAddress(_il);
                            EmitCall(ILOpCode.Call, CoreMethods.PhpValue.ToDouble);
                            return;
                        }
                        if (to.SpecialType == SpecialType.System_Boolean)
                        {
                            // <place>.ToBoolean()
                            place.EmitLoadAddress(_il);
                            EmitCall(ILOpCode.Call, CoreMethods.PhpValue.ToBoolean);
                            return;
                        }
                        if (to.SpecialType == SpecialType.System_String)
                        {
                            // <place>.ToString(<ctx>)
                            place.EmitLoadAddress(_il);
                            EmitLoadContext();
                            EmitCall(ILOpCode.Call, CoreMethods.PhpValue.ToString_Context);
                            return;
                        }
                        if (to.SpecialType == SpecialType.System_Object)
                        {
                            // <place>.ToClass()
                            place.EmitLoadAddress(_il);
                            EmitCall(ILOpCode.Call, CoreMethods.PhpValue.ToClass);
                            return;
                        }
                        //if (to == CoreTypes.PhpArray)
                        //{
                        //    // <place>.AsArray()
                        //    place.EmitLoadAddress(_il);
                        //    EmitCall(ILOpCode.Call, CoreMethods.PhpValue.ToArray);
                        //    return;
                        //}
                    }
                    else if (place.TypeOpt == CoreTypes.Long)
                    {
                        if (to.SpecialType == SpecialType.System_String)
                        {
                            // <place>.ToString()
                            place.EmitLoadAddress(_il);
                            EmitCall(ILOpCode.Call, CoreMethods.Operators.Long_ToString);
                            return;
                        }
                    }
                }
            }

            //
            EmitConvert(expr.Emit(this), expr.TypeRefMask, to);
        }