public static void ClipInteger(ConversionBlock block, Expression expression, IType type, bool isExplicit) { var specialType = NullableType.IsNullable(type) ? NullableType.GetUnderlyingType(type) : type; if (!isExplicit && (specialType.IsKnownType(KnownTypeCode.UInt64) || specialType.IsKnownType(KnownTypeCode.Int64))) { //expression.AcceptVisitor(block.Emitter); return; } NarrowingNumericOrEnumerationConversion(block, expression, specialType, false, false, NullableType.IsNullable(type), isExplicit); }
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) + ")"; } }
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; return(ConversionBlock.DoConversion(block, expression, conversion, expectedType, level, rr)); } catch { } return(0); }
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 AddBox(IMember m, IEmitter emitter, JObject properties) { bool needBox = ConversionBlock.IsBoxable(m.ReturnType, emitter) || m.ReturnType.IsKnownType(KnownTypeCode.NullableOfT) && ConversionBlock.IsBoxable(NullableType.GetUnderlyingType(m.ReturnType), emitter); if (needBox) { StringBuilder sb = new StringBuilder("function (" + JS.Vars.V + ") { return "); sb.Append(JS.Types.Bridge.BOX); sb.Append("(" + JS.Vars.V + ", "); sb.Append(ConversionBlock.GetBoxedType(m.ReturnType, emitter)); var inlineMethod = ConversionBlock.GetInlineMethod(emitter, CS.Methods.TOSTRING, emitter.Resolver.Compilation.FindType(KnownTypeCode.String), m.ReturnType, null); if (inlineMethod != null) { sb.Append(", " + inlineMethod); } inlineMethod = ConversionBlock.GetInlineMethod(emitter, CS.Methods.GETHASHCODE, emitter.Resolver.Compilation.FindType(KnownTypeCode.Int32), m.ReturnType, null); if (inlineMethod != null) { sb.Append(", " + inlineMethod); } sb.Append(");"); sb.Append("}"); properties.Add(JS.Fields.BOX, new JRaw(sb.ToString())); } }
protected virtual int CheckConversion(Expression expression) { return(ConversionBlock.CheckConversion(this, expression)); }
public static void FloatToInt(ConversionBlock block, Expression expression, IType sourceType, IType targetType, bool isChecked) { NarrowingNumericOrEnumerationConversion(block, expression, NullableType.IsNullable(targetType) ? NullableType.GetUnderlyingType(targetType) : targetType, true, isChecked, NullableType.IsNullable(sourceType)); }
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 += ")"; } } }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var castToEnum = this.Emitter.BridgeTypes.ToType(type).Kind == TypeKind.Enum; if (method != Bridge.Translator.Emitter.IS && (Helpers.IsIgnoreCast(type, this.Emitter) || castToEnum)) { expression.AcceptVisitor(this.Emitter); return; } if (method == Bridge.Translator.Emitter.IS && castToEnum) { this.Write("Bridge.hasValue("); expression.AcceptVisitor(this.Emitter); this.Write(")"); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Equals(typerr.Type)) { if (method == Bridge.Translator.Emitter.IS) { this.WriteScript(true); } else { expression.AcceptVisitor(this.Emitter); } return; } bool isInlineCast; string castCode = this.GetCastCode(expression, type, out isInlineCast); bool isNullable = NullableType.IsNullable(expressionrr.Type); bool isResultNullable = NullableType.IsNullable(typerr.Type); if (isInlineCast) { if (isNullable) { isNullable = !NullableType.GetUnderlyingType(expressionrr.Type).Equals(typerr.Type); } this.EmitInlineCast(expression, type, castCode, isNullable, isResultNullable); return; } if (method == Bridge.Translator.Emitter.CAST) { if (Helpers.IsIntegerType(typerr.Type, this.Emitter.Resolver)) { if (expressionrr.Type != null && Helpers.IsFloatType(expressionrr.Type, this.Emitter.Resolver)) { this.Write("Bridge.Int.trunc("); if (isNullable && !isResultNullable) { this.Write("Bridge.Nullable.getValue("); } expression.AcceptVisitor(this.Emitter); if (isNullable && !isResultNullable) { this.WriteCloseParentheses(); } this.Write(")"); return; } } if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression)) { expression.AcceptVisitor(this.Emitter); return; } } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == Bridge.Translator.Emitter.CAST || method == Bridge.Translator.Emitter.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == Bridge.Translator.Emitter.IS) { hasValue = true; method = "hasValue"; } } this.Write(Bridge.Translator.Emitter.ROOT); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); if (isNullable && !isResultNullable) { this.Write("Bridge.Nullable.getValue("); } expression.AcceptVisitor(this.Emitter); if (isNullable && !isResultNullable) { this.WriteCloseParentheses(); } if (!hasValue) { this.WriteComma(); if (castCode != null) { this.Write(castCode); } else { this.EmitCastType(type); } } if (isResultNullable && method != Bridge.Translator.Emitter.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var castToEnum = this.Emitter.BridgeTypes.ToType(type).Kind == TypeKind.Enum; if (method != Bridge.Translator.Emitter.IS && (Helpers.IsIgnoreCast(type, this.Emitter) || castToEnum)) { expression.AcceptVisitor(this.Emitter); return; } if (method == Bridge.Translator.Emitter.CAST) { var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter); if (cast_rr is ConstantResolveResult) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)cast_rr).ConstantValue; this.WriteCastValue(value, expectedType); return; } else { var conv_rr = cast_rr as ConversionResolveResult; if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)conv_rr.Input).ConstantValue; this.WriteCastValue(value, expectedType); return; } } } if (method == Bridge.Translator.Emitter.IS && castToEnum) { this.Write("Bridge.hasValue("); expression.AcceptVisitor(this.Emitter); this.Write(")"); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Equals(typerr.Type)) { if (method == Bridge.Translator.Emitter.IS) { this.WriteScript(true); } else { expression.AcceptVisitor(this.Emitter); } return; } bool isInlineCast; string castCode = this.GetCastCode(expression, type, out isInlineCast); bool isNullable = NullableType.IsNullable(expressionrr.Type); bool isResultNullable = NullableType.IsNullable(typerr.Type); if (isInlineCast) { this.EmitInlineCast(expression, type, castCode); return; } bool isCast = method == Bridge.Translator.Emitter.CAST; if (isCast) { if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression)) { expression.AcceptVisitor(this.Emitter); return; } } var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion.IsNumericConversion || (isCast && conversion.IsIdentityConversion)) { expression.AcceptVisitor(this.Emitter); return; } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == Bridge.Translator.Emitter.CAST || method == Bridge.Translator.Emitter.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == Bridge.Translator.Emitter.IS) { hasValue = true; method = "hasValue"; } } this.Write(Bridge.Translator.Emitter.ROOT); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); if (!hasValue) { this.WriteComma(); if (castCode != null) { this.Write(castCode); } else { this.EmitCastType(type); } } if (isResultNullable && method != Bridge.Translator.Emitter.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); }
protected void VisitAssignmentExpression() { AssignmentExpression assignmentExpression = this.AssignmentExpression; var oldAssigment = this.Emitter.IsAssignment; var oldAssigmentType = this.Emitter.AssignmentType; string variable = null; bool needReturnValue = !(assignmentExpression.Parent is ExpressionStatement); if (needReturnValue && assignmentExpression.Parent is LambdaExpression) { var lambdarr = this.Emitter.Resolver.ResolveNode(assignmentExpression.Parent, this.Emitter) as LambdaResolveResult; if (lambdarr != null && lambdarr.ReturnType.Kind == TypeKind.Void) { needReturnValue = false; } } var delegateAssigment = false; bool isEvent = false; var initCount = this.Emitter.Writers.Count; var asyncExpressionHandling = this.Emitter.AsyncExpressionHandling; this.WriteAwaiters(assignmentExpression.Left); this.WriteAwaiters(assignmentExpression.Right); var leftResolverResult = this.Emitter.Resolver.ResolveNode(assignmentExpression.Left, this.Emitter); var rightResolverResult = this.Emitter.Resolver.ResolveNode(assignmentExpression.Right, this.Emitter); var rr = this.Emitter.Resolver.ResolveNode(assignmentExpression, this.Emitter); var orr = rr as OperatorResolveResult; bool isDecimal = Helpers.IsDecimalType(rr.Type, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(rr.Type, this.Emitter.Resolver); var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver); bool isLongExpected = Helpers.Is64Type(expectedType, this.Emitter.Resolver); bool isUserOperator = this.IsUserOperator(orr); bool isUint = rr.Type.IsKnownType(KnownTypeCode.UInt16) || rr.Type.IsKnownType(KnownTypeCode.UInt32) || rr.Type.IsKnownType(KnownTypeCode.UInt64); var charToString = -1; if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String)) { for (int i = 0; i < orr.Operands.Count; i++) { var crr = orr.Operands[i] as ConversionResolveResult; if (crr != null && crr.Input.Type.IsKnownType(KnownTypeCode.Char)) { charToString = i; } } } var memberTargetrr = leftResolverResult as MemberResolveResult; bool isField = (memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult)) || leftResolverResult is ThisResolveResult || leftResolverResult is LocalResolveResult || leftResolverResult is ConstantResolveResult; var rightMemberTargetrr = rightResolverResult as MemberResolveResult; bool isRightSimple = (rightMemberTargetrr != null && rightMemberTargetrr.Member is IField && (rightMemberTargetrr.TargetResult is ThisResolveResult || rightMemberTargetrr.TargetResult is LocalResolveResult)) || rightResolverResult is ThisResolveResult || rightResolverResult is LocalResolveResult || rightResolverResult is ConstantResolveResult; var needTempVar = needReturnValue && (!isRightSimple && !isField || assignmentExpression.Operator != AssignmentOperatorType.Assign); /*if (assignmentExpression.Operator == AssignmentOperatorType.Any) * { * needTempVar = false; * }*/ if (needReturnValue) { if (needTempVar) { variable = this.GetTempVarName(); this.Write("(" + variable + " = "); var oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Write(", "); } else { this.Write("("); } } if (assignmentExpression.Operator == AssignmentOperatorType.Divide && !(this.Emitter.IsJavaScriptOverflowMode && !ConversionBlock.InsideOverflowContext(this.Emitter, assignmentExpression)) && !isLong && !isLongExpected && ( (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) || (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Left), this.Emitter.Resolver) && Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Right), this.Emitter.Resolver)) )) { this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = AssignmentOperatorType.Assign; var oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Left.AcceptVisitor(this.Emitter); if (this.Emitter.Writers.Count == initCount) { this.Write(" = "); } this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Emitter.AssignmentType = oldAssigmentType; this.Emitter.IsAssignment = oldAssigment; this.Write(JS.Types.BRIDGE_INT + "." + JS.Funcs.Math.DIV + "("); assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Write(", "); oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Write(")"); this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } if (needReturnValue && !isField) { if (needTempVar) { this.Write(", " + variable); } else { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } } if (needReturnValue) { this.Write(")"); } return; } if (assignmentExpression.Operator == AssignmentOperatorType.Add || assignmentExpression.Operator == AssignmentOperatorType.Subtract) { var add = assignmentExpression.Operator == AssignmentOperatorType.Add; if (this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult)) { delegateAssigment = true; var leftMemberResolveResult = leftResolverResult as MemberResolveResult; if (leftMemberResolveResult != null) { isEvent = leftMemberResolveResult.Member is IEvent; } if (!isEvent) { this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = AssignmentOperatorType.Assign; assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = false; if (this.Emitter.Writers.Count == initCount) { this.Write(" = "); } this.Write(add ? JS.Funcs.BRIDGE_COMBINE : JS.Funcs.BRIDGE_REMOVE); this.WriteOpenParentheses(); } } } bool nullable = orr != null && orr.IsLiftedOperator; string root = JS.Types.SYSTEM_NULLABLE + "."; bool special = nullable; this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = assignmentExpression.Operator; var oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; bool thisAssignment = leftResolverResult is ThisResolveResult; if (!thisAssignment) { if (special || (isDecimal && isDecimalExpected) || (isLong && isLongExpected) || isUserOperator) { this.Emitter.AssignmentType = AssignmentOperatorType.Assign; } if (delegateAssigment && !isEvent) { this.Emitter.IsAssignment = false; } assignmentExpression.Left.AcceptVisitor(this.Emitter); if (delegateAssigment) { this.Emitter.IsAssignment = true; } } else { this.Write("("); } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AssignmentType = oldAssigmentType; this.Emitter.IsAssignment = oldAssigment; if (this.Emitter.Writers.Count == initCount && !delegateAssigment && !thisAssignment) { this.WriteSpace(); } if (isDecimal && isDecimalExpected) { if (this.Emitter.Writers.Count == initCount) { this.Write("= "); } oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; this.HandleDecimal(rr, variable); if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } if (needTempVar) { this.Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } this.Write(")"); } this.Emitter.ReplaceAwaiterByVar = oldValue; return; } if (isLong && isLongExpected) { if (this.Emitter.Writers.Count == initCount) { this.Write("= "); } oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; this.HandleLong(rr, variable, isUint); if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } if (needTempVar) { this.Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } this.Write(")"); } this.Emitter.ReplaceAwaiterByVar = oldValue; return; } if (this.ResolveOperator(assignmentExpression, orr, initCount, thisAssignment)) { if (thisAssignment) { this.Write(")." + JS.Funcs.CLONE + "(this)"); } else if (needReturnValue) { this.Write(")"); } return; } bool isBool = NullableType.IsNullable(rr.Type) ? NullableType.GetUnderlyingType(rr.Type).IsKnownType(KnownTypeCode.Boolean) : rr.Type.IsKnownType(KnownTypeCode.Boolean); if (!delegateAssigment) { if (!special) { switch (assignmentExpression.Operator) { case AssignmentOperatorType.Assign: break; case AssignmentOperatorType.Add: this.Write("+"); break; case AssignmentOperatorType.BitwiseAnd: if (!isBool) { this.Write("&"); } break; case AssignmentOperatorType.BitwiseOr: if (!isBool) { this.Write("|"); } break; case AssignmentOperatorType.Divide: this.Write("/"); break; case AssignmentOperatorType.ExclusiveOr: this.Write("^"); break; case AssignmentOperatorType.Modulus: this.Write("%"); break; case AssignmentOperatorType.Multiply: this.Write("*"); break; case AssignmentOperatorType.ShiftLeft: this.Write("<<"); break; case AssignmentOperatorType.ShiftRight: this.Write(isUint ? ">>>" : ">>"); break; case AssignmentOperatorType.Subtract: this.Write("-"); break; default: throw new EmitterException(assignmentExpression, "Unsupported assignment operator: " + assignmentExpression.Operator.ToString()); } } if (special) { if (this.Emitter.Writers.Count == initCount) { this.Write("= "); } this.Write(root); switch (assignmentExpression.Operator) { case AssignmentOperatorType.Assign: break; case AssignmentOperatorType.Add: this.Write(JS.Funcs.Math.ADD); break; case AssignmentOperatorType.BitwiseAnd: this.Write(isBool ? JS.Funcs.Math.AND : JS.Funcs.Math.BAND); break; case AssignmentOperatorType.BitwiseOr: this.Write(isBool ? JS.Funcs.Math.OR : JS.Funcs.Math.BOR); break; case AssignmentOperatorType.Divide: this.Write(JS.Funcs.Math.DIV); break; case AssignmentOperatorType.ExclusiveOr: this.Write(JS.Funcs.Math.XOR); break; case AssignmentOperatorType.Modulus: this.Write(JS.Funcs.Math.MOD); break; case AssignmentOperatorType.Multiply: this.Write(JS.Funcs.Math.MUL); break; case AssignmentOperatorType.ShiftLeft: this.Write(JS.Funcs.Math.SL); break; case AssignmentOperatorType.ShiftRight: this.Write(isUint ? JS.Funcs.Math.SRR : JS.Funcs.Math.SR); break; case AssignmentOperatorType.Subtract: this.Write(JS.Funcs.Math.SUB); break; default: throw new EmitterException(assignmentExpression, "Unsupported assignment operator: " + assignmentExpression.Operator.ToString()); } this.WriteOpenParentheses(); assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Write(", "); } if (this.Emitter.Writers.Count == initCount && !thisAssignment && !special) { this.Write("= "); } } else if (!isEvent) { this.WriteComma(); } if (!special && isBool && (assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd || assignmentExpression.Operator == AssignmentOperatorType.BitwiseOr)) { this.Write("!!("); assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Write(assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd ? " & " : " | "); } oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; if (charToString == 1) { this.Write(JS.Funcs.STRING_FROMCHARCODE + "("); } if (needTempVar) { this.Write(variable); } else { var wrap = assignmentExpression.Operator != AssignmentOperatorType.Assign && this.Emitter.Writers.Count > initCount && !AssigmentExpressionHelper.CheckIsRightAssigmentExpression(assignmentExpression); if (wrap) { this.WriteOpenParentheses(); } assignmentExpression.Right.AcceptVisitor(this.Emitter); if (wrap) { this.WriteCloseParentheses(); } } if (!special && isBool && (assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd || assignmentExpression.Operator == AssignmentOperatorType.BitwiseOr)) { this.WriteCloseParentheses(); } if (charToString == 1) { this.WriteCloseParentheses(); } if (special) { this.WriteCloseParentheses(); } if (thisAssignment) { this.Write(")." + JS.Funcs.CLONE + "(this)"); } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (this.Emitter.Writers.Count > initCount) { var writerCount = this.Emitter.Writers.Count; for (int i = initCount; i < writerCount; i++) { this.PopWriter(); } } if (delegateAssigment) { this.WriteCloseParentheses(); } if (needTempVar) { this.Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } this.Write(")"); } }
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 bool CheckTypeConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion, string typeName, IsType isType, bool ignoreConversionResolveResult) { if (conversion.IsUserDefined) { var m = conversion.Method; if (isType(m.ReturnType, block.Emitter.Resolver)) { return(false); } } if (expression is CastExpression && !ignoreConversionResolveResult) { 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("." + JS.Funcs.Math.LIFT); } if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT); } if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT); } if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT); } if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT); } if (!ignoreConversionResolveResult && 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 ? 1 : 2; 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("." + JS.Funcs.Math.LIFT); } if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT); } if (!ignoreConversionResolveResult && 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) { var parameters = invocationrr.Member.Parameters; if (parameters.Count <= index) { index = parameters.Count - 1; } if (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("." + JS.Funcs.Math.LIFT); } if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT); } if (!ignoreConversionResolveResult && 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(JS.Types.System.Int64.TONUMBER); if (!ignoreConversionResolveResult && 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("." + JS.Funcs.Math.LIFT); } if (!ignoreConversionResolveResult && expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } block.WriteOpenParentheses(); return(true); } } return(false); }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var itype = this.Emitter.BridgeTypes.ToType(type); bool isCastAttr; string castCode = this.GetCastCode(expression, type, method, out isCastAttr); var enumType = itype; if (NullableType.IsNullable(enumType)) { enumType = NullableType.GetUnderlyingType(enumType); } var castToEnum = enumType.Kind == TypeKind.Enum; if (castToEnum) { itype = enumType.GetDefinition().EnumUnderlyingType; var enumMode = Helpers.EnumEmitMode(enumType); if (enumMode >= 3 && enumMode < 7) { itype = this.Emitter.Resolver.Compilation.FindType(KnownTypeCode.String); } } if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, this.Emitter)) || this.IsExternalCast(itype)) { if (expression is ParenthesizedExpression) { expression = ((ParenthesizedExpression)expression).Expression; } expression.AcceptVisitor(this.Emitter); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Kind == TypeKind.Enum) { var enumMode = Helpers.EnumEmitMode(expressionrr.Type); if (enumMode >= 3 && enumMode < 7 && Helpers.IsIntegerType(itype, this.Emitter.Resolver)) { throw new EmitterException(this.CastExpression, "Enum underlying type is string and cannot be casted to number"); } } if (method == CS.Ops.CAST && expressionrr.Type.Kind != TypeKind.Enum) { var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter); if (cast_rr is ConstantResolveResult) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)cast_rr).ConstantValue; this.WriteCastValue(value, expectedType); return; } else { var conv_rr = cast_rr as ConversionResolveResult; if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)conv_rr.Input).ConstantValue; this.WriteCastValue(value, expectedType); return; } } } if (method == CS.Ops.IS && castToEnum) { this.Write(JS.Types.Bridge.IS); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); this.Write(", "); this.Write(BridgeTypes.ToJsName(itype, this.Emitter)); this.Write(")"); return; } if (expressionrr.Type.Equals(itype)) { if (method == CS.Ops.IS) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); } expression.AcceptVisitor(this.Emitter); if (method == CS.Ops.IS) { this.Write(")"); } return; } bool isResultNullable = NullableType.IsNullable(typerr.Type); if (castCode != null) { this.EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method); return; } bool isCast = method == CS.Ops.CAST; if (isCast) { if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression)) { expression.AcceptVisitor(this.Emitter); return; } } var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion)) { expression.AcceptVisitor(this.Emitter); return; } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == CS.Ops.CAST || method == CS.Ops.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == CS.Ops.IS) { hasValue = true; method = "hasValue"; } } bool unbox = this.Emitter.Rules.Boxing == BoxingRule.Managed && !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion; if (unbox) { this.Write("System.Nullable.getValue("); } var typeDef = itype.Kind == TypeKind.TypeParameter ? null : this.Emitter.GetTypeDefinition(type, true); if (typeDef != null && method == CS.Ops.IS && itype.Kind != TypeKind.Interface && this.Emitter.Validator.IsObjectLiteral(typeDef) && this.Emitter.Validator.GetObjectCreateMode(typeDef) == 0) { throw new EmitterException(type, $"ObjectLiteral type ({itype.FullName}) with Plain mode cannot be used in 'is' operator. Please define cast logic in Cast attribute or use Constructor mode."); } this.Write(JS.NS.BRIDGE); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); if (!hasValue) { this.WriteComma(); this.EmitCastType(itype); } if (isResultNullable && method != CS.Ops.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); if (unbox) { this.Write(")"); } }
protected void VisitBinaryOperatorExpression() { BinaryOperatorExpression binaryOperatorExpression = this.BinaryOperatorExpression; var resolveOperator = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression, this.Emitter); var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver); bool isDecimal = Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver); bool isLongExpected = Helpers.Is64Type(expectedType, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; var leftResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Left, this.Emitter); var rightResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Right, this.Emitter); var charToString = -1; string variable = null; bool leftIsNull = this.BinaryOperatorExpression.Left is NullReferenceExpression; bool rightIsNull = this.BinaryOperatorExpression.Right is NullReferenceExpression; bool isUint = resolveOperator.Type.IsKnownType(KnownTypeCode.UInt16) || resolveOperator.Type.IsKnownType(KnownTypeCode.UInt32) || resolveOperator.Type.IsKnownType(KnownTypeCode.UInt64); if ((leftIsNull || rightIsNull) && (binaryOperatorExpression.Operator == BinaryOperatorType.Equality || binaryOperatorExpression.Operator == BinaryOperatorType.InEquality)) { if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) { this.Write("!"); } this.Write("Bridge.hasValue"); this.WriteOpenParentheses(); if (leftIsNull) { binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); } else { binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); } this.WriteCloseParentheses(); return; } if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String)) { for (int i = 0; i < orr.Operands.Count; i++) { var crr = orr.Operands[i] as ConversionResolveResult; if (crr != null && crr.Input.Type.IsKnownType(KnownTypeCode.Char)) { charToString = i; } } } if (resolveOperator is ConstantResolveResult) { this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue); return; } if (!((expectedType.IsKnownType(KnownTypeCode.String) || resolveOperator.Type.IsKnownType(KnownTypeCode.String)) && binaryOperatorExpression.Operator == BinaryOperatorType.Add) && (Helpers.IsDecimalType(leftResolverResult.Type, this.Emitter.Resolver) || Helpers.IsDecimalType(rightResolverResult.Type, this.Emitter.Resolver))) { isDecimal = true; isDecimalExpected = true; } if (isDecimal && isDecimalExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing) { this.HandleDecimal(resolveOperator); return; } var isFloatResult = Helpers.IsFloatType(resolveOperator.Type, this.Emitter.Resolver); var leftExpected = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left); var rightExpected = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right); var isLeftLong = Helpers.Is64Type(leftExpected, this.Emitter.Resolver); var isRightLong = Helpers.Is64Type(rightExpected, this.Emitter.Resolver); if (!((expectedType.IsKnownType(KnownTypeCode.String) || resolveOperator.Type.IsKnownType(KnownTypeCode.String)) && binaryOperatorExpression.Operator == BinaryOperatorType.Add) && (isLeftLong || isRightLong)) { isLong = true; isLongExpected = true; } if (isLong && isLongExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing) { if (!isFloatResult || binaryOperatorExpression.Operator == BinaryOperatorType.Divide && isLeftLong) { this.HandleLong(resolveOperator, isUint); return; } } var delegateOperator = false; if (this.ResolveOperator(binaryOperatorExpression, orr)) { return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Divide && !(this.Emitter.IsJavaScriptOverflowMode && !ConversionBlock.InsideOverflowContext(this.Emitter, binaryOperatorExpression)) && ( (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) || (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) && Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver)) )) { this.Write("Bridge.Int.div("); binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); this.Write(", "); binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); this.Write(")"); return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Add || binaryOperatorExpression.Operator == BinaryOperatorType.Subtract) { var add = binaryOperatorExpression.Operator == BinaryOperatorType.Add; if (this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult) && this.Emitter.Validator.IsDelegateOrLambda(rightResolverResult)) { delegateOperator = true; this.Write(Bridge.Translator.Emitter.ROOT + "." + (add ? Bridge.Translator.Emitter.DELEGATE_COMBINE : Bridge.Translator.Emitter.DELEGATE_REMOVE)); this.WriteOpenParentheses(); } } bool nullable = orr != null && orr.IsLiftedOperator; bool isCoalescing = binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing; string root = Bridge.Translator.Emitter.ROOT + ".Nullable."; bool special = nullable; bool rootSpecial = nullable; bool isBool = NullableType.IsNullable(resolveOperator.Type) ? NullableType.GetUnderlyingType(resolveOperator.Type).IsKnownType(KnownTypeCode.Boolean) : resolveOperator.Type.IsKnownType(KnownTypeCode.Boolean); bool toBool = isBool && !rootSpecial && !delegateOperator && (binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseAnd || binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseOr); if (rootSpecial) { this.Write(root); } else { if (isCoalescing) { this.Write("("); variable = this.GetTempVarName(); this.Write(variable); this.Write(" = "); } else if (charToString == 0) { this.Write("String.fromCharCode("); } if (toBool) { this.Write("!!("); } binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); if (isCoalescing) { this.Write(", Bridge.hasValue("); this.Write(variable); this.Write(") ? "); this.Write(variable); } else if (charToString == 0) { this.Write(")"); } } if (!delegateOperator) { if (!special) { this.WriteSpace(); } switch (binaryOperatorExpression.Operator) { case BinaryOperatorType.Add: this.Write(rootSpecial ? "add" : "+"); break; case BinaryOperatorType.BitwiseAnd: if (isBool) { this.Write(rootSpecial ? "and" : "&"); } else { this.Write(rootSpecial ? "band" : "&"); } break; case BinaryOperatorType.BitwiseOr: if (isBool) { this.Write(rootSpecial ? "or" : "|"); } else { this.Write(rootSpecial ? "bor" : "|"); } break; case BinaryOperatorType.ConditionalAnd: this.Write(rootSpecial ? "and" : "&&"); break; case BinaryOperatorType.NullCoalescing: this.Write(":"); break; case BinaryOperatorType.ConditionalOr: this.Write(rootSpecial ? "or" : "||"); break; case BinaryOperatorType.Divide: this.Write(rootSpecial ? "div" : "/"); break; case BinaryOperatorType.Equality: this.Write(rootSpecial ? "eq" : "==="); break; case BinaryOperatorType.ExclusiveOr: this.Write(rootSpecial ? "xor" : "^"); break; case BinaryOperatorType.GreaterThan: this.Write(rootSpecial ? "gt" : ">"); break; case BinaryOperatorType.GreaterThanOrEqual: this.Write(rootSpecial ? "gte" : ">="); break; case BinaryOperatorType.InEquality: this.Write(rootSpecial ? "neq" : "!=="); break; case BinaryOperatorType.LessThan: this.Write(rootSpecial ? "lt" : "<"); break; case BinaryOperatorType.LessThanOrEqual: this.Write(rootSpecial ? "lte" : "<="); break; case BinaryOperatorType.Modulus: this.Write(rootSpecial ? "mod" : "%"); break; case BinaryOperatorType.Multiply: this.Write(rootSpecial ? "mul" : "*"); break; case BinaryOperatorType.ShiftLeft: this.Write(rootSpecial ? "sl" : "<<"); break; case BinaryOperatorType.ShiftRight: if (isUint) { this.Write(rootSpecial ? "srr" : ">>>"); } else { this.Write(rootSpecial ? "sr" : ">>"); } break; case BinaryOperatorType.Subtract: this.Write(rootSpecial ? "sub" : "-"); break; default: throw new EmitterException(binaryOperatorExpression, "Unsupported binary operator: " + binaryOperatorExpression.Operator.ToString()); } } else { this.WriteComma(); } if (special) { this.WriteOpenParentheses(); if (charToString == 0) { this.Write("String.fromCharCode("); } binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); if (charToString == 0) { this.Write(")"); } this.WriteComma(); } else { this.WriteSpace(); } if (charToString == 1) { this.Write("String.fromCharCode("); } binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); if (toBool) { this.WriteCloseParentheses(); } if (charToString == 1 || isCoalescing) { this.WriteCloseParentheses(); } if (delegateOperator || special) { this.WriteCloseParentheses(); } }
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 void AddOveflowFlag(KnownTypeCode typeCode, string op_name) { if ((typeCode == KnownTypeCode.Int64 || typeCode == KnownTypeCode.UInt64) && ConversionBlock.IsInCheckedContext(this.Emitter, this.BinaryOperatorExpression)) { if (op_name == "add" || op_name == "sub" || op_name == "mul") { this.Write(", 1"); } } }
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; }
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); }
private void AddOveflowFlag(KnownTypeCode typeCode, string op_name, bool lifted) { if ((typeCode == KnownTypeCode.Int64 || typeCode == KnownTypeCode.UInt64) && ConversionBlock.IsInCheckedContext(this.Emitter, this.UnaryOperatorExpression)) { if (op_name == JS.Funcs.Math.NEG || op_name == JS.Funcs.Math.DEC || op_name == JS.Funcs.Math.INC) { if (lifted) { this.Write(", "); } this.Write("1"); } } }
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); }
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 += ")"; } }
private static bool CheckDecimalConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion) { return(CheckTypeConversion(block, expression, rr, expectedType, conversion, "Bridge.Decimal", Helpers.IsDecimalType)); }
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 bool IsLongConversion(ConversionBlock block, Expression expression, ResolveResult rr, IType expectedType, Conversion conversion) { return(IsTypeConversion(block, expression, rr, expectedType, conversion, "Bridge.Long", Helpers.IsLongType) || IsTypeConversion(block, expression, rr, expectedType, conversion, "Bridge.ULong", Helpers.IsULongType)); }
public static void CheckInteger(ConversionBlock block, Expression expression, IType type) { NarrowingNumericOrEnumerationConversion(block, expression, NullableType.IsNullable(type) ? NullableType.GetUnderlyingType(type) : type, false, true, NullableType.IsNullable(type)); }
private static bool IsTypeConversion(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); } } 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); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } 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); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } 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); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } 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); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } 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)) { if (expression.IsNull) { return(false); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } 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); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } 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); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } 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 && isType(elementType, block.Emitter.Resolver) && !isType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } 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)) { if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } 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); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(false); } return(true); } } return(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); }
protected void VisitBinaryOperatorExpression() { BinaryOperatorExpression binaryOperatorExpression = this.BinaryOperatorExpression; if (this.Emitter.IsAsync && ( binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseAnd || binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseOr || binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalOr || binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalAnd ) && this.GetAwaiters(binaryOperatorExpression).Length > 0) { if (this.Emitter.AsyncBlock.WrittenAwaitExpressions.Contains(binaryOperatorExpression)) { var index = System.Array.IndexOf(this.Emitter.AsyncBlock.AwaitExpressions, binaryOperatorExpression) + 1; this.Write(JS.Vars.ASYNC_TASK_RESULT + index); } else { var index = System.Array.IndexOf(this.Emitter.AsyncBlock.AwaitExpressions, binaryOperatorExpression) + 1; this.WriteAsyncBinaryExpression(index); } return; } var resolveOperator = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression, this.Emitter); var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver); bool isDecimal = Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver); bool isLongExpected = Helpers.Is64Type(expectedType, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; var leftResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Left, this.Emitter); var rightResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Right, this.Emitter); var charToString = -1; string variable = null; bool leftIsNull = this.BinaryOperatorExpression.Left is NullReferenceExpression; bool rightIsNull = this.BinaryOperatorExpression.Right is NullReferenceExpression; bool isUint = resolveOperator.Type.IsKnownType(KnownTypeCode.UInt16) || resolveOperator.Type.IsKnownType(KnownTypeCode.UInt32) || resolveOperator.Type.IsKnownType(KnownTypeCode.UInt64); var isFloatResult = Helpers.IsFloatType(resolveOperator.Type, this.Emitter.Resolver); var leftExpected = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left); var rightExpected = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right); var strictNullChecks = this.Emitter.AssemblyInfo.StrictNullChecks; if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String)) { for (int i = 0; i < orr.Operands.Count; i++) { var crr = orr.Operands[i] as ConversionResolveResult; if (crr != null && crr.Input.Type.IsKnownType(KnownTypeCode.Char)) { charToString = i; } } } if (resolveOperator is ConstantResolveResult) { this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue); return; } var resultIsString = expectedType.IsKnownType(KnownTypeCode.String) || resolveOperator.Type.IsKnownType(KnownTypeCode.String); var isStringConcat = resultIsString && binaryOperatorExpression.Operator == BinaryOperatorType.Add; var toStringForLeft = false; var toStringForRight = false; var parentBinary = binaryOperatorExpression.Parent as BinaryOperatorExpression; bool parentIsString = resultIsString && parentBinary != null && parentBinary.Operator == BinaryOperatorType.Add; if (parentIsString) { var parentResolveOperator = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Parent, this.Emitter) as OperatorResolveResult; if (parentResolveOperator != null && parentResolveOperator.UserDefinedOperatorMethod != null || BinaryOperatorBlock.IsOperatorSimple(parentBinary, this.Emitter)) { parentIsString = false; } } bool isSimpleConcat = isStringConcat && BinaryOperatorBlock.IsOperatorSimple(binaryOperatorExpression, this.Emitter); if (charToString == -1 && isStringConcat && !leftResolverResult.Type.IsKnownType(KnownTypeCode.String)) { toStringForLeft = true; } if (charToString == -1 && isStringConcat && !rightResolverResult.Type.IsKnownType(KnownTypeCode.String)) { toStringForRight = true; } if (!isStringConcat && (Helpers.IsDecimalType(leftResolverResult.Type, this.Emitter.Resolver) || Helpers.IsDecimalType(rightResolverResult.Type, this.Emitter.Resolver))) { isDecimal = true; isDecimalExpected = true; } if (isDecimal && isDecimalExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing) { this.HandleDecimal(resolveOperator); return; } var isLeftLong = Helpers.Is64Type(leftExpected, this.Emitter.Resolver); var isRightLong = Helpers.Is64Type(rightExpected, this.Emitter.Resolver); if (!isLeftLong && !isRightLong) { if (leftExpected.Kind == TypeKind.Enum && Helpers.Is64Type(leftExpected.GetDefinition().EnumUnderlyingType, this.Emitter.Resolver)) { isLeftLong = true; } if (rightExpected.Kind == TypeKind.Enum && Helpers.Is64Type(rightExpected.GetDefinition().EnumUnderlyingType, this.Emitter.Resolver)) { isRightLong = true; } } if (!(resultIsString && binaryOperatorExpression.Operator == BinaryOperatorType.Add) && (isLeftLong || isRightLong)) { isLong = true; isLongExpected = true; } if (isLong && isLongExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing) { if (!isFloatResult || binaryOperatorExpression.Operator == BinaryOperatorType.Divide && isLeftLong) { this.HandleLong(resolveOperator, isUint); return; } } var delegateOperator = false; if (this.ResolveOperator(binaryOperatorExpression, orr)) { return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality || binaryOperatorExpression.Operator == BinaryOperatorType.InEquality) { if (leftIsNull || rightIsNull) { this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult); if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) { this.Write(strictNullChecks ? " === " : " == "); } else { this.Write(strictNullChecks ? " !== " : " != "); } this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult); return; } } var insideOverflowContext = ConversionBlock.InsideOverflowContext(this.Emitter, binaryOperatorExpression); if (binaryOperatorExpression.Operator == BinaryOperatorType.Divide && this.Emitter.Rules.Integer == IntegerRule.Managed && !(this.Emitter.IsJavaScriptOverflowMode && !insideOverflowContext) && ( (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) || (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) && Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver)) )) { this.Write(JS.Types.BRIDGE_INT + "." + JS.Funcs.Math.DIV + "("); this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult); this.Write(", "); this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult); this.Write(")"); return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Multiply && this.Emitter.Rules.Integer == IntegerRule.Managed && !(this.Emitter.IsJavaScriptOverflowMode && !insideOverflowContext) && ( (Helpers.IsInteger32Type(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsInteger32Type(rightResolverResult.Type, this.Emitter.Resolver) && Helpers.IsInteger32Type(resolveOperator.Type, this.Emitter.Resolver)) || (Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) && Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver) && Helpers.IsInteger32Type(resolveOperator.Type, this.Emitter.Resolver)) )) { isUint = NullableType.GetUnderlyingType(resolveOperator.Type).IsKnownType(KnownTypeCode.UInt32); this.Write(JS.Types.BRIDGE_INT + "." + (isUint ? JS.Funcs.Math.UMUL : JS.Funcs.Math.MUL) + "("); this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult); this.Write(", "); this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult); if (ConversionBlock.IsInCheckedContext(this.Emitter, this.BinaryOperatorExpression)) { this.Write(", 1"); } this.Write(")"); return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Add || binaryOperatorExpression.Operator == BinaryOperatorType.Subtract) { var add = binaryOperatorExpression.Operator == BinaryOperatorType.Add; if (expectedType.Kind == TypeKind.Delegate || this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult) && this.Emitter.Validator.IsDelegateOrLambda(rightResolverResult)) { delegateOperator = true; this.Write(add ? JS.Funcs.BRIDGE_COMBINE : JS.Funcs.BRIDGE_REMOVE); this.WriteOpenParentheses(); } } this.NullStringCheck = isStringConcat && !parentIsString && isSimpleConcat; if (isStringConcat && !parentIsString && !isSimpleConcat) { this.Write(JS.Types.System.String.CONCAT); this.WriteOpenParentheses(); } bool nullable = orr != null && orr.IsLiftedOperator; bool isCoalescing = (this.Emitter.AssemblyInfo.StrictNullChecks || NullableType.IsNullable(leftResolverResult.Type) || leftResolverResult.Type.IsKnownType(KnownTypeCode.String) || leftResolverResult.Type.IsKnownType(KnownTypeCode.Object) ) && binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing; string root = JS.Types.SYSTEM_NULLABLE + "."; bool special = nullable; bool rootSpecial = nullable; bool isBool = NullableType.IsNullable(resolveOperator.Type) ? NullableType.GetUnderlyingType(resolveOperator.Type).IsKnownType(KnownTypeCode.Boolean) : resolveOperator.Type.IsKnownType(KnownTypeCode.Boolean); bool toBool = isBool && !rootSpecial && !delegateOperator && (binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseAnd || binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseOr); bool isRefEquals = !isCoalescing && !strictNullChecks && (binaryOperatorExpression.Operator == BinaryOperatorType.InEquality || binaryOperatorExpression.Operator == BinaryOperatorType.Equality) && leftExpected.IsReferenceType.HasValue && leftExpected.IsReferenceType.Value && rightExpected.IsReferenceType.HasValue && rightExpected.IsReferenceType.Value; if (rootSpecial) { this.Write(root); } else if (!isRefEquals) { if (isCoalescing) { this.Write("("); variable = this.GetTempVarName(); this.Write(variable); this.Write(" = "); } else if (charToString == 0) { this.Write(JS.Funcs.STRING_FROMCHARCODE + "("); } if (toBool) { this.Write("!!("); } this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult, isCoalescing); if (isCoalescing) { this.Write(", "); this.Write(variable); this.Write(strictNullChecks ? " !== null" : " != null"); this.Write(" ? "); ConversionBlock.expressionMap.Add(binaryOperatorExpression.Left, variable); //this.Write(variable); binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); ConversionBlock.expressionMap.Remove(binaryOperatorExpression.Left); } else if (charToString == 0) { this.Write(")"); } } if (isRefEquals) { if (binaryOperatorExpression.Operator == BinaryOperatorType.InEquality) { this.Write("!"); } this.Write(JS.Funcs.BRIDGE_REFERENCEEQUALS); special = true; } if (!delegateOperator && (!isStringConcat || isSimpleConcat)) { if (!special) { this.WriteSpace(); } switch (binaryOperatorExpression.Operator) { case BinaryOperatorType.Add: this.Write(rootSpecial ? JS.Funcs.Math.ADD : "+"); break; case BinaryOperatorType.BitwiseAnd: if (isBool) { this.Write(rootSpecial ? JS.Funcs.Math.AND : "&"); } else { this.Write(rootSpecial ? JS.Funcs.Math.BAND : "&"); } break; case BinaryOperatorType.BitwiseOr: if (isBool) { this.Write(rootSpecial ? JS.Funcs.Math.OR : "|"); } else { this.Write(rootSpecial ? JS.Funcs.Math.BOR : "|"); } break; case BinaryOperatorType.ConditionalAnd: this.Write(rootSpecial ? JS.Funcs.Math.AND : "&&"); break; case BinaryOperatorType.NullCoalescing: this.Write(isCoalescing ? ":" : "||"); break; case BinaryOperatorType.ConditionalOr: this.Write(rootSpecial ? JS.Funcs.Math.OR : "||"); break; case BinaryOperatorType.Divide: this.Write(rootSpecial ? JS.Funcs.Math.DIV : "/"); break; case BinaryOperatorType.Equality: if (!isRefEquals) { this.Write(rootSpecial ? "eq" : "==="); } break; case BinaryOperatorType.ExclusiveOr: this.Write(rootSpecial ? JS.Funcs.Math.XOR : "^"); break; case BinaryOperatorType.GreaterThan: this.Write(rootSpecial ? JS.Funcs.Math.GT : ">"); break; case BinaryOperatorType.GreaterThanOrEqual: this.Write(rootSpecial ? JS.Funcs.Math.GTE : ">="); break; case BinaryOperatorType.InEquality: if (!isRefEquals) { this.Write(rootSpecial ? "neq" : "!=="); } break; case BinaryOperatorType.LessThan: this.Write(rootSpecial ? JS.Funcs.Math.LT : "<"); break; case BinaryOperatorType.LessThanOrEqual: this.Write(rootSpecial ? JS.Funcs.Math.LTE : "<="); break; case BinaryOperatorType.Modulus: this.Write(rootSpecial ? JS.Funcs.Math.MOD : "%"); break; case BinaryOperatorType.Multiply: this.Write(rootSpecial ? JS.Funcs.Math.MUL : "*"); break; case BinaryOperatorType.ShiftLeft: this.Write(rootSpecial ? JS.Funcs.Math.SL : "<<"); break; case BinaryOperatorType.ShiftRight: if (isUint) { this.Write(rootSpecial ? JS.Funcs.Math.SRR : ">>>"); } else { this.Write(rootSpecial ? JS.Funcs.Math.SR : ">>"); } break; case BinaryOperatorType.Subtract: this.Write(rootSpecial ? JS.Funcs.Math.SUB : "-"); break; default: throw new EmitterException(binaryOperatorExpression, "Unsupported binary operator: " + binaryOperatorExpression.Operator.ToString()); } } else { this.WriteComma(); } if (special) { this.WriteOpenParentheses(); if (charToString == 0) { this.Write(JS.Funcs.STRING_FROMCHARCODE + "("); } this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult); if (charToString == 0) { this.Write(")"); } this.WriteComma(); } else if (!delegateOperator && (!isStringConcat || isSimpleConcat)) { this.WriteSpace(); } if (charToString == 1) { this.Write(JS.Funcs.STRING_FROMCHARCODE + "("); } this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult); if (toBool) { this.WriteCloseParentheses(); } if (charToString == 1 || isCoalescing) { this.WriteCloseParentheses(); } if (delegateOperator || special || isStringConcat && !parentIsString && !isSimpleConcat) { this.WriteCloseParentheses(); } }
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 void AddOveflowFlag(KnownTypeCode typeCode, string op_name) { if ((typeCode == KnownTypeCode.Int64 || typeCode == KnownTypeCode.UInt64) && ConversionBlock.IsInCheckedContext(this.Emitter, this.BinaryOperatorExpression)) { if (op_name == JS.Funcs.Math.ADD || op_name == JS.Funcs.Math.SUB || op_name == JS.Funcs.Math.MUL) { this.Write(", 1"); } } }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var itype = this.Emitter.BridgeTypes.ToType(type); bool isCastAttr; string castCode = this.GetCastCode(expression, type, out isCastAttr); if (itype != null && castCode == null && method != CS.Ops.CAST && itype.GetDefinition() != null && this.Emitter.Validator.IsObjectLiteral(itype.GetDefinition())) { throw new EmitterException(expression, "The type " + itype.FullName + " cannot be used in cast operation because there is no way to check its type"); } var enumType = itype; if (NullableType.IsNullable(enumType)) { enumType = NullableType.GetUnderlyingType(enumType); } var castToEnum = enumType.Kind == TypeKind.Enum; if (castToEnum) { itype = enumType.GetDefinition().EnumUnderlyingType; var enumMode = this.Emitter.Validator.EnumEmitMode(enumType); if (enumMode >= 3 && enumMode < 7) { itype = this.Emitter.Resolver.Compilation.FindType(KnownTypeCode.String); } } if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, this.Emitter))) { if (expression is ParenthesizedExpression) { expression = ((ParenthesizedExpression)expression).Expression; } expression.AcceptVisitor(this.Emitter); return; } if (method == CS.Ops.CAST) { var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter); if (cast_rr is ConstantResolveResult) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)cast_rr).ConstantValue; this.WriteCastValue(value, expectedType); return; } else { var conv_rr = cast_rr as ConversionResolveResult; if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)conv_rr.Input).ConstantValue; this.WriteCastValue(value, expectedType); return; } } } if (method == CS.Ops.IS && castToEnum) { this.Write("Bridge.is("); expression.AcceptVisitor(this.Emitter); this.Write(", "); this.Write(BridgeTypes.ToJsName(itype, this.Emitter)); this.Write(")"); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Equals(itype)) { if (method == CS.Ops.IS) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); } expression.AcceptVisitor(this.Emitter); if (method == CS.Ops.IS) { this.Write(")"); } return; } bool isResultNullable = NullableType.IsNullable(typerr.Type); if (castCode != null) { this.EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method); return; } bool isCast = method == CS.Ops.CAST; if (isCast) { if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression)) { expression.AcceptVisitor(this.Emitter); return; } } var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion)) { expression.AcceptVisitor(this.Emitter); return; } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == CS.Ops.CAST || method == CS.Ops.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == CS.Ops.IS) { hasValue = true; method = "hasValue"; } } bool unbox = !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion; if (unbox) { this.Write("System.Nullable.getValue("); } this.Write(JS.NS.BRIDGE); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); if (!hasValue) { this.WriteComma(); this.EmitCastType(itype); } if (isResultNullable && method != CS.Ops.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); if (unbox) { this.Write(")"); } }
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; }