Exemplo n.º 1
0
        private void EmitConvertToIPhpCallable(TypeSymbol from, TypeRefMask fromHint)
        {
            // dereference
            if (from == CoreTypes.PhpAlias)
            {
                from = Emit_PhpAlias_GetValue();
            }

            // (IPhpCallable)
            if (!from.IsEqualToOrDerivedFrom(CoreTypes.IPhpCallable))
            {
                if (from.SpecialType == SpecialType.System_String)
                {
                    EmitLoadToken(this.CallerType, null);
                    EmitCall(ILOpCode.Call, CoreMethods.Operators.AsCallable_String_RuntimeTypeHandle);
                }
                else if (
                    from.SpecialType == SpecialType.System_Int64 ||
                    from.SpecialType == SpecialType.System_Boolean ||
                    from.SpecialType == SpecialType.System_Double)
                {
                    throw new ArgumentException($"{from.Name} cannot be converted to a class of type IPhpCallable!");  // TODO: ErrCode
                }
                else
                {
                    EmitConvertToPhpValue(from, fromHint);
                    EmitLoadToken(this.CallerType, null);
                    EmitCall(ILOpCode.Call, CoreMethods.Operators.AsCallable_PhpValue_RuntimeTypeHandle);
                }
            }
        }
Exemplo n.º 2
0
        static bool IsAccessible(MethodSymbol method, TypeSymbol classCtx)
        {
            if (method.DeclaredAccessibility == Accessibility.Private)
            {
                return (method.ContainingType == classCtx);
            }
            else if (method.DeclaredAccessibility == Accessibility.Protected)
            {
                return classCtx != null && (
                    method.ContainingType.IsEqualToOrDerivedFrom(classCtx) ||
                    classCtx.IsEqualToOrDerivedFrom(method.ContainingType));
            }

            return true;
        }
Exemplo n.º 3
0
        private static bool IsCatching(BoundCatchBlock catchBlock, TypeSymbol exception)
        {
            // If it is catching all exceptions
            if ((object)catchBlock.ExceptionTypeOpt == null)
            {
                return(true);
            }

            HashSet <DiagnosticInfo> useSiteDiagnostics = null;

            if (exception.IsEqualToOrDerivedFrom(catchBlock.ExceptionTypeOpt, TypeCompareKind.ConsiderEverything, ref useSiteDiagnostics))
            {
                return(catchBlock.ExceptionFilterOpt == null);
            }

            return(false);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Emits conversion to a class object.
        /// </summary>
        /// <param name="from">Type of value on top of the evaluation stack.</param>
        /// <param name="fromHint">Hint in case of multitype value.</param>
        /// <param name="to">Target type.</param>
        private void EmitConvertToClass(TypeSymbol from, TypeRefMask fromHint, TypeSymbol to)
        {
            Contract.ThrowIfNull(from);
            Contract.ThrowIfNull(to);
            Debug.Assert(to.IsReferenceType);   // TODO: structs other than primitive types
            Debug.Assert(to != CoreTypes.PhpAlias);

            // dereference
            if (from == CoreTypes.PhpAlias)
            {
                Emit_PhpAlias_GetValue();
                from = CoreTypes.PhpValue;
            }

            if (from == to)
            {
                return;
            }

            Debug.Assert(to != CoreTypes.PhpArray && to != CoreTypes.PhpString && to != CoreTypes.PhpAlias);

            if (to == CoreTypes.IPhpCallable)
            {
                // (IPhpCallable)
                if (!from.IsEqualToOrDerivedFrom(CoreTypes.IPhpCallable))
                {
                    if (from.SpecialType == SpecialType.System_String)
                    {
                        EmitCall(ILOpCode.Call, CoreMethods.Operators.AsCallable_String);
                    }
                    else if (
                        from.SpecialType == SpecialType.System_Int64 ||
                        from.SpecialType == SpecialType.System_Boolean ||
                        from.SpecialType == SpecialType.System_Double)
                    {
                        throw new ArgumentException($"{from.Name} cannot be converted to a class of type {to.Name}!");  // TODO: ErrCode
                    }
                    else
                    {
                        EmitConvertToPhpValue(from, fromHint);
                        EmitCall(ILOpCode.Call, CoreMethods.Operators.AsCallable_PhpValue);
                    }
                }
                return;
            }

            if (to.IsArray())
            {
                var arrt = (ArrayTypeSymbol)to;
                if (arrt.IsSZArray)
                {
                    if (arrt.ElementType.SpecialType == SpecialType.System_Byte)
                    {
                        // byte[]

                        // Template: (PhpString).ToBytes(Context)
                        EmitConvertToPhpString(from, fromHint); // PhpString
                        this.EmitLoadContext();                 // Context
                        EmitCall(ILOpCode.Call, CoreMethods.PhpString.ToBytes_Context)
                        .Expect(to);                            // ToBytes()
                        return;
                    }
                }

                throw new NotImplementedException($"Conversion from {from.Name} to {to.Name} is not implemented.");
            }

            switch (from.SpecialType)
            {
            case SpecialType.System_Void:
            case SpecialType.System_Int32:
            case SpecialType.System_Int64:
            case SpecialType.System_Boolean:
            case SpecialType.System_Double:
            case SpecialType.System_String:
                if (to == CoreTypes.Object)
                {
                    from = EmitConvertToPhpValue(from, fromHint);
                    goto default;
                }
                else
                {
                    throw new ArgumentException($"{from.Name} cannot be converted to a class of type {to.Name}!");      // TODO: ErrCode
                }

            default:
                if (from == CoreTypes.PhpValue)
                {
                    if (!fromHint.IsRef && IsClassOnly(fromHint))
                    {
                        // <value>.Object
                        EmitPhpValueAddr();
                        from = EmitCall(ILOpCode.Call, CoreMethods.PhpValue.Object.Getter)
                               .Expect(SpecialType.System_Object);
                    }
                    else
                    {
                        // Convert.ToClass( value )
                        from = EmitCall(ILOpCode.Call, CoreMethods.Operators.ToClass_PhpValue)
                               .Expect(SpecialType.System_Object);
                    }

                    // (T)
                    EmitCastClass(from, to);
                    return;
                }
                if (from == CoreTypes.PhpNumber)
                {
                    // Object
                    EmitPhpNumberAddr();
                    EmitCall(ILOpCode.Call, CoreMethods.PhpNumber.ToClass)
                    .Expect(SpecialType.System_Object);

                    // (T)
                    EmitCastClass(to);
                    return;
                }
                else if (from.IsOfType(CoreTypes.PhpArray))
                {
                    // (T)PhpArray.ToClass();
                    EmitCastClass(EmitCall(ILOpCode.Call, CoreMethods.PhpArray.ToClass), to);
                    return;
                }
                else if (from.IsOfType(CoreTypes.IPhpArray))
                {
                    // (T)Convert.ToClass(IPhpArray)
                    EmitCastClass(EmitCall(ILOpCode.Call, CoreMethods.Operators.ToClass_IPhpArray), to);
                    return;
                }
                else if (from.IsReferenceType)
                {
                    Debug.Assert(from != CoreTypes.PhpAlias);
                    // (T)obj   // let .NET deal with eventual cast error for now
                    EmitCastClass(from, to);
                    return;
                }
                throw new NotImplementedException();
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Emits conversion to a class object.
        /// </summary>
        /// <param name="from">Type of value on top of the evaluation stack.</param>
        /// <param name="fromHint">Hint in case of multitype value.</param>
        /// <param name="to">Target type.</param>
        private void EmitConvertToClass(TypeSymbol from, TypeRefMask fromHint, TypeSymbol to)
        {
            Contract.ThrowIfNull(from);
            Contract.ThrowIfNull(to);
            Debug.Assert(to.IsReferenceType);   // TODO: structs other than primitive types
            Debug.Assert(to != CoreTypes.PhpAlias);

            // dereference
            if (from == CoreTypes.PhpAlias)
            {
                Emit_PhpAlias_GetValue();
                from = CoreTypes.PhpValue;
            }

            if (from == to)
            {
                return;
            }

            Debug.Assert(to != CoreTypes.PhpArray && to != CoreTypes.PhpString && to != CoreTypes.PhpAlias);

            if (to == CoreTypes.IPhpCallable)
            {
                // (IPhpCallable)
                if (!from.IsEqualToOrDerivedFrom(CoreTypes.IPhpCallable))
                {
                    if (from.SpecialType == SpecialType.System_String)
                    {
                        EmitCall(ILOpCode.Call, CoreMethods.Operators.AsCallable_String);
                    }
                    else if (
                        from.SpecialType == SpecialType.System_Int64 ||
                        from.SpecialType == SpecialType.System_Boolean ||
                        from.SpecialType == SpecialType.System_Double)
                    {
                        throw new ArgumentException($"{from.Name} cannot be converted to a class of type {to.Name}!");  // TODO: ErrCode
                    }
                    else
                    {
                        EmitConvertToPhpValue(from, fromHint);
                        EmitCall(ILOpCode.Call, CoreMethods.Operators.AsCallable_PhpValue);
                    }
                }
                return;
            }

            switch (from.SpecialType)
            {
            case SpecialType.System_Void:
            case SpecialType.System_Int32:
            case SpecialType.System_Int64:
            case SpecialType.System_Boolean:
            case SpecialType.System_Double:
            case SpecialType.System_String:
                if (to == CoreTypes.Object)
                {
                    from = EmitConvertToPhpValue(from, fromHint);
                    goto default;
                }
                else
                {
                    throw new ArgumentException($"{from.Name} cannot be converted to a class of type {to.Name}!");      // TODO: ErrCode
                }

            default:
                if (from == CoreTypes.PhpValue)
                {
                    // Convert.ToClass( value )
                    EmitCall(ILOpCode.Call, CoreMethods.Operators.ToClass_PhpValue)
                    .Expect(SpecialType.System_Object);

                    // (T)
                    EmitCastClass(to);
                    return;
                }
                if (from == CoreTypes.PhpNumber)
                {
                    // Object
                    EmitPhpNumberAddr();
                    EmitCall(ILOpCode.Call, CoreMethods.PhpNumber.ToClass)
                    .Expect(SpecialType.System_Object);

                    // (T)
                    EmitCastClass(to);
                    return;
                }
                else if (from == CoreTypes.PhpArray)
                {
                    // (T)PhpArray.ToClass();
                    EmitCastClass(EmitCall(ILOpCode.Call, CoreMethods.PhpArray.ToClass), to);
                    return;
                }
                else if (from.IsReferenceType)
                {
                    Debug.Assert(from != CoreTypes.PhpAlias);
                    // (T)obj   // let .NET deal with eventual cast error for now
                    EmitCastClass(from, to);
                    return;
                }
                throw new NotImplementedException();
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Emits conversion from one CLR type to another using PHP conventions.
        /// </summary>
        /// <param name="from">Type of value on top of evaluation stack.</param>
        /// <param name="fromHint">Type hint in case of a multityple type choices (like PhpValue or PhpNumber or PhpAlias).</param>
        /// <param name="to">Target CLR type.</param>
        public void EmitConvert(TypeSymbol from, TypeRefMask fromHint, TypeSymbol to)
        {
            Contract.ThrowIfNull(from);
            Contract.ThrowIfNull(to);

            // conversion is not needed:
            if (from.IsEqualToOrDerivedFrom(to) ||
                (from.SpecialType == to.SpecialType && from.SpecialType != SpecialType.None))
            {
                return;
            }

            //
            from = EmitSpecialize(from, fromHint);

            // specialized conversions:
            switch (to.SpecialType)
            {
            case SpecialType.System_Void:
                EmitPop(from);
                return;

            case SpecialType.System_Boolean:
                EmitConvertToBool(from, fromHint);
                return;

            case SpecialType.System_Int32:
                EmitConvertToInt(from, fromHint);
                return;

            case SpecialType.System_Int64:
                EmitConvertToLong(from, fromHint);
                return;

            case SpecialType.System_Double:
                EmitConvertToDouble(from, fromHint);
                return;

            case SpecialType.System_String:
                EmitConvertToString(from, fromHint);
                return;

            case SpecialType.System_Object:
                EmitConvertToClass(from, fromHint, to);
                return;

            default:
                if (to == CoreTypes.PhpValue)
                {
                    EmitConvertToPhpValue(from, fromHint);
                }
                else if (to == CoreTypes.PhpAlias)
                {
                    EmitConvertToPhpValue(from, fromHint);
                    Emit_PhpValue_MakeAlias();
                }
                else if (to == CoreTypes.PhpNumber)
                {
                    EmitConvertToPhpNumber(from, fromHint);
                    return;
                }
                else if (to == CoreTypes.PhpArray || to == CoreTypes.IPhpEnumerable)        // TODO: merge into IPhpArray
                {
                    EmitConvertToPhpArray(from, fromHint);
                    return;
                }
                else if (to == CoreTypes.PhpString)
                {
                    throw new NotImplementedException($"{to}");
                }
                else if (to.IsReferenceType)
                {
                    EmitConvertToClass(from, fromHint, to);
                    return;
                }
                else if (to.IsEnumType())
                {
                    EmitConvertToEnum(from, (NamedTypeSymbol)to);
                    return;
                }
                else
                {
                    throw new NotImplementedException($"{to}");
                }
                return;
            }

            //
            throw new NotImplementedException();
        }
Exemplo n.º 7
0
        /// <summary>
        /// Emits conversion to a class object.
        /// </summary>
        /// <param name="from">Type of value on top of the evaluation stack.</param>
        /// <param name="fromHint">Hint in case of multitype value.</param>
        /// <param name="to">Target type.</param>
        private void EmitConvertToClass(TypeSymbol from, TypeRefMask fromHint, TypeSymbol to)
        {
            Contract.ThrowIfNull(from);
            Contract.ThrowIfNull(to);
            Debug.Assert(to.IsReferenceType);   // TODO: structs other than primitive types
            Debug.Assert(to != CoreTypes.PhpAlias);

            // dereference
            if (from == CoreTypes.PhpAlias)
            {
                Emit_PhpAlias_GetValue();
                from = CoreTypes.PhpValue;
            }

            if (from == to)
                return;

            Debug.Assert(to != CoreTypes.PhpArray && to != CoreTypes.PhpString && to != CoreTypes.PhpAlias);

            if (to == CoreTypes.IPhpCallable)
            {
                // (IPhpCallable)
                if (!from.IsEqualToOrDerivedFrom(CoreTypes.IPhpCallable))
                {
                    if (from.SpecialType == SpecialType.System_String)
                    {
                        EmitCall(ILOpCode.Call, CoreMethods.Operators.AsCallable_String);
                    }
                    else if (
                        from.SpecialType == SpecialType.System_Int64 ||
                        from.SpecialType == SpecialType.System_Boolean ||
                        from.SpecialType == SpecialType.System_Double)
                    {
                        throw new ArgumentException($"{from.Name} cannot be converted to a class of type {to.Name}!");  // TODO: ErrCode
                    }
                    else
                    {
                        EmitConvertToPhpValue(from, fromHint);
                        EmitCall(ILOpCode.Call, CoreMethods.Operators.AsCallable_PhpValue);
                    }
                }
                return;
            }

            switch (from.SpecialType)
            {
                case SpecialType.System_Void:
                case SpecialType.System_Int32:
                case SpecialType.System_Int64:
                case SpecialType.System_Boolean:
                case SpecialType.System_Double:
                case SpecialType.System_String:
                    if (to == CoreTypes.Object)
                    {
                        from = EmitConvertToPhpValue(from, fromHint);
                        goto default;
                    }
                    else
                    {
                        throw new ArgumentException($"{from.Name} cannot be converted to a class of type {to.Name}!");  // TODO: ErrCode
                    }
                default:
                    if (from == CoreTypes.PhpValue)
                    {
                        // Convert.ToClass( value )
                        EmitCall(ILOpCode.Call, CoreMethods.Operators.ToClass_PhpValue)
                            .Expect(SpecialType.System_Object);

                        // (T)
                        EmitCastClass(to);
                        return;
                    }
                    if (from == CoreTypes.PhpNumber)
                    {
                        // Object
                        EmitPhpNumberAddr();
                        EmitCall(ILOpCode.Call, CoreMethods.PhpNumber.ToClass)
                            .Expect(SpecialType.System_Object);

                        // (T)
                        EmitCastClass(to);
                        return;
                    }
                    else if (from.IsOfType(CoreTypes.PhpArray))
                    {
                        // (T)PhpArray.ToClass();
                        EmitCastClass(EmitCall(ILOpCode.Call, CoreMethods.PhpArray.ToClass), to);
                        return;
                    }
                    else if (from.IsOfType(CoreTypes.IPhpArray))
                    {
                        // (T)Convert.ToClass(IPhpArray)
                        EmitCastClass(EmitCall(ILOpCode.Call, CoreMethods.Operators.ToClass_IPhpArray), to);
                        return;
                    }
                    else if (from.IsReferenceType)
                    {
                        Debug.Assert(from != CoreTypes.PhpAlias);
                        // (T)obj   // let .NET deal with eventual cast error for now
                        EmitCastClass(from, to);
                        return;
                    }
                    throw new NotImplementedException();
            }
        }
Exemplo n.º 8
0
 internal void EmitCastClass(TypeSymbol from, TypeSymbol to)
 {
     if (!from.IsEqualToOrDerivedFrom(to))
     {
         EmitCastClass(to);
     }
 }