/// <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); }
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); } }
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); }