| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library code_generator; | 5 library code_generator; |
| 6 | 6 |
| 7 import 'glue.dart'; | 7 import 'glue.dart'; |
| 8 | 8 |
| 9 import '../../closure.dart' show ClosureClassElement; | 9 import '../../closure.dart' show ClosureClassElement; |
| 10 import '../../common/codegen.dart' show CodegenRegistry; | 10 import '../../common/codegen.dart' show CodegenRegistry; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 if (!declaredVariables.add(use.name)) break; | 101 if (!declaredVariables.add(use.name)) break; |
| 102 | 102 |
| 103 js.VariableInitialization jsVariable = new js.VariableInitialization( | 103 js.VariableInitialization jsVariable = new js.VariableInitialization( |
| 104 new js.VariableDeclaration(use.name), | 104 new js.VariableDeclaration(use.name), |
| 105 assign.value); | 105 assign.value); |
| 106 jsVariables.add(jsVariable); | 106 jsVariables.add(jsVariable); |
| 107 | 107 |
| 108 ++accumulatorIndex; | 108 ++accumulatorIndex; |
| 109 } | 109 } |
| 110 | 110 |
| 111 // If the last statement is a for loop with an initializer expression, try | |
| 112 // to pull that expression into an initializer as well. | |
| 113 pullFromForLoop: | |
| 114 if (accumulatorIndex < accumulator.length && | |
| 115 accumulator[accumulatorIndex] is js.For) { | |
| 116 js.For forLoop = accumulator[accumulatorIndex]; | |
| 117 if (forLoop.init is! js.Assignment) break pullFromForLoop; | |
| 118 js.Assignment assign = forLoop.init; | |
| 119 if (assign.leftHandSide is! js.VariableUse) break pullFromForLoop; | |
| 120 if (assign.op != null) break pullFromForLoop; // Compound assignment. | |
| 121 js.VariableUse use = assign.leftHandSide; | |
| 122 | |
| 123 // We cannot declare a variable more than once. | |
| 124 if (!declaredVariables.add(use.name)) break pullFromForLoop; | |
| 125 | |
| 126 js.VariableInitialization jsVariable = new js.VariableInitialization( | |
| 127 new js.VariableDeclaration(use.name), | |
| 128 assign.value); | |
| 129 jsVariables.add(jsVariable); | |
| 130 | |
| 131 // Remove the initializer from the for loop. | |
| 132 accumulator[accumulatorIndex] = | |
| 133 new js.For(null, forLoop.condition, forLoop.update, forLoop.body); | |
| 134 } | |
| 135 | |
| 136 // Discard the statements that were pulled in the initializer. | 111 // Discard the statements that were pulled in the initializer. |
| 137 if (accumulatorIndex > 0) { | 112 if (accumulatorIndex > 0) { |
| 138 accumulator = accumulator.sublist(accumulatorIndex); | 113 accumulator = accumulator.sublist(accumulatorIndex); |
| 139 } | 114 } |
| 140 | 115 |
| 141 // Declare remaining variables. | 116 // Declare remaining variables. |
| 142 for (tree_ir.Variable variable in variableNames.keys) { | 117 for (tree_ir.Variable variable in variableNames.keys) { |
| 143 String name = getVariableName(variable); | 118 String name = getVariableName(variable); |
| 144 if (declaredVariables.contains(name)) continue; | 119 if (declaredVariables.contains(name)) continue; |
| 145 js.VariableInitialization jsVariable = new js.VariableInitialization( | 120 js.VariableInitialization jsVariable = new js.VariableInitialization( |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 | 509 |
| 535 js.Block buildBodyBlock(tree_ir.Statement statement) { | 510 js.Block buildBodyBlock(tree_ir.Statement statement) { |
| 536 List<js.Statement> savedAccumulator = accumulator; | 511 List<js.Statement> savedAccumulator = accumulator; |
| 537 accumulator = <js.Statement>[]; | 512 accumulator = <js.Statement>[]; |
| 538 visitStatement(statement); | 513 visitStatement(statement); |
| 539 js.Statement result = new js.Block(accumulator); | 514 js.Statement result = new js.Block(accumulator); |
| 540 accumulator = savedAccumulator; | 515 accumulator = savedAccumulator; |
| 541 return result; | 516 return result; |
| 542 } | 517 } |
| 543 | 518 |
| 544 js.Expression makeSequence(List<tree_ir.Expression> list) { | |
| 545 return list.map(visitExpression).reduce((x,y) => new js.Binary(',', x, y)); | |
| 546 } | |
| 547 | |
| 548 @override | 519 @override |
| 549 void visitFor(tree_ir.For node) { | 520 void visitWhileCondition(tree_ir.WhileCondition node) { |
| 550 js.Expression condition = visitExpression(node.condition); | 521 js.Expression condition = visitExpression(node.condition); |
| 551 shortBreak.push(node.next); | 522 shortBreak.push(node.next); |
| 552 shortContinue.push(node); | 523 shortContinue.push(node); |
| 553 fallthrough.push(node); | 524 fallthrough.push(node); |
| 554 js.Statement body = buildBodyStatement(node.body); | 525 js.Statement jsBody = buildBodyStatement(node.body); |
| 555 fallthrough.pop(); | 526 fallthrough.pop(); |
| 556 shortContinue.pop(); | 527 shortContinue.pop(); |
| 557 shortBreak.pop(); | 528 shortBreak.pop(); |
| 558 js.Statement loopNode; | 529 accumulator.add(insertLabel(node.label, new js.While(condition, jsBody))); |
| 559 if (node.updates.isEmpty) { | |
| 560 loopNode = new js.While(condition, body); | |
| 561 } else { // Compile as a for loop. | |
| 562 js.Expression init; | |
| 563 if (accumulator.isNotEmpty && | |
| 564 accumulator.last is js.ExpressionStatement) { | |
| 565 // Take the preceding expression from the accumulator and use | |
| 566 // it as the initializer expression. | |
| 567 js.ExpressionStatement initStmt = accumulator.removeLast(); | |
| 568 init = initStmt.expression; | |
| 569 } | |
| 570 js.Expression update = makeSequence(node.updates); | |
| 571 loopNode = new js.For(init, condition, update, body); | |
| 572 } | |
| 573 accumulator.add(insertLabel(node.label, loopNode)); | |
| 574 visitStatement(node.next); | 530 visitStatement(node.next); |
| 575 } | 531 } |
| 576 | 532 |
| 577 @override | 533 @override |
| 578 void visitWhileTrue(tree_ir.WhileTrue node) { | 534 void visitWhileTrue(tree_ir.WhileTrue node) { |
| 579 js.Expression condition = new js.LiteralBool(true); | 535 js.Expression condition = new js.LiteralBool(true); |
| 580 // A short break in the while will jump to the current fallthrough target. | 536 // A short break in the while will jump to the current fallthrough target. |
| 581 shortBreak.push(fallthrough.target); | 537 shortBreak.push(fallthrough.target); |
| 582 shortContinue.push(node); | 538 shortContinue.push(node); |
| 583 fallthrough.push(node); | 539 fallthrough.push(node); |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 896 js.Expression visitAwait(tree_ir.Await node) { | 852 js.Expression visitAwait(tree_ir.Await node) { |
| 897 return new js.Await(visitExpression(node.input)); | 853 return new js.Await(visitExpression(node.input)); |
| 898 } | 854 } |
| 899 | 855 |
| 900 visitFunctionExpression(tree_ir.FunctionExpression node) { | 856 visitFunctionExpression(tree_ir.FunctionExpression node) { |
| 901 // FunctionExpressions are currently unused. | 857 // FunctionExpressions are currently unused. |
| 902 // We might need them if we want to emit raw JS nested functions. | 858 // We might need them if we want to emit raw JS nested functions. |
| 903 throw 'FunctionExpressions should not be used'; | 859 throw 'FunctionExpressions should not be used'; |
| 904 } | 860 } |
| 905 } | 861 } |
| OLD | NEW |