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 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)); }
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); } }
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); } }
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)); }
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); }
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); }
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); }
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); }
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); }
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); } }
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); }
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); } }
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; } }