public void VisitNode(JSExpressionStatement es) { try { VisitChildren(es); } catch (Exception exc) { Console.WriteLine("// Error in statement"); Console.WriteLine("// {0}", es); throw; } }
public void BuildLabelGroups(JSFunctionExpression function) { // If a label is applied to the first statement in a block, hoist it upward // onto the parent block. var lh = new LabelHoister(); do { lh.HoistedALabel = false; lh.Visit(function); } while (lh.HoistedALabel); // Walk the function to build our list of labels and gotos. Visit(function); // When a goto crosses block boundaries, we need to move the target label // upwards so that the goto can reach it. foreach (var g in Gotos) { var targetLabel = Labels[g.TargetLabel]; if (targetLabel.EnclosingBlock.Depth > g.EnclosingBlock.Depth) { targetLabel.EnclosingBlock = g.EnclosingBlock; } } foreach (var l in Labels.Values) { l.EnsureLabelGroupExists(LabelGroups); var replacementGoto = new JSExpressionStatement( new JSGotoExpression(l.LabelledStatement.Label) ); l.EnclosingBlock.Block.ReplaceChildRecursive(l.LabelledStatement, replacementGoto); l.LabelGroup.Add(l.LabelledStatement); } // If a label group only contains one label (plus an entry label), // and it has a parent label group, hoist the label up. var lgs = new LabelGroupFlattener(); do { lgs.FlattenedAGroup = false; lgs.Visit(function); } while (lgs.FlattenedAGroup); // Remove any labels within a label group that contain no statements (as long // as no goto targets that label directly). This will prune empty entry/exit labels. var elr = new EmptyLabelRemover(UsedLabels); elr.Visit(function); }
public void VisitNode(JSExpressionStatement es) { var invocationExpression = es.Expression as JSInvocationExpression; if (invocationExpression != null) { var replacement = MaybeReplaceInvocation(invocationExpression); if (replacement != null) { ParentNode.ReplaceChild(es, replacement); VisitReplacement(replacement); return; } } VisitChildren(es); }
public void VisitNode(JSExpressionStatement statement) { bool isNull = (statement.IsNull || statement.Expression.IsNull) && !(statement.Expression is JSUntranslatableExpression) && !(statement.Expression is JSIgnoredMemberReference); Visit(statement.Expression); if (!isNull && ((BlockStack.Count == 0) || (BlockStack.Peek() != BlockType.ForHeader)) ) { Output.Semicolon(); } }
public void BuildLabelGroups() { foreach (var g in Gotos) { var targetLabel = Labels[g.TargetLabel]; if (targetLabel.EnclosingBlock.Depth > g.EnclosingBlock.Depth) { targetLabel.EnclosingBlock = g.EnclosingBlock; } } foreach (var l in Labels.Values) { l.EnsureLabelGroupExists(LabelGroups); var replacementGoto = new JSExpressionStatement( new JSGotoExpression(l.LabelledStatement.Label) ); l.EnclosingBlock.Block.ReplaceChildRecursive(l.LabelledStatement, replacementGoto); l.LabelGroup.Add(l.LabelledStatement); } }
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) { Console.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); }
public void VisitNode(JSExpressionStatement es) { base.VisitNode(es); }