Ejemplo n.º 1
0
        public void VisitNode(JSInvocationExpression invocation)
        {
            FunctionAnalysis2ndPass sa = null;

            if (invocation.JSMethod != null)
                sa = FunctionSource.GetSecondPass(invocation.JSMethod);

            var parms = invocation.Parameters.ToArray();

            for (int i = 0, c = parms.Length; i < c; i++) {
                var pd = parms[i].Key;
                var argument = parms[i].Value;

                string parameterName = null;
                if (pd != null)
                    parameterName = pd.Name;

                GenericParameter relevantParameter;
                if (IsParameterCopyNeeded(sa, parameterName, argument, out relevantParameter)) {
                    if (Tracing)
                        Debug.WriteLine(String.Format("struct copy introduced for argument #{0}: {1}", i, argument));

                    invocation.Arguments[i] = MakeCopyForExpression(argument, relevantParameter);
                } else {
                    if (Tracing && TypeUtil.IsStruct(argument.GetActualType(TypeSystem)))
                        Debug.WriteLine(String.Format("struct copy elided for argument #{0}: {1}", i, argument));
                }
            }

            var thisReference = invocation.ThisReference;
            if (
                (thisReference != null) &&
                (sa != null) &&
                sa.ViolatesThisReferenceImmutability &&
                !(ParentNode is JSCommaExpression)
            ) {
                // The method we're calling violates immutability so we need to clone the this-reference
                //  before we call it.
                var thisReferenceType = thisReference.GetActualType(TypeSystem);
                if (TypeUtil.IsStruct(thisReferenceType)) {
                    if (!(thisReference is JSVariable) && !(thisReference is JSFieldAccess))
                        throw new NotImplementedException("Unsupported invocation of method that reassigns this within an immutable struct: " + invocation.ToString());

                    var cloneExpr = new JSBinaryOperatorExpression(
                        JSOperator.Assignment, thisReference, new JSStructCopyExpression(thisReference), thisReferenceType
                    );
                    var commaExpression = new JSCommaExpression(cloneExpr, invocation);

                    ParentNode.ReplaceChild(invocation, commaExpression);
                    VisitReplacement(commaExpression);
                    return;
                }
            }

            VisitChildren(invocation);
        }
        public void VisitNode (JSInvocationExpression invocation) {
            FunctionAnalysis2ndPass sa = null;

            if (invocation.JSMethod != null)
                sa = GetSecondPass(invocation.JSMethod);

            CloneArgumentsIfNecessary(invocation.Parameters, invocation.Arguments, sa);

            var thisReference = invocation.ThisReference;
            if (
                (thisReference != null) && 
                (sa != null) && 
                sa.ViolatesThisReferenceImmutability && 
                !(ParentNode is JSCommaExpression)
            ) {
                // The method we're calling violates immutability so we need to clone the this-reference
                //  before we call it.
                var thisReferenceType = thisReference.GetActualType(TypeSystem);
                if (TypeUtil.IsStruct(thisReferenceType)) {
                    if (!(thisReference is JSVariable) && !(thisReference is JSFieldAccess))
                        throw new NotImplementedException("Unsupported invocation of method that reassigns this within an immutable struct: " + invocation.ToString());

                    var cloneExpr = new JSBinaryOperatorExpression(
                        JSOperator.Assignment, thisReference, new JSStructCopyExpression(thisReference), thisReferenceType
                    );
                    var commaExpression = new JSCommaExpression(cloneExpr, invocation);

                    ParentNode.ReplaceChild(invocation, commaExpression);
                    VisitReplacement(commaExpression);
                    return;
                }
            }

            VisitChildren(invocation);
        }
Ejemplo n.º 3
0
        public void VisitNode(JSInvocationExpression invocation)
        {
            FunctionAnalysis2ndPass sa = null;

            if (invocation.JSMethod != null)
            {
                sa = GetSecondPass(invocation.JSMethod);
            }

            CloneArgumentsIfNecessary(invocation.Parameters, invocation.Arguments, sa);

            var thisReference = invocation.ThisReference;

            if (
                (thisReference != null) &&
                (sa != null) &&
                sa.ViolatesThisReferenceImmutability &&
                !(ParentNode is JSCommaExpression)
                )
            {
                // The method we're calling violates immutability so we need to clone the this-reference
                //  before we call it.
                var thisReferenceType = thisReference.GetActualType(TypeSystem);
                if (TypeUtil.IsStruct(thisReferenceType))
                {
                    if (!(thisReference is JSVariable) && !(thisReference is JSFieldAccess))
                    {
                        throw new NotImplementedException("Unsupported invocation of method that reassigns this within an immutable struct: " + invocation.ToString());
                    }

                    var cloneExpr = new JSBinaryOperatorExpression(
                        JSOperator.Assignment, thisReference, new JSStructCopyExpression(thisReference), thisReferenceType
                        );
                    var commaExpression = new JSCommaExpression(cloneExpr, invocation);

                    ParentNode.ReplaceChild(invocation, commaExpression);
                    VisitReplacement(commaExpression);
                    return;
                }
            }

            VisitChildren(invocation);
        }