protected JSVariable GetConstructedReference(JSPassByReferenceExpression pbr) { JSVariable referentVariable; JSExpression referent; if (!JSReferenceExpression.TryMaterialize(JSIL, pbr.Referent, out referent)) { // If the reference can be dereferenced, but cannot be materialized, it is // a constructed reference. if (JSReferenceExpression.TryDereference(JSIL, pbr.Referent, out referent)) { referentVariable = referent as JSVariable; // Ignore variables we previously transformed. if ((referentVariable != null) && TransformedVariables.Contains(referentVariable.Identifier)) { return(null); } return(referentVariable); } else { return(null); } } referentVariable = referent as JSVariable; if (referentVariable == null) { return(null); } // Ignore variables we previously transformed. if (TransformedVariables.Contains(referentVariable.Identifier)) { return(null); } // If the variable does not match the one in the dictionary, it is a constructed // reference to a parameter. if (!referentVariable.Equals(Variables[referentVariable.Identifier])) { // If the parameter is a reference, we don't care about it. if (Variables[referentVariable.Identifier].IsReference) { return(null); } else { return(referentVariable); } } return(null); }
public void VisitNode(JSBinaryOperatorExpression boe) { JSExpression left; if (!JSReferenceExpression.TryDereference(JSIL, boe.Left, out left)) { left = boe.Left; } var leftVar = left as JSVariable; var leftChangeType = left as JSChangeTypeExpression; if (leftChangeType != null) { leftVar = leftChangeType.Expression as JSVariable; } if ( !(ParentNode is JSVariableDeclarationStatement) && (leftVar != null) && (leftVar.Identifier == Variable.Identifier) ) { if (boe.Operator is JSAssignmentOperator) { var replacement = new JSWriteThroughReferenceExpression( Variable, boe.Right ); ParentNode.ReplaceChild(boe, replacement); VisitReplacement(replacement); } else { VisitChildren(boe); } } else if (ParentNode is JSVariableDeclarationStatement) { // Don't walk through the left-hand side of variable declarations. VisitChildren( boe, (node, name) => name != "Left" ); } else { VisitChildren(boe); } }
public void VisitNode(JSUnaryOperatorExpression uoe) { JSExpression expr; if (!JSReferenceExpression.TryDereference(JSIL, uoe.Expression, out expr)) { expr = uoe.Expression; } var eVar = expr as JSVariable; var eChangeType = expr as JSChangeTypeExpression; if (eChangeType != null) { eVar = eChangeType.Expression as JSVariable; } var type = uoe.Expression.GetActualType(TypeSystem); if ( (eVar != null) && (eVar.Identifier == Variable.Identifier) && (uoe.Operator is JSUnaryMutationOperator) ) { var newValue = DecomposeMutationOperators.DecomposeUnaryMutation( uoe, () => TemporaryVariable.ForFunction( Stack.Last() as JSFunctionExpression, type ), type, TypeSystem ); var replacement = new JSWriteThroughReferenceExpression( Variable, newValue ); ParentNode.ReplaceChild(uoe, replacement); VisitReplacement(replacement); } else { VisitChildren(uoe); } }
protected JSVariable GetReferentVariable(JSPassByReferenceExpression pbr) { JSVariable referentVariable; JSExpression referent; if (!JSReferenceExpression.TryMaterialize(JSIL, pbr.Referent, out referent)) { if (JSReferenceExpression.TryDereference(JSIL, pbr.Referent, out referent)) { referentVariable = referent as JSVariable; return(referentVariable); } else { return(null); } } referentVariable = referent as JSVariable; return(referentVariable); }
public void VisitNode(JSBinaryOperatorExpression boe) { JSExpression left, right, nestedLeft; if (!JSReferenceExpression.TryDereference(JSIL, boe.Left, out left)) { left = boe.Left; } if (!JSReferenceExpression.TryDereference(JSIL, boe.Right, out right)) { right = boe.Right; } var nestedBoe = right as JSBinaryOperatorExpression; var isAssignment = (boe.Operator == JSOperator.Assignment); var leftNew = left as JSNewExpression; var rightNew = right as JSNewExpression; var leftVar = left as JSVariable; if ( isAssignment && (nestedBoe != null) && (left.IsConstant || (leftVar != null) || left is JSDotExpressionBase) && !(ParentNode is JSVariableDeclarationStatement) ) { JSUnaryOperator prefixOperator; JSAssignmentOperator compoundOperator; if (!JSReferenceExpression.TryDereference(JSIL, nestedBoe.Left, out nestedLeft)) { nestedLeft = nestedBoe.Left; } var rightLiteral = nestedBoe.Right as JSIntegerLiteral; var areEqual = left.Equals(nestedLeft); if ( areEqual && PrefixOperators.TryGetValue(nestedBoe.Operator, out prefixOperator) && (rightLiteral != null) && (rightLiteral.Value == 1) ) { var newUoe = new JSUnaryOperatorExpression( prefixOperator, boe.Left, boe.GetActualType(TypeSystem) ); ParentNode.ReplaceChild(boe, newUoe); VisitReplacement(newUoe); return; } else if ( areEqual && CompoundAssignments.TryGetValue(nestedBoe.Operator, out compoundOperator) ) { var newBoe = new JSBinaryOperatorExpression( compoundOperator, boe.Left, nestedBoe.Right, boe.GetActualType(TypeSystem) ); ParentNode.ReplaceChild(boe, newBoe); VisitReplacement(newBoe); return; } } else if ( isAssignment && (leftNew != null) && (rightNew != null) ) { var rightType = rightNew.Type as JSDotExpressionBase; if ( (rightType != null) && (rightType.Member.Identifier == "CollectionInitializer") ) { var newInitializer = new JSInitializerApplicationExpression( boe.Left, new JSArrayExpression( TypeSystem.Object, rightNew.Arguments.ToArray() ) ); ParentNode.ReplaceChild(boe, newInitializer); VisitReplacement(newInitializer); return; } } else if ( isAssignment && (leftVar != null) && leftVar.IsThis ) { var leftType = leftVar.GetActualType(TypeSystem); if (!TypeUtil.IsStruct(leftType)) { ParentNode.ReplaceChild(boe, new JSUntranslatableExpression(boe)); return; } else { var newInvocation = JSInvocationExpression.InvokeStatic( JSIL.CopyMembers, new[] { boe.Right, leftVar } ); ParentNode.ReplaceChild(boe, newInvocation); VisitReplacement(newInvocation); return; } } VisitChildren(boe); }