private static void ClipDecimal(Expression expression, ConversionBlock block, IType expectedType) { var toFloat = Helpers.IsFloatType(expectedType, block.Emitter.Resolver); if (toFloat || (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression))) { block.Write(JS.Types.SYSTEM_DECIMAL + ".toFloat"); block.Write("("); block.AfterOutput += ")"; } else { block.Write(JS.Types.SYSTEM_DECIMAL + ".toInt("); block.AfterOutput = ", " + BridgeTypes.ToJsName(expectedType, block.Emitter) + ")"; } }
private static void ClipDecimal(Expression expression, ConversionBlock block, IType expectedType) { var toFloat = Helpers.IsFloatType(expectedType, block.Emitter.Resolver); if (toFloat || (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression))) { block.Write("Bridge.Decimal.toFloat"); if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression)) { block.Write("("); block.AfterOutput += ")"; } } else { block.Write("Bridge.Decimal.toInt("); block.AfterOutput = ", " + BridgeTypes.ToJsName(expectedType, block.Emitter) + ")"; } }
private static void NarrowingNumericOrEnumerationConversion(ConversionBlock block, Expression expression, IType targetType, bool fromFloatingPoint, bool isChecked, bool isNullable, bool isExplicit = true) { if (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression)) { return; } if (isChecked) { block.Write(JS.Types.BRIDGE_INT + ".check("); if (fromFloatingPoint) { block.Write(JS.Types.BRIDGE_INT + ".trunc"); block.WriteOpenParentheses(); } //expression.AcceptVisitor(block.Emitter); if (fromFloatingPoint) { block.AfterOutput += ")"; } block.AfterOutput += ", "; block.AfterOutput += BridgeTypes.ToJsName(targetType, block.Emitter); block.AfterOutput += ")"; } else { if (isNullable || fromFloatingPoint) { targetType = NullableType.IsNullable(targetType) ? NullableType.GetUnderlyingType(targetType) : targetType; string action = null; if (targetType.IsKnownType(KnownTypeCode.Char)) { action = "clipu16"; } else if (targetType.IsKnownType(KnownTypeCode.SByte)) { action = "clip8"; } else if (targetType.IsKnownType(KnownTypeCode.Byte)) { action = "clipu8"; } else if (targetType.IsKnownType(KnownTypeCode.Int16)) { action = "clip16"; } else if (targetType.IsKnownType(KnownTypeCode.UInt16)) { action = "clipu16"; } else if (targetType.IsKnownType(KnownTypeCode.Int32)) { action = "clip32"; } else if (targetType.IsKnownType(KnownTypeCode.UInt32)) { action = "clipu32"; } else if (targetType.IsKnownType(KnownTypeCode.Int64)) { action = "clip64"; } else if (targetType.IsKnownType(KnownTypeCode.UInt64)) { action = "clipu64"; } else { throw new ArgumentException("Can not narrow to " + targetType, "targetType"); } block.Write(JS.Types.BRIDGE_INT + "."); block.Write(action); if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression)) { block.Write("("); block.AfterOutput += ")"; } } else { var skipOuterWrap = (expression.Parent is VariableInitializer) || (expression.Parent is AssignmentExpression) || targetType.IsKnownType(KnownTypeCode.Int64) || targetType.IsKnownType(KnownTypeCode.UInt64) || targetType.IsKnownType(KnownTypeCode.Int16) || targetType.IsKnownType(KnownTypeCode.SByte); bool skipInnerWrap = false; var rr = block.Emitter.Resolver.ResolveNode(expression is CastExpression ? ((CastExpression)expression).Expression : expression, block.Emitter); var memberTargetrr = rr as MemberResolveResult; bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (rr is ThisResolveResult || rr is LocalResolveResult || rr is ConstantResolveResult || isField) { skipInnerWrap = true; } if (!skipOuterWrap) { block.WriteOpenParentheses(); } if (targetType.IsKnownType(KnownTypeCode.Char)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 65535"; } else if (targetType.IsKnownType(KnownTypeCode.SByte)) { block.Write(JS.Types.BRIDGE_INT + ".sxb("); if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 255)"; } else if (targetType.IsKnownType(KnownTypeCode.Byte)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 255"; } else if (targetType.IsKnownType(KnownTypeCode.Int16)) { block.Write(JS.Types.BRIDGE_INT + ".sxs("); if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 65535)"; } else if (targetType.IsKnownType(KnownTypeCode.UInt16)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 65535"; } else if (targetType.IsKnownType(KnownTypeCode.Int32)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " | 0"; } else if (targetType.IsKnownType(KnownTypeCode.UInt32)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " >>> 0"; } else if (targetType.IsKnownType(KnownTypeCode.Int64)) { block.Write(JS.Types.BRIDGE_INT + ".clip64("); block.AfterOutput += ")"; } else if (targetType.IsKnownType(KnownTypeCode.UInt64)) { block.Write(JS.Types.BRIDGE_INT + ".clipu64("); block.AfterOutput += ")"; } else { throw new ArgumentException("Can not narrow to " + targetType, "targetType"); } if (!skipOuterWrap) { block.AfterOutput += ")"; } } } }
private static void CheckLong(ConversionBlock block, Expression expression, IType expectedType, IType fromType, bool isChecked) { if (!NeedsNarrowingNumericConversion(fromType, expectedType)) { return; } if (isChecked) { expectedType = NullableType.IsNullable(expectedType) ? NullableType.GetUnderlyingType(expectedType) : expectedType; block.Write(JS.Types.System.Int64.CHECK); block.WriteOpenParentheses(); block.AfterOutput += ", "; block.AfterOutput += BridgeTypes.ToJsName(expectedType, block.Emitter); block.AfterOutput += ")"; } else { string action = null; expectedType = NullableType.IsNullable(expectedType) ? NullableType.GetUnderlyingType(expectedType) : expectedType; if (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression)) { action = "toNumber"; } else if (expectedType.IsKnownType(KnownTypeCode.Char)) { action = "clipu16"; } else if (expectedType.IsKnownType(KnownTypeCode.SByte)) { action = "clip8"; } else if (expectedType.IsKnownType(KnownTypeCode.Byte)) { action = "clipu8"; } else if (expectedType.IsKnownType(KnownTypeCode.Int16)) { action = "clip16"; } else if (expectedType.IsKnownType(KnownTypeCode.UInt16)) { action = "clipu16"; } else if (expectedType.IsKnownType(KnownTypeCode.Int32)) { action = "clip32"; } else if (expectedType.IsKnownType(KnownTypeCode.UInt32)) { action = "clipu32"; } else if (expectedType.IsKnownType(KnownTypeCode.Int64)) { action = "clip64"; } else if (expectedType.IsKnownType(KnownTypeCode.UInt64)) { action = "clipu64"; } else { throw new ArgumentException("Can not narrow to " + expectedType, "expectedType"); } block.Write(JS.Types.System.Int64.NAME + "."); block.Write(action); if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression)) { block.Write("("); block.AfterOutput += ")"; } } }
private static void CheckNumericConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion) { var fromType = rr.Type; var toType = expectedType; if (fromType.Kind == TypeKind.Enum) { fromType = fromType.GetDefinition().EnumUnderlyingType; } if (toType.Kind == TypeKind.Enum) { toType = toType.GetDefinition().EnumUnderlyingType; } bool isArrayIndex = false; if (Helpers.Is64Type(toType, block.Emitter.Resolver) && expression.Parent is IndexerExpression && ((IndexerExpression)expression.Parent).Arguments.Contains(expression)) { var memberResolveResult = rr as MemberResolveResult; var isIgnore = true; var isAccessorsIndexer = false; IProperty member = null; IndexerAccessor current = null; if (memberResolveResult == null) { memberResolveResult = block.Emitter.Resolver.ResolveNode(expression.Parent, block.Emitter) as MemberResolveResult; } if (memberResolveResult != null) { var resolvedMember = memberResolveResult.Member; isIgnore = block.Emitter.Validator.IsExternalType(resolvedMember.DeclaringTypeDefinition); isAccessorsIndexer = block.Emitter.Validator.IsAccessorsIndexer(resolvedMember); var property = resolvedMember as IProperty; if (property != null) { member = property; current = IndexerBlock.GetIndexerAccessor(block.Emitter, member, block.Emitter.IsAssignment); } } if (!(current != null && current.InlineAttr != null) && !(!(isIgnore || (current != null && current.IgnoreAccessor)) || isAccessorsIndexer)) { block.Write(JS.Types.System.Int64.TONUMBER); block.Write("("); isArrayIndex = true; } } if ((conversion.IsNumericConversion || conversion.IsEnumerationConversion) && conversion.IsExplicit) { if (!(expression.Parent is ArrayInitializerExpression) && Helpers.Is64Type(fromType, block.Emitter.Resolver) && Helpers.IsFloatType(toType, block.Emitter.Resolver) && !Helpers.IsDecimalType(toType, block.Emitter.Resolver)) { var be = expression.Parent as BinaryOperatorExpression; if (be == null || be.Operator != BinaryOperatorType.Divide || be.Left != expression) { block.Write(JS.Types.System.Int64.TONUMBER); if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression)) { block.Write("("); block.AfterOutput += ")"; } } } else if (Helpers.IsDecimalType(toType, block.Emitter.Resolver) && !Helpers.IsDecimalType(fromType, block.Emitter.Resolver)) { block.Write(JS.Types.SYSTEM_DECIMAL + "("); block.AfterOutput += ", null, " + BridgeTypes.ToJsName(fromType, block.Emitter) + ")"; } else if (Helpers.IsDecimalType(fromType, block.Emitter.Resolver)) { ClipDecimal(expression, block, toType); } else if (Helpers.Is64Type(fromType, block.Emitter.Resolver)) { CheckLong(block, expression, toType, fromType, IsInCheckedContext(block.Emitter, expression)); } else if (Helpers.IsFloatType(fromType, block.Emitter.Resolver) && Helpers.IsIntegerType(toType, block.Emitter.Resolver)) { FloatToInt(block, expression, fromType, toType, IsInCheckedContext(block.Emitter, expression)); } else if (NeedsNarrowingNumericConversion(fromType, toType)) { if (IsInCheckedContext(block.Emitter, expression)) { CheckInteger(block, expression, toType); } else { ClipInteger(block, expression, toType, true); } } } else if (conversion.IsNumericConversion && conversion.IsImplicit && !(expression.Parent is ArrayInitializerExpression) && Helpers.Is64Type(fromType, block.Emitter.Resolver) && Helpers.IsFloatType(toType, block.Emitter.Resolver) && !Helpers.IsDecimalType(toType, block.Emitter.Resolver)) { var be = expression.Parent as BinaryOperatorExpression; if (be == null || be.Operator != BinaryOperatorType.Divide || be.Left != expression) { block.Write(JS.Types.System.Int64.TONUMBER); if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression)) { block.Write("("); block.AfterOutput += ")"; } } } else if (((!Helpers.Is64Type(toType, block.Emitter.Resolver) && Helpers.IsIntegerType(toType, block.Emitter.Resolver)) || (rr is OperatorResolveResult && !Helpers.Is64Type(fromType, block.Emitter.Resolver) && Helpers.IsIntegerType(fromType, block.Emitter.Resolver))) && (expression is BinaryOperatorExpression || expression is UnaryOperatorExpression || expression.Parent is AssignmentExpression) && IsInCheckedContext(block.Emitter, expression)) { var needCheck = false; var be = expression as BinaryOperatorExpression; bool isBitwiseOperator = be != null && (be.Operator == BinaryOperatorType.ShiftLeft || be.Operator == BinaryOperatorType.ShiftRight || be.Operator == BinaryOperatorType.BitwiseAnd || be.Operator == BinaryOperatorType.BitwiseOr || be.Operator == BinaryOperatorType.ExclusiveOr); if ((Helpers.IsKnownType(KnownTypeCode.Int32, toType, block.Emitter.Resolver) && isBitwiseOperator) || (Helpers.IsKnownType(KnownTypeCode.UInt32, toType, block.Emitter.Resolver) && be != null && be.Operator == BinaryOperatorType.ShiftRight)) { // Don't need to check even in checked context and don't need to clip } else if (be != null && (be.Operator == BinaryOperatorType.Add || be.Operator == BinaryOperatorType.Divide || be.Operator == BinaryOperatorType.Multiply || isBitwiseOperator || be.Operator == BinaryOperatorType.Subtract)) { if (isBitwiseOperator) { ClipInteger(block, expression, toType, false); } else { needCheck = true; } } else { var ue = expression as UnaryOperatorExpression; if (ue != null && (ue.Operator == UnaryOperatorType.Minus || ue.Operator == UnaryOperatorType.Increment || ue.Operator == UnaryOperatorType.Decrement || ue.Operator == UnaryOperatorType.PostIncrement || ue.Operator == UnaryOperatorType.PostDecrement)) { needCheck = true; } else { var ae = expression.Parent as AssignmentExpression; isBitwiseOperator = ae != null && (ae.Operator == AssignmentOperatorType.ShiftRight || ae.Operator == AssignmentOperatorType.ShiftLeft || ae.Operator == AssignmentOperatorType.BitwiseAnd || ae.Operator == AssignmentOperatorType.BitwiseOr || ae.Operator == AssignmentOperatorType.ExclusiveOr); if ((isBitwiseOperator && Helpers.IsKnownType(KnownTypeCode.Int32, toType, block.Emitter.Resolver)) || (ae != null && ae.Operator == AssignmentOperatorType.ShiftRight && Helpers.IsKnownType(KnownTypeCode.UInt32, toType, block.Emitter.Resolver))) { // Don't need to check even in checked context and don't need to clip } else if (ae != null && (isBitwiseOperator || ae.Operator == AssignmentOperatorType.Add || ae.Operator == AssignmentOperatorType.Divide || ae.Operator == AssignmentOperatorType.Multiply || ae.Operator == AssignmentOperatorType.Subtract)) { if (isBitwiseOperator) { ClipInteger(block, expression, toType, false); } else { needCheck = true; } } } } if (!Helpers.IsIntegerType(toType, block.Emitter.Resolver)) { if (rr is OperatorResolveResult) { toType = fromType; } } if (needCheck) { CheckInteger(block, expression, toType); } } else if (((!Helpers.Is64Type(toType, block.Emitter.Resolver) && Helpers.IsIntegerType(toType, block.Emitter.Resolver)) || (rr is OperatorResolveResult && !Helpers.Is64Type(fromType, block.Emitter.Resolver) && Helpers.IsIntegerType(fromType, block.Emitter.Resolver))) && (expression is BinaryOperatorExpression || expression is UnaryOperatorExpression || expression.Parent is AssignmentExpression) && IsInUncheckedContext(block.Emitter, expression)) { if (ConversionBlock.IsLongConversion(block, expression, rr, toType, conversion) || rr is ConstantResolveResult) { return; } if (!Helpers.IsIntegerType(toType, block.Emitter.Resolver)) { if (rr is OperatorResolveResult) { toType = fromType; } } var needCheck = false; var be = expression as BinaryOperatorExpression; bool isBitwiseOperator = be != null && (be.Operator == BinaryOperatorType.ShiftLeft || be.Operator == BinaryOperatorType.ShiftRight || be.Operator == BinaryOperatorType.BitwiseAnd || be.Operator == BinaryOperatorType.BitwiseOr || be.Operator == BinaryOperatorType.ExclusiveOr); if ((Helpers.IsKnownType(KnownTypeCode.Int32, toType, block.Emitter.Resolver) && isBitwiseOperator) || (Helpers.IsKnownType(KnownTypeCode.UInt32, toType, block.Emitter.Resolver) && be != null && be.Operator == BinaryOperatorType.ShiftRight)) { // Don't need to check even in checked context and don't need to clip } else if (be != null && !(be.Left is PrimitiveExpression && be.Right is PrimitiveExpression) && (be.Operator == BinaryOperatorType.Add || be.Operator == BinaryOperatorType.Divide || be.Operator == BinaryOperatorType.Multiply || isBitwiseOperator || be.Operator == BinaryOperatorType.Subtract)) { needCheck = true; } else { var ue = expression as UnaryOperatorExpression; if (ue != null && !(ue.Expression is PrimitiveExpression) && (ue.Operator == UnaryOperatorType.Minus || ue.Operator == UnaryOperatorType.Increment || ue.Operator == UnaryOperatorType.Decrement || ue.Operator == UnaryOperatorType.PostIncrement || ue.Operator == UnaryOperatorType.PostDecrement)) { needCheck = true; } else { var ae = expression.Parent as AssignmentExpression; isBitwiseOperator = ae != null && (ae.Operator == AssignmentOperatorType.ShiftRight || ae.Operator == AssignmentOperatorType.ShiftLeft || ae.Operator == AssignmentOperatorType.BitwiseAnd || ae.Operator == AssignmentOperatorType.BitwiseOr || ae.Operator == AssignmentOperatorType.ExclusiveOr); if ((isBitwiseOperator && Helpers.IsKnownType(KnownTypeCode.Int32, toType, block.Emitter.Resolver)) || (ae != null && ae.Operator == AssignmentOperatorType.ShiftRight && Helpers.IsKnownType(KnownTypeCode.UInt32, toType, block.Emitter.Resolver))) { // Don't need to check even in checked context and don't need to clip } else if (ae != null && (isBitwiseOperator || ae.Operator == AssignmentOperatorType.Add || ae.Operator == AssignmentOperatorType.Divide || ae.Operator == AssignmentOperatorType.Multiply || ae.Operator == AssignmentOperatorType.Subtract)) { needCheck = true; } } } if (needCheck) { ClipInteger(block, expression, toType, false); } } if (isArrayIndex) { block.AfterOutput += ")"; } }
public static bool CheckConversion(ConversionBlock block, Expression expression) { Conversion conversion = null; try { var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter); conversion = block.Emitter.Resolver.Resolver.GetConversion(expression); var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression); var invocationExpression = expression.Parent as InvocationExpression; if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression)) { var index = invocationExpression.Arguments.ToList().IndexOf(expression); var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult; var m = methodResolveResult.Member as IMethod; var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)]; if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } var namedArgExpression = expression.Parent as NamedArgumentExpression; if (namedArgExpression != null) { var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult; if (Helpers.IsDecimalType(namedArgResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } var namedExpression = expression.Parent as NamedExpression; if (namedExpression != null) { var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter); if (Helpers.IsDecimalType(namedResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } var binaryOpExpr = expression.Parent as BinaryOperatorExpression; if (binaryOpExpr != null) { var idx = binaryOpExpr.Left == expression ? 0 : 1; var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult; if (Helpers.IsDecimalType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(binaryOpRr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } var assignmentExpr = expression.Parent as AssignmentExpression; if (assignmentExpr != null) { var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult; if (Helpers.IsDecimalType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } var arrayInit = expression.Parent as ArrayInitializerExpression; if (arrayInit != null) { while (arrayInit.Parent is ArrayInitializerExpression) { arrayInit = (ArrayInitializerExpression)arrayInit.Parent; } IType elementType = null; var arrayCreate = arrayInit.Parent as ArrayCreateExpression; if (arrayCreate != null) { var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter); if (rrArrayType.Type is TypeWithElementType) { elementType = ((TypeWithElementType)rrArrayType.Type).ElementType; } else { elementType = rrArrayType.Type; } } else { var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter); var pt = rrElemenet.Type as ParameterizedType; if (pt != null) { elementType = pt.TypeArguments.Count > 0 ? pt.TypeArguments.First() : null; } else { var arrayType = rrElemenet.Type as TypeWithElementType; if (arrayType != null) { elementType = arrayType.ElementType; } else { elementType = rrElemenet.Type; } } } if (elementType != null && Helpers.IsDecimalType(elementType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { var castExpr = expression.Parent as CastExpression; ResolveResult castTypeRr = null; if (castExpr != null) { castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter); } if (castTypeRr == null || !Helpers.IsDecimalType(castTypeRr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver)) { return false; } if (conversion == null) { return false; } if (conversion.IsIdentityConversion) { return false; } var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression); if (isNumLifted && !conversion.IsUserDefined) { return false; } bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock); if (isLifted) { block.Write("Bridge.Nullable.lift("); } if (conversion.IsUserDefined) { var method = conversion.Method; string inline = block.Emitter.GetInline(method); if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline)) { // Still returns true if Nullable.lift( was written. return isLifted; } if (!string.IsNullOrWhiteSpace(inline)) { if (expression is InvocationExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is ObjectCreateExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is UnaryOperatorExpression) { var unaryExpression = (UnaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit(); } else if (expression is BinaryOperatorExpression) { var binaryExpression = (BinaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit(); } else { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit(); } block.DisableEmitConversionExpression = true; // Still returns true if Nullable.lift( was written. return isLifted; } else { if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { // Still returns true if Nullable.lift( was written. return isLifted; } block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter)); block.WriteDot(); block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName()); } if (isLifted) { block.WriteComma(); } else { block.WriteOpenParentheses(); } return true; } // Still returns true if Nullable.lift( was written. return isLifted; } catch { } return false; }
private static bool CheckTypeConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion, string typeName, IsType isType) { if (conversion.IsUserDefined) { var m = conversion.Method; if (isType(m.ReturnType, block.Emitter.Resolver)) { return(false); } } if (expression is CastExpression) { var nestedExpr = ((CastExpression)expression).Expression; var nested_rr = block.Emitter.Resolver.ResolveNode(nestedExpr, block.Emitter); if (!(nested_rr is ConversionResolveResult)) { return(false); } } var invocationExpression = expression.Parent as InvocationExpression; if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression)) { var index = invocationExpression.Arguments.ToList().IndexOf(expression); var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult; if (methodResolveResult != null) { var m = methodResolveResult.Member as IMethod; var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)]; if (isType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !isType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write(typeName); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } } } var objectCreateExpression = expression.Parent as ObjectCreateExpression; if (objectCreateExpression != null && objectCreateExpression.Arguments.Any(a => a == expression)) { var index = objectCreateExpression.Arguments.ToList().IndexOf(expression); var methodResolveResult = block.Emitter.Resolver.ResolveNode(objectCreateExpression, block.Emitter) as MemberResolveResult; if (methodResolveResult != null) { var m = methodResolveResult.Member as IMethod; var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)]; if (isType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !isType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write(typeName); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } } } var namedArgExpression = expression.Parent as NamedArgumentExpression; if (namedArgExpression != null) { var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult; if (isType(namedArgResolveResult.Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write(typeName); if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } } var namedExpression = expression.Parent as NamedExpression; if (namedExpression != null) { var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter); if (isType(namedResolveResult.Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write(typeName); if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } } var binaryOpExpr = expression.Parent as BinaryOperatorExpression; if (binaryOpExpr != null) { var idx = binaryOpExpr.Left == expression ? 0 : 1; var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult; if (binaryOpRr != null && isType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver)) { var isNullable = NullableType.IsNullable(binaryOpRr.Operands[idx].Type); if (expression.IsNull) { return(false); } block.Write(typeName); if (isNullable && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } } var conditionalExpr = expression.Parent as ConditionalExpression; if (conditionalExpr != null && conditionalExpr.Condition != expression) { var idx = conditionalExpr.TrueExpression == expression ? 0 : 1; var conditionalrr = block.Emitter.Resolver.ResolveNode(conditionalExpr, block.Emitter) as OperatorResolveResult; if (conditionalrr != null && isType(conditionalrr.Operands[idx].Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write(typeName); if (NullableType.IsNullable(conditionalrr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } } var assignmentExpr = expression.Parent as AssignmentExpression; if (assignmentExpr != null) { var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult; if (isType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write(typeName); if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } } var indexerExpr = expression.Parent as IndexerExpression; if (indexerExpr != null) { var index = indexerExpr.Arguments.ToList().IndexOf(expression); if (index >= 0) { var invocationrr = block.Emitter.Resolver.ResolveNode(indexerExpr, block.Emitter) as InvocationResolveResult; if (invocationrr != null && isType(invocationrr.Member.Parameters.ElementAt(index).Type, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write(typeName); if (NullableType.IsNullable(invocationrr.Member.Parameters.ElementAt(index).Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } } } var arrayInit = expression.Parent as ArrayInitializerExpression; if (arrayInit != null) { while (arrayInit.Parent is ArrayInitializerExpression) { arrayInit = (ArrayInitializerExpression)arrayInit.Parent; } IType elementType = null; var arrayCreate = arrayInit.Parent as ArrayCreateExpression; if (arrayCreate != null) { var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter); if (rrArrayType.Type is TypeWithElementType) { elementType = ((TypeWithElementType)rrArrayType.Type).ElementType; } else { elementType = rrArrayType.Type; } } else { var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter); var pt = rrElemenet.Type as ParameterizedType; if (pt != null && pt.TypeArguments.Count > 0) { if (pt.TypeArguments.Count == 1) { elementType = pt.TypeArguments.First(); } else { var index = 0; arrayInit = expression.Parent as ArrayInitializerExpression; for (int i = 0; i < arrayInit.Elements.Count; i++) { if (expression == arrayInit.Elements.ElementAt(i)) { index = i; break; } } elementType = index < pt.TypeArguments.Count ? pt.TypeArguments.ElementAt(index) : pt.TypeArguments.ElementAt(0); } } else { var arrayType = rrElemenet.Type as TypeWithElementType; if (arrayType != null) { elementType = arrayType.ElementType; } else { elementType = rrElemenet.Type; } } } if (elementType != null && isType(elementType, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write(typeName); if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } else if (Helpers.Is64Type(rr.Type, block.Emitter.Resolver) && Helpers.IsFloatType(elementType, block.Emitter.Resolver) && !Helpers.IsDecimalType(elementType, block.Emitter.Resolver) && isType(rr.Type, block.Emitter.Resolver)) { block.Write("Bridge.Long.toNumber"); if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } } if (isType(expectedType, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver) && !(conversion.IsExplicit && conversion.IsNumericConversion)) { var castExpr = expression.Parent as CastExpression; ResolveResult castTypeRr = null; if (castExpr != null) { castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter); } /*if (castTypeRr == null || !isType(castTypeRr.Type, block.Emitter.Resolver))*/ if (castTypeRr == null || !conversion.IsExplicit) { if (expression.IsNull) { return(false); } block.Write(typeName); if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } } return(false); }
public static bool CheckConversion(ConversionBlock block, Expression expression) { Conversion conversion = null; try { var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter); conversion = block.Emitter.Resolver.Resolver.GetConversion(expression); var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression); var invocationExpression = expression.Parent as InvocationExpression; if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression)) { var index = invocationExpression.Arguments.ToList().IndexOf(expression); var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult; if (methodResolveResult != null) { var m = methodResolveResult.Member as IMethod; var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)]; if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } } var namedArgExpression = expression.Parent as NamedArgumentExpression; if (namedArgExpression != null) { var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult; if (Helpers.IsDecimalType(namedArgResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var namedExpression = expression.Parent as NamedExpression; if (namedExpression != null) { var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter); if (Helpers.IsDecimalType(namedResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var binaryOpExpr = expression.Parent as BinaryOperatorExpression; if (binaryOpExpr != null) { var idx = binaryOpExpr.Left == expression ? 0 : 1; var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult; if (binaryOpRr != null && Helpers.IsDecimalType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(binaryOpRr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var conditionalExpr = expression.Parent as ConditionalExpression; if (conditionalExpr != null && conditionalExpr.Condition != expression) { var idx = conditionalExpr.TrueExpression == expression ? 0 : 1; var conditionalrr = block.Emitter.Resolver.ResolveNode(conditionalExpr, block.Emitter) as OperatorResolveResult; if (conditionalrr != null && Helpers.IsDecimalType(conditionalrr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(conditionalrr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var assignmentExpr = expression.Parent as AssignmentExpression; if (assignmentExpr != null) { var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult; if (Helpers.IsDecimalType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var arrayInit = expression.Parent as ArrayInitializerExpression; if (arrayInit != null) { while (arrayInit.Parent is ArrayInitializerExpression) { arrayInit = (ArrayInitializerExpression)arrayInit.Parent; } IType elementType = null; var arrayCreate = arrayInit.Parent as ArrayCreateExpression; if (arrayCreate != null) { var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter); if (rrArrayType.Type is TypeWithElementType) { elementType = ((TypeWithElementType)rrArrayType.Type).ElementType; } else { elementType = rrArrayType.Type; } } else { var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter); var pt = rrElemenet.Type as ParameterizedType; if (pt != null) { elementType = pt.TypeArguments.Count > 0 ? pt.TypeArguments.First() : null; } else { var arrayType = rrElemenet.Type as TypeWithElementType; if (arrayType != null) { elementType = arrayType.ElementType; } else { elementType = rrElemenet.Type; } } } if (elementType != null && Helpers.IsDecimalType(elementType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { var castExpr = expression.Parent as CastExpression; ResolveResult castTypeRr = null; if (castExpr != null) { castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter); } if (castTypeRr == null || !Helpers.IsDecimalType(castTypeRr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver)) { return(false); } if (conversion == null) { return(false); } if (conversion.IsIdentityConversion) { return(false); } var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression); if (isNumLifted && !conversion.IsUserDefined) { return(false); } bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock); if (isLifted) { block.Write("Bridge.Nullable.lift("); } if (conversion.IsUserDefined) { var method = conversion.Method; string inline = block.Emitter.GetInline(method); if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline)) { // Still returns true if Nullable.lift( was written. return(isLifted); } if (!string.IsNullOrWhiteSpace(inline)) { if (expression is InvocationExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is ObjectCreateExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is UnaryOperatorExpression) { var unaryExpression = (UnaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit(); } else if (expression is BinaryOperatorExpression) { var binaryExpression = (BinaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit(); } else { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit(); } block.DisableEmitConversionExpression = true; // Still returns true if Nullable.lift( was written. return(isLifted); } else { if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { // Still returns true if Nullable.lift( was written. return(isLifted); } block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter)); block.WriteDot(); block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName()); } if (isLifted) { block.WriteComma(); } else { block.WriteOpenParentheses(); } return(true); } // Still returns true if Nullable.lift( was written. return(isLifted); } catch { } return(false); }
public static int CheckConversion(ConversionBlock block, Expression expression) { try { var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter); var conversion = block.Emitter.Resolver.Resolver.GetConversion(expression); var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression); var level = ConversionBlock.CheckDecimalConversion(block, expression, rr, expectedType, conversion) ? 1 : 0; if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined) { return level; } if (conversion == null) { return level; } if (conversion.IsIdentityConversion) { return level; } var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression); if (isNumLifted && !conversion.IsUserDefined) { return level; } bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock) && !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver); if (isLifted) { level++; block.Write("Bridge.Nullable.lift("); } if (conversion.IsUserDefined) { var method = conversion.Method; string inline = block.Emitter.GetInline(method); if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline)) { // Still returns true if Nullable.lift( was written. return level; } if (!string.IsNullOrWhiteSpace(inline)) { if (expression is InvocationExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is ObjectCreateExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is UnaryOperatorExpression) { var unaryExpression = (UnaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit(); } else if (expression is BinaryOperatorExpression) { var binaryExpression = (BinaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit(); } else { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit(); } block.DisableEmitConversionExpression = true; // Still returns true if Nullable.lift( was written. return level; } else { if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { // Still returns true if Nullable.lift( was written. return level; } block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter)); block.WriteDot(); block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName()); } if (isLifted) { block.WriteComma(); } else { block.WriteOpenParentheses(); level++; } var arg = method.Parameters[0]; if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver) && !expression.IsNull) { block.Write("Bridge.Decimal"); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); level++; } return level; } // Still returns true if Nullable.lift( was written. return level; } catch { } return 0; }
public static int CheckConversion(ConversionBlock block, Expression expression) { try { var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter); var conversion = block.Emitter.Resolver.Resolver.GetConversion(expression); var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression); int level = 0; if (block.Emitter.IsAssignment) { return(level); } /*if (expression is ParenthesizedExpression && expression.Parent is CastExpression) * { * return level; * }*/ if (conversion.IsUserDefined && expression.Parent is CastExpression && ((CastExpression)expression.Parent).Expression == expression) { var parentConversion = block.Emitter.Resolver.Resolver.GetConversion((CastExpression)expression.Parent); if (!parentConversion.IsUserDefined || parentConversion.Method.Equals(conversion.Method)) { return(level); } } if (rr is ConstantResolveResult && expression is CastExpression && !conversion.IsUserDefined) { return(level); } var convrr = rr as ConversionResolveResult; if (convrr != null && convrr.Input is ConstantResolveResult && !convrr.Conversion.IsUserDefined) { return(level); } if (convrr != null && !conversion.IsUserDefined) { conversion = convrr.Conversion; rr = convrr.Input; expectedType = convrr.Type; } if (!((expression.Parent is CastExpression) && !(expression is CastExpression))) { CheckNumericConversion(block, expression, rr, expectedType, conversion); } if (!(conversion.IsExplicit && conversion.IsNumericConversion)) { level = ConversionBlock.CheckDecimalConversion(block, expression, rr, expectedType, conversion) ? (level + 1) : level; } if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined) { return(level); } if (!(conversion.IsExplicit && conversion.IsNumericConversion)) { level = ConversionBlock.CheckLongConversion(block, expression, rr, expectedType, conversion) ? (level + 1) : level; } if (Helpers.Is64Type(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined) { return(level); } if (conversion == null) { return(level); } if (conversion.IsIdentityConversion) { return(level); } var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression); if (isNumLifted && !conversion.IsUserDefined) { return(level); } bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock) && !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.Is64Type(expectedType, block.Emitter.Resolver) && !NullableType.IsNullable(expectedType); if (isLifted) { level++; block.Write("Bridge.Nullable.getValue("); } if (conversion.IsUserDefined) { var method = conversion.Method; string inline = block.Emitter.GetInline(method); if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline)) { // Still returns true if Nullable.lift( was written. return(level); } if (!string.IsNullOrWhiteSpace(inline)) { if (expression is InvocationExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is ObjectCreateExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (ObjectCreateExpression)expression), inline).Emit(); } else if (expression is UnaryOperatorExpression) { var unaryExpression = (UnaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit(); } else if (expression is BinaryOperatorExpression) { var binaryExpression = (BinaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit(); } else { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit(); } block.DisableEmitConversionExpression = true; // Still returns true if Nullable.lift( was written. return(level); } else { if (method.DeclaringTypeDefinition != null && (block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition) || Helpers.IsIgnoreCast(method.DeclaringTypeDefinition, block.Emitter))) { // Still returns true if Nullable.lift( was written. return(level); } block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter)); block.WriteDot(); block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName()); } if (isLifted) { block.WriteComma(); } else { block.WriteOpenParentheses(); level++; } var arg = method.Parameters[0]; if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver) && !expression.IsNull) { block.Write("Bridge.Decimal"); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(level); } block.WriteOpenParentheses(); level++; } if (Helpers.Is64Type(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.Is64Type(rr.Type, block.Emitter.Resolver) && !expression.IsNull) { var isUint = Helpers.IsULongType(arg.Type, block.Emitter.Resolver, arg.IsParams); block.Write("Bridge." + (isUint ? "ULong" : "Long")); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(level); } block.WriteOpenParentheses(); level++; } return(level); } // Still returns true if Nullable.lift( was written. return(level); } catch { } return(0); }
public static bool CheckConversion(ConversionBlock block, Expression expression) { Conversion conversion = null; try { var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter); conversion = block.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion == null) { return false; } if (conversion.IsIdentityConversion) { return false; } var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression); if (isNumLifted && !conversion.IsUserDefined) { return false; } if (conversion.IsLifted && !isNumLifted) { block.Write("Bridge.Nullable.lift("); } if (conversion.IsUserDefined) { var method = conversion.Method; string inline = block.Emitter.GetInline(method); if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline)) { // Still returns true if Nullable.lift( was written. return conversion.IsLifted; } if (!string.IsNullOrWhiteSpace(inline)) { if (expression is InvocationExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is ObjectCreateExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is UnaryOperatorExpression) { var unaryExpression = (UnaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr), inline).Emit(); } else if (expression is BinaryOperatorExpression) { var binaryExpression = (BinaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr), inline).Emit(); } else { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit(); } block.DisableEmitConversionExpression = true; // Still returns true if Nullable.lift( was written. return conversion.IsLifted; } else { if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { // Still returns true if Nullable.lift( was written. return conversion.IsLifted; } block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter)); block.WriteDot(); block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName()); } if (conversion.IsLifted) { block.WriteComma(); } else { block.WriteOpenParentheses(); } return true; } // Still returns true if Nullable.lift( was written. return conversion.IsLifted; } catch { } return false; }
private static int CheckUserDefinedConversion(ConversionBlock block, Expression expression, Conversion conversion, int level, ResolveResult rr, IType expectedType) { if (conversion.IsUserDefined && !ConversionBlock.expressionIgnoreUserDefine.Contains(expression)) { var method = conversion.Method; string inline = block.Emitter.GetInline(method); if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline)) { // Still returns true if Nullable.lift( was written. return(level); } if (!string.IsNullOrWhiteSpace(inline)) { ConversionBlock.expressionIgnoreUserDefine.Add(expression); if (expression is InvocationExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is ObjectCreateExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (ObjectCreateExpression)expression), inline).Emit(); } else if (expression is UnaryOperatorExpression) { var unaryExpression = (UnaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit(); } else { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression, method), inline, method).Emit(); } block.DisableEmitConversionExpression = true; ConversionBlock.expressionIgnoreUserDefine.Remove(expression); // Still returns true if Nullable.lift( was written. return(level); } else { if (method.DeclaringTypeDefinition != null && (block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition) || Helpers.IsIgnoreCast(method.DeclaringTypeDefinition, block.Emitter))) { // Still returns true if Nullable.lift( was written. return(level); } block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter)); block.WriteDot(); block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName()); } block.WriteOpenParentheses(); block.AfterOutput += ")"; var arg = method.Parameters[0]; if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver) && !expression.IsNull) { block.Write(JS.Types.SYSTEM_DECIMAL); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write("." + JS.Funcs.Math.LIFT); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(level); } block.WriteOpenParentheses(); block.AfterOutput += ")"; } if (Helpers.Is64Type(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.Is64Type(rr.Type, block.Emitter.Resolver) && !expression.IsNull) { var isUint = Helpers.IsULongType(arg.Type, block.Emitter.Resolver, arg.IsParams); block.Write(isUint ? JS.Types.SYSTEM_UInt64 : JS.Types.System.Int64.NAME); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write("." + JS.Funcs.Math.LIFT); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(level); } block.WriteOpenParentheses(); block.AfterOutput += ")"; } } return(level); }
private static int DoConversion(ConversionBlock block, Expression expression, Conversion conversion, IType expectedType, int level, ResolveResult rr, bool ignoreConversionResolveResult = false) { if (ConversionBlock.expressionIgnoreUserDefine.Contains(expression) && conversion.IsUserDefined) { expectedType = conversion.Method.Parameters.First().Type; } if (block.Emitter.IsAssignment) { return(level); } if (expression is ParenthesizedExpression && ((ParenthesizedExpression)expression).Expression is CastExpression) { return(level); } if (conversion.IsUserDefined && expression.Parent is CastExpression && ((CastExpression)expression.Parent).Expression == expression) { var parentConversion = block.Emitter.Resolver.Resolver.GetConversion((CastExpression)expression.Parent); if (!parentConversion.IsUserDefined || parentConversion.Method.Equals(conversion.Method)) { return(level); } } if (rr is ConstantResolveResult && expression is CastExpression && !conversion.IsUserDefined) { return(level); } var convrr = rr as ConversionResolveResult; if (convrr != null && convrr.Input is ConstantResolveResult && !convrr.Conversion.IsUserDefined) { return(level); } string afterUserDefined = ""; if (convrr != null && !conversion.IsUserDefined && !ignoreConversionResolveResult) { if (expectedType != convrr.Type) { if (expression.Parent is CastExpression && ((CastExpression)expression.Parent).Expression == expression) { var parentExpectedType = block.Emitter.Resolver.Resolver.GetExpectedType((CastExpression)expression.Parent); var parentrr = block.Emitter.Resolver.ResolveNode(expression.Parent, block.Emitter) as ConversionResolveResult; if (parentrr != null && parentrr.Type != expectedType || parentrr == null && expectedType != parentExpectedType) { level = ConversionBlock.DoConversion(block, expression, conversion, expectedType, level, rr, true); afterUserDefined = block.AfterOutput; block.AfterOutput = ""; } } else { level = ConversionBlock.DoConversion(block, expression, conversion, expectedType, level, rr, true); afterUserDefined = block.AfterOutput; block.AfterOutput = ""; } } conversion = convrr.Conversion; rr = convrr.Input; expectedType = convrr.Type; } var isNumLifted = conversion != null && conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression); bool skipUserConversion = conversion == null || (!conversion.IsUserDefined && (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) || Helpers.Is64Type(expectedType, block.Emitter.Resolver) || conversion.IsIdentityConversion || isNumLifted)); if (!skipUserConversion && conversion.IsUserDefined && (expression is BinaryOperatorExpression || expression is UnaryOperatorExpression || expression.Parent is AssignmentExpression)) { level = ConversionBlock.CheckUserDefinedConversion(block, expression, conversion, level, rr, expectedType); if (conversion.IsUserDefined && block.DisableEmitConversionExpression) { return(level); } afterUserDefined = block.AfterOutput + afterUserDefined; block.AfterOutput = ""; } if (!(conversion.IsExplicit && conversion.IsNumericConversion)) { if (ConversionBlock.CheckDecimalConversion(block, expression, rr, expectedType, conversion, ignoreConversionResolveResult)) { block.AfterOutput += ")"; } } if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined) { var s = block.AfterOutput; block.AfterOutput = ""; if (!((expression.Parent is CastExpression) && !(expression is CastExpression))) { ConversionBlock.CheckNumericConversion(block, expression, rr, expectedType, conversion); } block.AfterOutput = block.AfterOutput + s + afterUserDefined; return(level); } if (!(conversion.IsExplicit && conversion.IsNumericConversion)) { if (ConversionBlock.CheckLongConversion(block, expression, rr, expectedType, conversion, ignoreConversionResolveResult)) { block.AfterOutput += ")"; } } if (Helpers.Is64Type(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined) { var s = block.AfterOutput; block.AfterOutput = ""; if (!((expression.Parent is CastExpression) && !(expression is CastExpression))) { ConversionBlock.CheckNumericConversion(block, expression, rr, expectedType, conversion); } block.AfterOutput = block.AfterOutput + s + afterUserDefined; return(level); } if (!((expression.Parent is CastExpression) && !(expression is CastExpression))) { ConversionBlock.CheckNumericConversion(block, expression, rr, expectedType, conversion); } if (conversion.IsIdentityConversion) { block.AfterOutput = block.AfterOutput + afterUserDefined; return(level); } if (isNumLifted && !conversion.IsUserDefined) { block.AfterOutput = block.AfterOutput + afterUserDefined; return(level); } bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock) && !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.Is64Type(expectedType, block.Emitter.Resolver) && !NullableType.IsNullable(expectedType); if (isLifted) { block.Write(JS.Types.SYSTEM_NULLABLE + ".getValue("); block.AfterOutput += ")"; } if (conversion.IsUserDefined && !(expression is BinaryOperatorExpression || expression is UnaryOperatorExpression || expression.Parent is AssignmentExpression)) { level = ConversionBlock.CheckUserDefinedConversion(block, expression, conversion, level, rr, expectedType); } block.AfterOutput = block.AfterOutput + afterUserDefined; return(level); }
private static void CheckNumericConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion) { if (conversion.IsNumericConversion && conversion.IsExplicit) { var fromType = rr.Type; var toType = expectedType; if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(fromType, block.Emitter.Resolver)) { block.Write("Bridge.Decimal("); block.AfterOutput += ")"; } else if (Helpers.IsDecimalType(fromType, block.Emitter.Resolver)) { ClipDecimal(expression, block, toType); } else if (Helpers.Is64Type(fromType, block.Emitter.Resolver)) { CheckLong(block, expression, toType, fromType, IsInCheckedContext(block.Emitter, expression)); } else if (Helpers.IsFloatType(fromType, block.Emitter.Resolver) && Helpers.IsIntegerType(toType, block.Emitter.Resolver)) { FloatToInt(block, expression, fromType, toType, IsInCheckedContext(block.Emitter, expression)); } else if (NeedsNarrowingNumericConversion(fromType, toType)) { if (IsInCheckedContext(block.Emitter, expression)) { CheckInteger(block, expression, toType); } else { ClipInteger(block, expression, toType, true); } } } else if (conversion.IsNumericConversion && conversion.IsImplicit && !(expression.Parent is ArrayInitializerExpression) && Helpers.Is64Type(rr.Type, block.Emitter.Resolver) && Helpers.IsFloatType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver)) { var be = expression.Parent as BinaryOperatorExpression; if (be == null || be.Operator != BinaryOperatorType.Divide || be.Left != expression) { block.Write("Bridge.Long.toNumber"); if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression)) { block.Write("("); block.AfterOutput += ")"; } } } else if (((!Helpers.Is64Type(expectedType, block.Emitter.Resolver) && Helpers.IsIntegerType(expectedType, block.Emitter.Resolver)) || (rr is OperatorResolveResult && !Helpers.Is64Type(rr.Type, block.Emitter.Resolver) && Helpers.IsIntegerType(rr.Type, block.Emitter.Resolver))) && (expression is BinaryOperatorExpression || expression is UnaryOperatorExpression || expression.Parent is AssignmentExpression) && IsInCheckedContext(block.Emitter, expression)) { var needCheck = false; var be = expression as BinaryOperatorExpression; bool isBitwiseOperator = be != null && (be.Operator == BinaryOperatorType.ShiftLeft || be.Operator == BinaryOperatorType.ShiftRight || be.Operator == BinaryOperatorType.BitwiseAnd || be.Operator == BinaryOperatorType.BitwiseOr || be.Operator == BinaryOperatorType.ExclusiveOr); if ((Helpers.IsKnownType(KnownTypeCode.Int32, expectedType, block.Emitter.Resolver) && isBitwiseOperator) || (Helpers.IsKnownType(KnownTypeCode.UInt32, expectedType, block.Emitter.Resolver) && be != null && be.Operator == BinaryOperatorType.ShiftRight)) { // Don't need to check even in checked context and don't need to clip } else if (be != null && (be.Operator == BinaryOperatorType.Add || be.Operator == BinaryOperatorType.Divide || be.Operator == BinaryOperatorType.Multiply || isBitwiseOperator || be.Operator == BinaryOperatorType.Subtract)) { if (isBitwiseOperator) { ClipInteger(block, expression, expectedType, false); } else { needCheck = true; } } else { var ue = expression as UnaryOperatorExpression; if (ue != null && (ue.Operator == UnaryOperatorType.Minus || ue.Operator == UnaryOperatorType.Increment || ue.Operator == UnaryOperatorType.Decrement || ue.Operator == UnaryOperatorType.PostIncrement || ue.Operator == UnaryOperatorType.PostDecrement)) { needCheck = true; } else { var ae = expression.Parent as AssignmentExpression; isBitwiseOperator = ae != null && (ae.Operator == AssignmentOperatorType.ShiftRight || ae.Operator == AssignmentOperatorType.ShiftLeft || ae.Operator == AssignmentOperatorType.BitwiseAnd || ae.Operator == AssignmentOperatorType.BitwiseOr || ae.Operator == AssignmentOperatorType.ExclusiveOr); if ((isBitwiseOperator && Helpers.IsKnownType(KnownTypeCode.Int32, expectedType, block.Emitter.Resolver)) || (ae != null && ae.Operator == AssignmentOperatorType.ShiftRight && Helpers.IsKnownType(KnownTypeCode.UInt32, expectedType, block.Emitter.Resolver))) { // Don't need to check even in checked context and don't need to clip } else if (ae != null && (isBitwiseOperator || ae.Operator == AssignmentOperatorType.Add || ae.Operator == AssignmentOperatorType.Divide || ae.Operator == AssignmentOperatorType.Multiply || ae.Operator == AssignmentOperatorType.Subtract)) { if (isBitwiseOperator) { ClipInteger(block, expression, expectedType, false); } else { needCheck = true; } } } } if (!Helpers.IsIntegerType(expectedType, block.Emitter.Resolver)) { if (rr is OperatorResolveResult) { expectedType = rr.Type; } } if (needCheck) { CheckInteger(block, expression, expectedType); } } else if (((!Helpers.Is64Type(expectedType, block.Emitter.Resolver) && Helpers.IsIntegerType(expectedType, block.Emitter.Resolver)) || (rr is OperatorResolveResult && !Helpers.Is64Type(rr.Type, block.Emitter.Resolver) && Helpers.IsIntegerType(rr.Type, block.Emitter.Resolver))) && (expression is BinaryOperatorExpression || expression is UnaryOperatorExpression || expression.Parent is AssignmentExpression) && IsInUncheckedContext(block.Emitter, expression)) { if (ConversionBlock.IsLongConversion(block, expression, rr, expectedType, conversion) || rr is ConstantResolveResult) { return; } if (!Helpers.IsIntegerType(expectedType, block.Emitter.Resolver)) { if (rr is OperatorResolveResult) { expectedType = rr.Type; } } var needCheck = false; var be = expression as BinaryOperatorExpression; bool isBitwiseOperator = be != null && (be.Operator == BinaryOperatorType.ShiftLeft || be.Operator == BinaryOperatorType.ShiftRight || be.Operator == BinaryOperatorType.BitwiseAnd || be.Operator == BinaryOperatorType.BitwiseOr || be.Operator == BinaryOperatorType.ExclusiveOr); if ((Helpers.IsKnownType(KnownTypeCode.Int32, expectedType, block.Emitter.Resolver) && isBitwiseOperator) || (Helpers.IsKnownType(KnownTypeCode.UInt32, expectedType, block.Emitter.Resolver) && be != null && be.Operator == BinaryOperatorType.ShiftRight)) { // Don't need to check even in checked context and don't need to clip } else if (be != null && !(be.Left is PrimitiveExpression && be.Right is PrimitiveExpression) && (be.Operator == BinaryOperatorType.Add || be.Operator == BinaryOperatorType.Divide || be.Operator == BinaryOperatorType.Multiply || isBitwiseOperator || be.Operator == BinaryOperatorType.Subtract)) { needCheck = true; } else { var ue = expression as UnaryOperatorExpression; if (ue != null && !(ue.Expression is PrimitiveExpression) && (ue.Operator == UnaryOperatorType.Minus || ue.Operator == UnaryOperatorType.Increment || ue.Operator == UnaryOperatorType.Decrement || ue.Operator == UnaryOperatorType.PostIncrement || ue.Operator == UnaryOperatorType.PostDecrement)) { needCheck = true; } else { var ae = expression.Parent as AssignmentExpression; isBitwiseOperator = ae != null && (ae.Operator == AssignmentOperatorType.ShiftRight || ae.Operator == AssignmentOperatorType.ShiftLeft || ae.Operator == AssignmentOperatorType.BitwiseAnd || ae.Operator == AssignmentOperatorType.BitwiseOr || ae.Operator == AssignmentOperatorType.ExclusiveOr); if ((isBitwiseOperator && Helpers.IsKnownType(KnownTypeCode.Int32, expectedType, block.Emitter.Resolver)) || (ae != null && ae.Operator == AssignmentOperatorType.ShiftRight && Helpers.IsKnownType(KnownTypeCode.UInt32, expectedType, block.Emitter.Resolver))) { // Don't need to check even in checked context and don't need to clip } else if (ae != null && (isBitwiseOperator || ae.Operator == AssignmentOperatorType.Add || ae.Operator == AssignmentOperatorType.Divide || ae.Operator == AssignmentOperatorType.Multiply || ae.Operator == AssignmentOperatorType.Subtract)) { needCheck = true; } } } if (needCheck) { ClipInteger(block, expression, expectedType, false); } } }
private static bool CheckDecimalConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion) { if (conversion.IsUserDefined) { var m = conversion.Method; if (Helpers.IsDecimalType(m.ReturnType, block.Emitter.Resolver)) { return(false); } } var invocationExpression = expression.Parent as InvocationExpression; if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression)) { var index = invocationExpression.Arguments.ToList().IndexOf(expression); var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult; if (methodResolveResult != null) { var m = methodResolveResult.Member as IMethod; var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)]; if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } } var namedArgExpression = expression.Parent as NamedArgumentExpression; if (namedArgExpression != null) { var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult; if (Helpers.IsDecimalType(namedArgResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var namedExpression = expression.Parent as NamedExpression; if (namedExpression != null) { var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter); if (Helpers.IsDecimalType(namedResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var binaryOpExpr = expression.Parent as BinaryOperatorExpression; if (binaryOpExpr != null) { var idx = binaryOpExpr.Left == expression ? 0 : 1; var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult; if (binaryOpRr != null && Helpers.IsDecimalType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(binaryOpRr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var conditionalExpr = expression.Parent as ConditionalExpression; if (conditionalExpr != null && conditionalExpr.Condition != expression) { var idx = conditionalExpr.TrueExpression == expression ? 0 : 1; var conditionalrr = block.Emitter.Resolver.ResolveNode(conditionalExpr, block.Emitter) as OperatorResolveResult; if (conditionalrr != null && Helpers.IsDecimalType(conditionalrr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(conditionalrr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var assignmentExpr = expression.Parent as AssignmentExpression; if (assignmentExpr != null) { var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult; if (Helpers.IsDecimalType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var arrayInit = expression.Parent as ArrayInitializerExpression; if (arrayInit != null) { while (arrayInit.Parent is ArrayInitializerExpression) { arrayInit = (ArrayInitializerExpression)arrayInit.Parent; } IType elementType = null; var arrayCreate = arrayInit.Parent as ArrayCreateExpression; if (arrayCreate != null) { var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter); if (rrArrayType.Type is TypeWithElementType) { elementType = ((TypeWithElementType)rrArrayType.Type).ElementType; } else { elementType = rrArrayType.Type; } } else { var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter); var pt = rrElemenet.Type as ParameterizedType; if (pt != null) { elementType = pt.TypeArguments.Count > 0 ? pt.TypeArguments.First() : null; } else { var arrayType = rrElemenet.Type as TypeWithElementType; if (arrayType != null) { elementType = arrayType.ElementType; } else { elementType = rrElemenet.Type; } } } if (elementType != null && Helpers.IsDecimalType(elementType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { var castExpr = expression.Parent as CastExpression; ResolveResult castTypeRr = null; if (castExpr != null) { castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter); } if (castTypeRr == null || !Helpers.IsDecimalType(castTypeRr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } return(false); }
public static bool CheckConversion(ConversionBlock block, Expression expression) { Conversion conversion = null; try { var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter); conversion = block.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion == null) { return(false); } if (conversion.IsIdentityConversion) { return(false); } if (conversion.IsLifted) { block.Write("Bridge.Nullable.lift("); } if (conversion.IsUserDefined) { var method = conversion.Method; string inline = block.Emitter.GetInline(method); if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline)) { return(false); } if (!string.IsNullOrWhiteSpace(inline)) { if (expression is InvocationExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is ObjectCreateExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is UnaryOperatorExpression) { var unaryExpression = (UnaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr), inline).Emit(); } else if (expression is BinaryOperatorExpression) { var binaryExpression = (BinaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr), inline).Emit(); } else { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit(); } block.DisableEmitConversionExpression = true; return(false); } else { if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { return(false); } block.Write(block.Emitter.ShortenTypeName(Helpers.GetScriptFullName(method.DeclaringType))); block.WriteDot(); block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName()); } if (conversion.IsLifted) { block.WriteComma(); } else { block.WriteOpenParentheses(); } return(true); } else if (conversion.IsNumericConversion) { } } catch { } return(false); }
public static int CheckConversion(ConversionBlock block, Expression expression) { try { var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter); var conversion = block.Emitter.Resolver.Resolver.GetConversion(expression); var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression); var level = ConversionBlock.CheckDecimalConversion(block, expression, rr, expectedType, conversion) ? 1 : 0; if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined) { return(level); } if (conversion == null) { return(level); } if (conversion.IsIdentityConversion) { return(level); } var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression); if (isNumLifted && !conversion.IsUserDefined) { return(level); } bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock) && !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver); if (isLifted) { level++; block.Write("Bridge.Nullable.lift("); } if (conversion.IsUserDefined) { var method = conversion.Method; string inline = block.Emitter.GetInline(method); if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline)) { // Still returns true if Nullable.lift( was written. return(level); } if (!string.IsNullOrWhiteSpace(inline)) { if (expression is InvocationExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is ObjectCreateExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is UnaryOperatorExpression) { var unaryExpression = (UnaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit(); } else if (expression is BinaryOperatorExpression) { var binaryExpression = (BinaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit(); } else { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit(); } block.DisableEmitConversionExpression = true; // Still returns true if Nullable.lift( was written. return(level); } else { if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { // Still returns true if Nullable.lift( was written. return(level); } block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter)); block.WriteDot(); block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName()); } if (isLifted) { block.WriteComma(); } else { block.WriteOpenParentheses(); level++; } var arg = method.Parameters[0]; if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver) && !expression.IsNull) { block.Write("Bridge.Decimal"); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); level++; } return(level); } // Still returns true if Nullable.lift( was written. return(level); } catch { } return(0); }
private static bool CheckDecimalConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion) { if (conversion.IsUserDefined) { var m = conversion.Method; if (Helpers.IsDecimalType(m.ReturnType, block.Emitter.Resolver)) { return false; } } var invocationExpression = expression.Parent as InvocationExpression; if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression)) { var index = invocationExpression.Arguments.ToList().IndexOf(expression); var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult; if (methodResolveResult != null) { var m = methodResolveResult.Member as IMethod; var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)]; if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } } var namedArgExpression = expression.Parent as NamedArgumentExpression; if (namedArgExpression != null) { var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult; if (Helpers.IsDecimalType(namedArgResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } var namedExpression = expression.Parent as NamedExpression; if (namedExpression != null) { var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter); if (Helpers.IsDecimalType(namedResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } var binaryOpExpr = expression.Parent as BinaryOperatorExpression; if (binaryOpExpr != null) { var idx = binaryOpExpr.Left == expression ? 0 : 1; var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult; if (binaryOpRr != null && Helpers.IsDecimalType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(binaryOpRr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } var conditionalExpr = expression.Parent as ConditionalExpression; if (conditionalExpr != null && conditionalExpr.Condition != expression) { var idx = conditionalExpr.TrueExpression == expression ? 0 : 1; var conditionalrr = block.Emitter.Resolver.ResolveNode(conditionalExpr, block.Emitter) as OperatorResolveResult; if (conditionalrr != null && Helpers.IsDecimalType(conditionalrr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(conditionalrr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } var assignmentExpr = expression.Parent as AssignmentExpression; if (assignmentExpr != null) { var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult; if (Helpers.IsDecimalType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } var arrayInit = expression.Parent as ArrayInitializerExpression; if (arrayInit != null) { while (arrayInit.Parent is ArrayInitializerExpression) { arrayInit = (ArrayInitializerExpression)arrayInit.Parent; } IType elementType = null; var arrayCreate = arrayInit.Parent as ArrayCreateExpression; if (arrayCreate != null) { var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter); if (rrArrayType.Type is TypeWithElementType) { elementType = ((TypeWithElementType)rrArrayType.Type).ElementType; } else { elementType = rrArrayType.Type; } } else { var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter); var pt = rrElemenet.Type as ParameterizedType; if (pt != null) { elementType = pt.TypeArguments.Count > 0 ? pt.TypeArguments.First() : null; } else { var arrayType = rrElemenet.Type as TypeWithElementType; if (arrayType != null) { elementType = arrayType.ElementType; } else { elementType = rrElemenet.Type; } } } if (elementType != null && Helpers.IsDecimalType(elementType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { var castExpr = expression.Parent as CastExpression; ResolveResult castTypeRr = null; if (castExpr != null) { castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter); } if (castTypeRr == null || !Helpers.IsDecimalType(castTypeRr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return false; } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return true; } } return false; }