//mostly used for logical operators and ducky mode //other cases of bool context are handled by PMB bool EmitToBoolIfNeeded(Expression expression, ref bool notContext) { bool inNotContext = notContext; notContext = false; //use a builtin conversion operator just for the logical operator trueness test IType type = GetExpressionType(expression); if (TypeSystemServices.ObjectType == type || TypeSystemServices.DuckType == type) { _il.EmitCall(OpCodes.Call, RuntimeServices_ToBool_Object, null); return true; } else if (TypeSystemServices.IsNullable(type)) { _il.Emit(OpCodes.Ldloca, _currentLocal); Type sType = GetSystemType(TypeSystemServices.GetNullableUnderlyingType(type)); _il.EmitCall(OpCodes.Call, GetNullableHasValue(sType), null); LocalBuilder hasValue = StoreTempLocal(TypeSystemServices.BoolType); _il.Emit(OpCodes.Pop); //pop nullable address (ldloca) _il.Emit(OpCodes.Ldloc, hasValue); return true; } else if (TypeSystemServices.StringType == type) { _il.EmitCall(OpCodes.Call, String_IsNullOrEmpty, null); if (!inNotContext) EmitIntNot(); //reverse result (true for not empty) else notContext = true; return true; } else if (TypeSystemServices.IsIntegerNumber(type)) { if (TypeSystemServices.LongType == type || TypeSystemServices.ULongType == type) _il.Emit(OpCodes.Conv_I4); return true; } else if (TypeSystemServices.SingleType == type) { EmitDefaultValue(TypeSystemServices.SingleType); _il.Emit(OpCodes.Ceq); if (!inNotContext) EmitIntNot(); else notContext = true; return true; } else if (TypeSystemServices.DoubleType == type) { EmitDefaultValue(TypeSystemServices.DoubleType); _il.Emit(OpCodes.Ceq); if (!inNotContext) EmitIntNot(); else notContext = true; return true; } else if (TypeSystemServices.DecimalType == type) { _il.EmitCall(OpCodes.Call, RuntimeServices_ToBool_Decimal, null); return true; } else if (!type.IsValueType) { if (null == expression.GetAncestor<BinaryExpression>() && null != expression.GetAncestor<IfStatement>()) return true; //use br(true|false) directly (most common case) _il.Emit(OpCodes.Ldnull); if (!inNotContext) { _il.Emit(OpCodes.Cgt_Un); } else { _il.Emit(OpCodes.Ceq); notContext = true; } return true; } return false; }