public void VisitNode(JSVariableDeclarationStatement vds) { var parentBlock = (JSBlockStatement)ParentNode; Declarations.Add(vds, parentBlock); VisitChildren(vds); }
public void VisitNode(JSVariableDeclarationStatement node) { if (node.Declarations.Count == 0) { node.SymbolInfo = null; } VisitChildren(node); }
public void VisitNode(JSVariableDeclarationStatement vds) { var parentBlock = (JSBlockStatement)ParentNode; // FIXME: Is this right? JSBlockStatement existing; if (Declarations.TryGetValue(vds, out existing)) { if (existing != parentBlock) throw new InvalidDataException("Multiple parents for a single declaration statement"); } else { Declarations.Add(vds, parentBlock); } VisitChildren(vds); }
private JSForLoop ReplaceWhileLoopAndEnumerator(JSWhileLoop wl, JSExpression backingStore, JSExpression enumerator, TypeInfo enumeratorType, string arrayMember, string lengthMember) { var loopId = _NextLoopId++; var arrayVariableName = String.Format("a${0:x}", loopId); var indexVariableName = String.Format("i${0:x}", loopId); var lengthVariableName = String.Format("l${0:x}", loopId); var currentPropertyReference = enumeratorType.Definition.Properties.First((p) => p.Name == "Current"); var currentPropertyInfo = enumeratorType.Source.GetProperty(currentPropertyReference); var itemType = currentPropertyInfo.ReturnType; var arrayType = new ArrayType(itemType); var arrayVariable = new JSVariable( arrayVariableName, arrayType, Function.Method.Reference, JSDotExpression.New(backingStore, new JSStringIdentifier(arrayMember, arrayType)) ); var indexVariable = new JSVariable( indexVariableName, TypeSystem.Int32, Function.Method.Reference, JSLiteral.New(0) ); var lengthVariable = new JSVariable( lengthVariableName, TypeSystem.Int32, Function.Method.Reference, JSDotExpression.New(backingStore, new JSStringIdentifier(lengthMember, TypeSystem.Int32)) ); var initializer = new JSVariableDeclarationStatement( new JSBinaryOperatorExpression( JSOperator.Assignment, arrayVariable, arrayVariable.DefaultValue, arrayVariable.IdentifierType ), new JSBinaryOperatorExpression( JSOperator.Assignment, indexVariable, indexVariable.DefaultValue, indexVariable.IdentifierType ), new JSBinaryOperatorExpression( JSOperator.Assignment, lengthVariable, lengthVariable.DefaultValue, lengthVariable.IdentifierType ) ); var condition = new JSBinaryOperatorExpression( JSBinaryOperator.LessThan, indexVariable, lengthVariable, TypeSystem.Boolean ); var increment = new JSUnaryOperatorExpression( JSUnaryOperator.PostIncrement, indexVariable, TypeSystem.Int32 ); var result = new JSForLoop( initializer, condition, new JSExpressionStatement(increment), wl.Statements.ToArray() ); result.Index = wl.Index; new PropertyAccessReplacer( enumerator, new JSProperty(currentPropertyReference, currentPropertyInfo), new JSIndexerExpression( arrayVariable, indexVariable, itemType ) ).Visit(result); return result; }
protected void TransformVariableIntoReference(JSVariable variable, JSVariableDeclarationStatement statement, int declarationIndex, JSBlockStatement enclosingBlock) { var oldDeclaration = statement.Declarations[declarationIndex]; var valueType = oldDeclaration.Right.GetActualType(JSIL.TypeSystem); var newVariable = variable.Reference(); var enclosingFunction = Stack.OfType<JSFunctionExpression>().First(); JSExpression initialValue; // If the declaration was in function scope originally we can hoist the initial value // into our new variable declaration. If not, we need to initialize the ref variable // to the default value for its type. It will get the correct value assigned later. if (enclosingBlock == enclosingFunction.Body) initialValue = oldDeclaration.Right; else initialValue = new JSDefaultValueLiteral(valueType); var newDeclaration = new JSVariableDeclarationStatement(new JSBinaryOperatorExpression( JSOperator.Assignment, // We have to use a constructed ref to the variable here, otherwise // the declaration will look like 'var x.value = foo' new JSVariable(variable.Identifier, variable.IdentifierType, variable.Function), JSIL.NewReference(initialValue), newVariable.IdentifierType )); if (Tracing) Debug.WriteLine(String.Format("Transformed {0} into {1} in {2}", variable, newVariable, statement)); // Insert the new declaration directly before the top-level block containing the original // declaration. This ensures that if its initial value has a dependency on external state, // the declaration will not precede the values it depends on. // Note that for declarations that were hoisted out of inner blocks (conditionals, loops) // it doesn't actually matter where the insert occurs, since we initialize with a default // value in that case. enclosingFunction.Body.InsertNearChildRecursive( statement, newDeclaration, 0 ); // If the reference is being declared in function scope, it doesn't need a separate assignment // for its initialization. Otherwise, we need to insert an assignment after the original variable // declaration statement to ensure that the reference variable is initialized to the right value // at the exact right point in the function's execution. if (enclosingBlock != enclosingFunction.Body) { var newAssignment = new JSExpressionStatement( new JSBinaryOperatorExpression( JSOperator.Assignment, newVariable, oldDeclaration.Right, valueType ) ); var insertLocation = enclosingBlock.Statements.IndexOf(statement) + 1; enclosingBlock.Statements.Insert(insertLocation, newAssignment); } Variables[variable.Identifier] = newVariable; statement.Declarations.RemoveAt(declarationIndex); TransformedVariables.Add(variable.Identifier); }
protected void TransformParameterIntoReference(JSVariable parameter, JSBlockStatement block) { var newParameter = new JSParameter("$" + parameter.Identifier, parameter.IdentifierType, parameter.Function); var newVariable = new JSVariable(parameter.Identifier, new ByReferenceType(parameter.IdentifierType), parameter.Function); var newDeclaration = new JSVariableDeclarationStatement( new JSBinaryOperatorExpression( JSOperator.Assignment, // We have to use parameter here, not newVariable or newParameter, otherwise the resulting // assignment looks like 'x.value = initializer' instead of 'x = initializer' parameter, JSIL.NewReference(newParameter), newVariable.IdentifierType ) ); if (Tracing) Debug.WriteLine(String.Format("Transformed {0} into {1}={2}", parameter, newVariable, newParameter)); Variables[newVariable.Identifier] = newVariable; Variables.Add(newParameter.Identifier, newParameter); var enclosingFunction = Stack.OfType<JSFunctionExpression>().First(); enclosingFunction.Body.Statements.Insert(0, newDeclaration); var oldIndex = Array.IndexOf(enclosingFunction.Parameters, parameter); enclosingFunction.Parameters[oldIndex] = newParameter; }
public void VisitNode (JSFunctionExpression fn) { Function = fn; FirstPass = GetFirstPass(Function.Method.QualifiedIdentifier); VisitChildren(fn); if (ToDeclare.Count > 0) { int i = 0; var vds = new JSVariableDeclarationStatement(); foreach (var pd in ToDeclare) { vds.Declarations.Add( new JSBinaryOperatorExpression( JSOperator.Assignment, pd.Expression, pd.DefaultValue ?? new JSDefaultValueLiteral(pd.Type), pd.Type ) ); } fn.Body.Statements.Insert(i++, vds); InvalidateFirstPass(); } }
public void VisitNode(JSVariableDeclarationStatement vds) { Declarations.Add(vds); VisitChildren(vds); }
protected void TransformVariableIntoReference(JSVariable variable, JSVariableDeclarationStatement statement, int declarationIndex) { if (variable.IsReference) Debugger.Break(); var oldDeclaration = statement.Declarations[declarationIndex]; var newVariable = variable.Reference(); var newDeclaration = new JSBinaryOperatorExpression( JSOperator.Assignment, // We have to use a constructed ref to the variable here, otherwise // the declaration will look like 'var x.value = foo' new JSVariable(variable.Identifier, variable.Type), JSIL.NewReference(oldDeclaration.Right), newVariable.Type ); if (Tracing) Debug.WriteLine(String.Format("Transformed {0} into {1} in {2}", variable, newVariable, statement)); Variables[variable.Identifier] = newVariable; statement.Declarations[declarationIndex] = newDeclaration; TransformedVariables.Add(variable.Identifier); }
protected void TransformParameterIntoReference(JSVariable parameter, JSBlockStatement block) { var newParameter = new JSParameter("$" + parameter.Identifier, parameter.Type); var newVariable = new JSVariable(parameter.Identifier, new ByReferenceType(parameter.Type)); var newDeclaration = new JSVariableDeclarationStatement( new JSBinaryOperatorExpression( JSOperator.Assignment, // We have to use parameter here, not newVariable or newParameter, otherwise the resulting // assignment looks like 'x.value = initializer' instead of 'x = initializer' parameter, JSIL.NewReference(newParameter), newVariable.Type ) ); if (Tracing) Debug.WriteLine(String.Format("Transformed {0} into {1}={2}", parameter, newVariable, newParameter)); Variables[newVariable.Identifier] = newVariable; Variables.Add(newParameter.Identifier, newParameter); ParameterNames.Remove(parameter.Identifier); ParameterNames.Add(newParameter.Identifier); block.Statements.Insert(0, newDeclaration); }