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 override AstNode VisitAssignmentExpression(AssignmentExpression assignmentExpression) { var rr = this.Resolver.ResolveNode(assignmentExpression, null); bool found = false; var isInt = Helpers.IsIntegerType(rr.Type, this.Resolver); if (isInt || !(assignmentExpression.Parent is ExpressionStatement)) { found = true; } if (found && !isInt && assignmentExpression.Parent is ICSharpCode.NRefactory.CSharp.LambdaExpression) { var lambdarr = this.Resolver.ResolveNode(assignmentExpression.Parent, null) as LambdaResolveResult; if (lambdarr != null && lambdarr.ReturnType.Kind == TypeKind.Void) { found = false; } } if (assignmentExpression.Operator == AssignmentOperatorType.Add && rr.Type.IsKnownType(KnownTypeCode.String)) { found = true; } if (assignmentExpression.Operator != AssignmentOperatorType.Any && assignmentExpression.Operator != AssignmentOperatorType.Assign && found) { AssignmentExpression clonAssignmentExpression = (AssignmentExpression)base.VisitAssignmentExpression(assignmentExpression); if (clonAssignmentExpression == null) { clonAssignmentExpression = (AssignmentExpression)assignmentExpression.Clone(); } var op = clonAssignmentExpression.Operator; clonAssignmentExpression.Operator = AssignmentOperatorType.Assign; BinaryOperatorType opType; switch (op) { case AssignmentOperatorType.Add: opType = BinaryOperatorType.Add; break; case AssignmentOperatorType.Subtract: opType = BinaryOperatorType.Subtract; break; case AssignmentOperatorType.Multiply: opType = BinaryOperatorType.Multiply; break; case AssignmentOperatorType.Divide: opType = BinaryOperatorType.Divide; break; case AssignmentOperatorType.Modulus: opType = BinaryOperatorType.Modulus; break; case AssignmentOperatorType.ShiftLeft: opType = BinaryOperatorType.ShiftLeft; break; case AssignmentOperatorType.ShiftRight: opType = BinaryOperatorType.ShiftRight; break; case AssignmentOperatorType.BitwiseAnd: opType = BinaryOperatorType.BitwiseAnd; break; case AssignmentOperatorType.BitwiseOr: opType = BinaryOperatorType.BitwiseOr; break; case AssignmentOperatorType.ExclusiveOr: opType = BinaryOperatorType.ExclusiveOr; break; default: throw new ArgumentOutOfRangeException(); } var wrapRightExpression = AssigmentExpressionHelper.CheckIsRightAssigmentExpression(clonAssignmentExpression) ? clonAssignmentExpression.Right.Clone() : new ParenthesizedExpression(clonAssignmentExpression.Right.Clone()); clonAssignmentExpression.Right = new BinaryOperatorExpression( clonAssignmentExpression.Left.Clone(), opType, wrapRightExpression); return(clonAssignmentExpression); } return(base.VisitAssignmentExpression(assignmentExpression)); }
public override AstNode VisitAssignmentExpression(AssignmentExpression assignmentExpression) { var rr = this.Resolver.ResolveNode(assignmentExpression, null); var orr = rr as OperatorResolveResult; var simpleIndex = true; if (orr != null) { var accessrr = orr.Operands[0] as ArrayAccessResolveResult; if (accessrr != null) { foreach (var index in accessrr.Indexes) { var indexMemberTargetrr = index as MemberResolveResult; bool isIndexSimple = (indexMemberTargetrr != null && indexMemberTargetrr.Member is IField && (indexMemberTargetrr.TargetResult is ThisResolveResult || indexMemberTargetrr.TargetResult is LocalResolveResult)) || index is ThisResolveResult || index is LocalResolveResult || index is ConstantResolveResult; if (!isIndexSimple) { simpleIndex = false; } } } } bool found = false; var isInt = Helpers.IsIntegerType(rr.Type, this.Resolver); if (this.Rules.Integer == IntegerRule.Managed && isInt || !(assignmentExpression.Parent is ExpressionStatement)) { found = true; } if (found && !isInt && assignmentExpression.Parent is ICSharpCode.NRefactory.CSharp.LambdaExpression) { var lambdarr = this.Resolver.ResolveNode(assignmentExpression.Parent, null) as LambdaResolveResult; if (lambdarr != null && lambdarr.ReturnType.Kind == TypeKind.Void) { found = false; } } if (assignmentExpression.Operator == AssignmentOperatorType.Add && rr.Type.IsKnownType(KnownTypeCode.String)) { found = true; } if (assignmentExpression.Operator != AssignmentOperatorType.Any && assignmentExpression.Operator != AssignmentOperatorType.Assign && found) { AssignmentExpression clonAssignmentExpression = (AssignmentExpression)base.VisitAssignmentExpression(assignmentExpression); if (clonAssignmentExpression == null) { clonAssignmentExpression = (AssignmentExpression)assignmentExpression.Clone(); } var indexerExpr = clonAssignmentExpression.Left as IndexerExpression; List<Expression> leftIndexerArgs = null; List<Expression> rightIndexerArgs = null; var needReturnValue = false; if (indexerExpr != null && !simpleIndex) { leftIndexerArgs = new List<Expression>(); rightIndexerArgs = new List<Expression>(); foreach (var index in indexerExpr.Arguments) { var expr = new InvocationExpression(new MemberReferenceExpression(new MemberReferenceExpression(new TypeReferenceExpression(new MemberType(new SimpleType("global"), CS.NS.BRIDGE) { IsDoubleColon = true }), "Script"), "ToTemp"), new PrimitiveExpression("idx" + tempKey), index.Clone()); leftIndexerArgs.Add(expr); expr = new InvocationExpression(new MemberReferenceExpression(new MemberReferenceExpression(new TypeReferenceExpression(new MemberType(new SimpleType("global"), CS.NS.BRIDGE) { IsDoubleColon = true }), "Script"), "FromTemp"), new PrimitiveExpression("idx" + tempKey++), index.Clone()); rightIndexerArgs.Add(expr); } needReturnValue = !(assignmentExpression.Parent is ExpressionStatement); if (needReturnValue && assignmentExpression.Parent is LambdaExpression) { var lambdarr = this.Resolver.ResolveNode(assignmentExpression.Parent, null) as LambdaResolveResult; if (lambdarr != null && lambdarr.ReturnType.Kind == TypeKind.Void) { needReturnValue = false; } } clonAssignmentExpression.Left = new IndexerExpression(indexerExpr.Target.Clone(), needReturnValue ? rightIndexerArgs : leftIndexerArgs); } else { indexerExpr = null; } var op = clonAssignmentExpression.Operator; clonAssignmentExpression.Operator = AssignmentOperatorType.Assign; BinaryOperatorType opType; switch (op) { case AssignmentOperatorType.Add: opType = BinaryOperatorType.Add; break; case AssignmentOperatorType.Subtract: opType = BinaryOperatorType.Subtract; break; case AssignmentOperatorType.Multiply: opType = BinaryOperatorType.Multiply; break; case AssignmentOperatorType.Divide: opType = BinaryOperatorType.Divide; break; case AssignmentOperatorType.Modulus: opType = BinaryOperatorType.Modulus; break; case AssignmentOperatorType.ShiftLeft: opType = BinaryOperatorType.ShiftLeft; break; case AssignmentOperatorType.ShiftRight: opType = BinaryOperatorType.ShiftRight; break; case AssignmentOperatorType.BitwiseAnd: opType = BinaryOperatorType.BitwiseAnd; break; case AssignmentOperatorType.BitwiseOr: opType = BinaryOperatorType.BitwiseOr; break; case AssignmentOperatorType.ExclusiveOr: opType = BinaryOperatorType.ExclusiveOr; break; default: throw new ArgumentOutOfRangeException(); } var wrapRightExpression = AssigmentExpressionHelper.CheckIsRightAssigmentExpression(clonAssignmentExpression) ? clonAssignmentExpression.Right.Clone() : new ParenthesizedExpression(clonAssignmentExpression.Right.Clone()); clonAssignmentExpression.Right = new BinaryOperatorExpression( indexerExpr != null ? new IndexerExpression(indexerExpr.Target.Clone(), needReturnValue ? leftIndexerArgs : rightIndexerArgs) : clonAssignmentExpression.Left.Clone(), opType, wrapRightExpression); return clonAssignmentExpression; } return base.VisitAssignmentExpression(assignmentExpression); }