public void VisitNode(JSNewExpression newexp)
        {
            var type = newexp.GetActualType(TypeSystem);

            var isStruct         = TypeUtil.IsStruct(type);
            var isInsideLoop     = (Stack.Any((node) => node is JSLoopStatement));
            var parentInvocation = ParentNode as JSInvocationExpression;
            var doesValueEscape  = DoesValueEscapeFromInvocation(parentInvocation, newexp, false);

            if (isStruct &&
                isInsideLoop &&
                (parentInvocation != null) &&
                !doesValueEscape
                )
            {
                var replacement = CreateHoistedVariable(
                    (hoistedVariable) => new JSCommaExpression(
                        JSInvocationExpression.InvokeMethod(
                            type, new JSMethod(newexp.ConstructorReference, newexp.Constructor, MethodTypes, null), hoistedVariable,
                            newexp.Arguments.ToArray(), false
                            ),
                        hoistedVariable
                        ),
                    type
                    );

                ParentNode.ReplaceChild(newexp, replacement);
                VisitReplacement(replacement);
            }
            else
            {
                VisitChildren(newexp);
            }
        }
예제 #2
0
        private JSStatement FoldInvocation(JSInvocationExpression invocation, InitializationInfo ii)
        {
            var arguments     = invocation.Arguments.ToArray();
            var newExpression = new JSNewExpression(
                ii.Type, invocation.JSMethod.Reference, invocation.JSMethod.Method, arguments
                );

            // Constructor call contains a reference to the struct being initialized.
            // For some reason the C# compiler lets you do this even though it would be undefined
            //  if not for a nuance in how struct locals work in MSIL.
            if (newExpression.SelfAndChildrenRecursive.Any((n) => n.Equals(invocation.ThisReference)))
            {
                return(null);
            }

            ii.Folded = true;
            ii.BinaryExpressionParent.ReplaceChild(ii.ParentBinaryExpression, new JSNullExpression());

            var newBoe = new JSBinaryOperatorExpression(
                JSOperator.Assignment,
                ii.ParentBinaryExpression.Left, newExpression,
                ii.ParentBinaryExpression.ActualType
                );

            return(new JSVariableDeclarationStatement(newBoe));
        }
예제 #3
0
        public void VisitNode(JSNewExpression ne)
        {
            var expectedType = ne.GetActualType(TypeSystem);

            if (
                IsNullable(expectedType)
                )
            {
                if (ne.Arguments.Count == 0)
                {
                    ParentNode.ReplaceChild(
                        ne, JSLiteral.Null(expectedType)
                        );
                }
                else
                {
                    ParentNode.ReplaceChild(
                        ne, ne.Arguments[0]
                        );
                    VisitReplacement(ne.Arguments[0]);
                }
            }
            else
            {
                VisitChildren(ne);
            }
        }
예제 #4
0
        public void VisitNode(JSNewExpression newexp)
        {
            var type = newexp.GetActualType(TypeSystem);

            var isStruct = TypeUtil.IsStruct(type);
            var isInsideLoop = (Stack.Any((node) => node is JSLoopStatement));
            var parentInvocation = ParentNode as JSInvocationExpression;

            var doesValueEscape = true;
            if (
                isStruct &&
                (parentInvocation != null) &&
                (parentInvocation.JSMethod != null) &&
                (parentInvocation.JSMethod.Reference != null)
            ) {
                var methodDef = parentInvocation.JSMethod.Reference.Resolve();
                var secondPass = FunctionSource.GetSecondPass(parentInvocation.JSMethod, Function.Method.QualifiedIdentifier);
                if ((secondPass != null) && (methodDef != null)) {
                    // HACK
                    var argumentIndex = parentInvocation.Arguments.Select(
                        (a, i) => new { argument = a, index = i })
                        .FirstOrDefault((_) => _.argument.SelfAndChildrenRecursive.Contains(newexp));

                    if (argumentIndex != null) {
                        var argumentName = methodDef.Parameters[argumentIndex.index].Name;

                        doesValueEscape = secondPass.EscapingVariables.Contains(argumentName);
                    }
                }
            }

            if (isStruct &&
                isInsideLoop &&
                (parentInvocation != null) &&
                !doesValueEscape
            ) {
                string id;
                var hoistedVariable = MakeTemporaryVariable(type, out id);
                var constructorInvocation = JSInvocationExpression.InvokeMethod(
                    type, new JSMethod(newexp.ConstructorReference, newexp.Constructor, MethodTypes, null), hoistedVariable, newexp.Arguments.ToArray(), false
                );
                var replacement = new JSCommaExpression(
                    constructorInvocation, hoistedVariable
                );

                ToDeclare.Add(new PendingDeclaration(id, type, hoistedVariable));

                ParentNode.ReplaceChild(newexp, replacement);
                VisitReplacement(replacement);
            } else {
                VisitChildren(newexp);
            }
        }
예제 #5
0
        private JSStatement ConvertInvocationIntoReassignment(JSInvocationExpression invocation, InitializationInfo ii)
        {
            var arguments     = invocation.Arguments.ToArray();
            var newExpression = new JSNewExpression(
                ii.Type, invocation.JSMethod.Reference, invocation.JSMethod.Method, arguments
                );
            var newBoe = new JSBinaryOperatorExpression(
                JSOperator.Assignment,
                ii.ParentBinaryExpression.Left, newExpression,
                ii.ParentBinaryExpression.ActualType
                );

            return(new JSExpressionStatement(newBoe));
        }
예제 #6
0
        public void VisitNode(JSNewExpression newexp)
        {
            if ((newexp.ConstructorReference != null) && (newexp.Constructor != null))
            {
                var jsm       = new JSMethod(newexp.ConstructorReference, newexp.Constructor, FunctionSource.MethodTypes);
                var variables = ExtractAffectedVariables(jsm, newexp.Parameters);

                State.Invocations.Add(new FunctionAnalysis1stPass.Invocation(
                                          GetParentNodeIndices(), StatementIndex, NodeIndex, (JSVariable)null, jsm, newexp.ConstructorReference, variables
                                          ));
            }

            VisitChildren(newexp);
        }
예제 #7
0
        public void VisitNode(JSNewExpression newexp)
        {
            FunctionAnalysis2ndPass sa = null;

            if (newexp.Constructor != null)
            {
                // HACK
                sa = GetSecondPass(new JSMethod(newexp.ConstructorReference, newexp.Constructor, MethodTypes));
            }

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

            VisitChildren(newexp);
        }
        public void VisitNode (JSNewExpression ne) {
            var parentBoe = ParentNode as JSBinaryOperatorExpression;

            var thisReferenceType = ne.GetActualType(TypeSystem);
            if (TypeUtil.IsStruct(thisReferenceType) && (parentBoe != null))
                Initializations.Add(new InitializationInfo {
                    Type = thisReferenceType,
                    NewExpression = ne,
                    ParentBinaryExpression = parentBoe,
                    BinaryExpressionParent = Stack.Skip(2).First()
                });

            VisitChildren(ne);
        }
예제 #9
0
        public void VisitNode(JSNewExpression ne)
        {
            var parentBoe = ParentNode as JSBinaryOperatorExpression;

            var thisReferenceType = ne.GetActualType(TypeSystem);

            if (TypeUtil.IsStruct(thisReferenceType) && (parentBoe != null))
            {
                Initializations.Add(new InitializationInfo {
                    Type                   = thisReferenceType,
                    NewExpression          = ne,
                    ParentBinaryExpression = parentBoe,
                    BinaryExpressionParent = Stack.Skip(2).First()
                });
            }

            VisitChildren(ne);
        }
예제 #10
0
        public void VisitNode(JSNewExpression newexp)
        {
            var ctor         = newexp.Constructor;
            var isOverloaded = (ctor != null) &&
                               ctor.IsOverloadedRecursive &&
                               !ctor.Metadata.HasAttribute("JSIL.Meta.JSRuntimeDispatch");

            // New improved ConstructorSignature.Construct is faster than fast overload dispatch! :)

            /*
             * if (isOverloaded && JavascriptAstEmitter.CanUseFastOverloadDispatch(ctor))
             *  isOverloaded = false;
             */

            if (isOverloaded)
            {
                CacheSignature(newexp.ConstructorReference, ctor.Signature, true);
            }

            VisitChildren(newexp);
        }
예제 #11
0
        private List <JSStatement> GetPrototype(CilType type)
        {
            var baseType = type.ReflectionType.BaseType;

            var shouldHaveBasePrototype =
                baseType != null &&
                baseType.FullName != "System.MulticastDelegate" &&
                baseType.FullName != "System.ValueType";

            JSExpression basePrototype;
            var          body = new List <JSStatement>();

            if (shouldHaveBasePrototype)
            {
                basePrototype = new JSNewExpression
                {
                    Constructor = GetTypeIdentifier(baseType, typeScope: type.ReflectionType)
                };

                if (baseType.IsGenericType)
                {
                    body.AddRange(baseType
                                  .GetGenericArguments()
                                  .Where(g => g.IsGenericParameter == false)
                                  .Select(g => GetTypeIdentifier(g, typeScope: type.ReflectionType))
                                  .Select(g => JSFactory.Call(JSFactory.Identifier(g, "init")).ToStatement()));
                }
            }
            else
            {
                basePrototype = new JSObjectLiteral();
            }

            body.Add(new JSReturnExpression {
                Expression = basePrototype
            }.ToStatement());
            return(body);
        }
예제 #12
0
 public void VisitNode (JSNewExpression ne) {
     var expectedType = ne.GetActualType(TypeSystem);
     if (
         IsNullable(expectedType)
     ) {
         if (ne.Arguments.Count == 0) {
             ParentNode.ReplaceChild(
                 ne, JSLiteral.Null(expectedType)
             );
         } else {
             ParentNode.ReplaceChild(
                 ne, ne.Arguments[0]
             );
             VisitReplacement(ne.Arguments[0]);
         }
     } else {
         VisitChildren(ne);
     }
 }
예제 #13
0
        public void VisitNode (JSNewExpression newexp) {
            var type = newexp.GetActualType(TypeSystem);

            var isStruct = TypeUtil.IsStruct(type);
            var isInsideLoop = (Stack.Any((node) => node is JSLoopStatement));
            var parentInvocation = ParentNode as JSInvocationExpression;
            var doesValueEscape = DoesValueEscapeFromInvocation(parentInvocation, newexp, false);

            if (isStruct && 
                isInsideLoop && 
                (parentInvocation != null) &&
                !doesValueEscape
            ) {
                var replacement = CreateHoistedVariable(
                    (hoistedVariable) => new JSCommaExpression(
                        JSInvocationExpression.InvokeMethod(
                            type, new JSMethod(newexp.ConstructorReference, newexp.Constructor, MethodTypes, null), hoistedVariable,
                            newexp.Arguments.ToArray(), false
                        ), 
                        hoistedVariable
                    ),
                    type
                );

                ParentNode.ReplaceChild(newexp, replacement);
                VisitReplacement(replacement);
            } else {
                VisitChildren(newexp);
            }
        }
        private JSStatement ConvertInvocationIntoReassignment (JSInvocationExpression invocation, InitializationInfo ii) {
            var arguments = invocation.Arguments.ToArray();
            var newExpression = new JSNewExpression(
                ii.Type, invocation.JSMethod.Reference, invocation.JSMethod.Method, arguments
            );
            var newBoe = new JSBinaryOperatorExpression(
                JSOperator.Assignment, 
                ii.ParentBinaryExpression.Left, newExpression, 
                ii.ParentBinaryExpression.ActualType
            );

            return new JSExpressionStatement(newBoe);
        }
        private JSStatement FoldInvocation(JSInvocationExpression invocation, InitializationInfo ii)
        {
            var arguments = invocation.Arguments.ToArray();
            var newExpression = new JSNewExpression(
                ii.Type, invocation.JSMethod.Reference, invocation.JSMethod.Method, arguments
            );

            ii.BinaryExpressionParent.ReplaceChild(ii.ParentBinaryExpression, new JSNullExpression());
            Initializations.Remove(ii);

            var newBoe = new JSBinaryOperatorExpression(
                JSOperator.Assignment,
                ii.ParentBinaryExpression.Left, newExpression,
                ii.ParentBinaryExpression.ActualType
            );

            return new JSVariableDeclarationStatement(newBoe);
        }
        public void VisitNode (JSNewExpression newexp) {
            FunctionAnalysis2ndPass sa = null;

            if (newexp.Constructor != null)
                // HACK
                sa = GetSecondPass(new JSMethod(newexp.ConstructorReference, newexp.Constructor, MethodTypes));

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

            VisitChildren(newexp);
        }
        private JSStatement FoldInvocation (JSInvocationExpression invocation, InitializationInfo ii) {
            var arguments = invocation.Arguments.ToArray();
            var newExpression = new JSNewExpression(
                ii.Type, invocation.JSMethod.Reference, invocation.JSMethod.Method, arguments
            );

            // Constructor call contains a reference to the struct being initialized.
            // For some reason the C# compiler lets you do this even though it would be undefined
            //  if not for a nuance in how struct locals work in MSIL.
            if (newExpression.SelfAndChildrenRecursive.Any((n) => n.Equals(invocation.ThisReference)))
                return null;

            ii.Folded = true;
            ii.BinaryExpressionParent.ReplaceChild(ii.ParentBinaryExpression, new JSNullExpression());

            var newBoe = new JSBinaryOperatorExpression(
                JSOperator.Assignment, 
                ii.ParentBinaryExpression.Left, newExpression, 
                ii.ParentBinaryExpression.ActualType
            );

            return new JSVariableDeclarationStatement(newBoe);
        }
예제 #18
0
 public void VisitNode(JSNewExpression ne)
 {
     var expectedType = ne.GetExpectedType(TypeSystem);
     if (
         (expectedType != null) &&
         expectedType.FullName.StartsWith("System.Nullable")
     ) {
         if (ne.Arguments.Count == 0) {
             ParentNode.ReplaceChild(
                 ne, JSLiteral.Null(expectedType)
             );
         } else {
             ParentNode.ReplaceChild(
                 ne, ne.Arguments[0]
             );
             VisitReplacement(ne.Arguments[0]);
         }
     } else {
         VisitChildren(ne);
     }
 }
예제 #19
0
        public void VisitNode(JSNewExpression newexp)
        {
            var outer           = Stack.Skip(1).FirstOrDefault();
            var outerInvocation = outer as JSInvocationExpression;
            var outerDot        = outer as JSDotExpressionBase;

            bool parens = ((outerDot != null) && (outerDot.Target == newexp)) ||
                          ((outerInvocation != null) && (outerInvocation.ThisReference == newexp));

            var ctor         = newexp.Constructor;
            var isOverloaded = (ctor != null) &&
                               ctor.IsOverloadedRecursive &&
                               !ctor.Metadata.HasAttribute("JSIL.Meta.JSRuntimeDispatch");

            bool hasArguments = newexp.Arguments.Count > 0;

            var oldInvoking = ReferenceContext.InvokingMethod;

            if (isOverloaded && CanUseFastOverloadDispatch(ctor))
            {
                isOverloaded = false;
            }

            try {
                if (isOverloaded)
                {
                    Output.MethodSignature(newexp.ConstructorReference, ctor.Signature, ReferenceContext);
                    Output.Dot();

                    ReferenceContext.InvokingMethod = newexp.ConstructorReference;

                    Output.Identifier("Construct");
                    Output.LPar();

                    IncludeTypeParens.Push(false);
                    try {
                        Visit(newexp.Type);
                    } finally {
                        IncludeTypeParens.Pop();
                    }

                    if (hasArguments)
                    {
                        Output.Comma();
                        CommaSeparatedList(newexp.Arguments);
                    }

                    Output.RPar();
                }
                else
                {
                    if (parens)
                    {
                        Output.LPar();
                    }

                    Output.WriteRaw("new");
                    Output.Space();

                    IncludeTypeParens.Push(true);
                    try {
                        Visit(newexp.Type);
                    } finally {
                        IncludeTypeParens.Pop();
                    }

                    ReferenceContext.InvokingMethod = newexp.ConstructorReference;

                    Output.LPar();
                    CommaSeparatedList(newexp.Arguments);
                    Output.RPar();

                    if (parens)
                    {
                        Output.RPar();
                    }
                }
            } finally {
                ReferenceContext.InvokingMethod = oldInvoking;
            }
        }