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); } } }
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; }
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); }
/// <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(); } }
/// <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(); } }
/// <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(); }
/// <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(); } }
internal void EmitCastClass(TypeSymbol from, TypeSymbol to) { if (!from.IsEqualToOrDerivedFrom(to)) { EmitCastClass(to); } }