| 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 |
| 111 // Discard the statements that were pulled in the initializer. | 136 // Discard the statements that were pulled in the initializer. |
| 112 if (accumulatorIndex > 0) { | 137 if (accumulatorIndex > 0) { |
| 113 accumulator = accumulator.sublist(accumulatorIndex); | 138 accumulator = accumulator.sublist(accumulatorIndex); |
| 114 } | 139 } |
| 115 | 140 |
| 116 // Declare remaining variables. | 141 // Declare remaining variables. |
| 117 for (tree_ir.Variable variable in variableNames.keys) { | 142 for (tree_ir.Variable variable in variableNames.keys) { |
| 118 String name = getVariableName(variable); | 143 String name = getVariableName(variable); |
| 119 if (declaredVariables.contains(name)) continue; | 144 if (declaredVariables.contains(name)) continue; |
| 120 js.VariableInitialization jsVariable = new js.VariableInitialization( | 145 js.VariableInitialization jsVariable = new js.VariableInitialization( |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 | 534 |
| 510 js.Block buildBodyBlock(tree_ir.Statement statement) { | 535 js.Block buildBodyBlock(tree_ir.Statement statement) { |
| 511 List<js.Statement> savedAccumulator = accumulator; | 536 List<js.Statement> savedAccumulator = accumulator; |
| 512 accumulator = <js.Statement>[]; | 537 accumulator = <js.Statement>[]; |
| 513 visitStatement(statement); | 538 visitStatement(statement); |
| 514 js.Statement result = new js.Block(accumulator); | 539 js.Statement result = new js.Block(accumulator); |
| 515 accumulator = savedAccumulator; | 540 accumulator = savedAccumulator; |
| 516 return result; | 541 return result; |
| 517 } | 542 } |
| 518 | 543 |
| 544 js.Expression makeSequence(List<tree_ir.Expression> list) { |
| 545 return list.map(visitExpression).reduce((x,y) => new js.Binary(',', x, y)); |
| 546 } |
| 547 |
| 519 @override | 548 @override |
| 520 void visitWhileCondition(tree_ir.WhileCondition node) { | 549 void visitWhileCondition(tree_ir.WhileCondition node) { |
| 521 js.Expression condition = visitExpression(node.condition); | 550 js.Expression condition = visitExpression(node.condition); |
| 522 shortBreak.push(node.next); | 551 shortBreak.push(node.next); |
| 523 shortContinue.push(node); | 552 shortContinue.push(node); |
| 524 fallthrough.push(node); | 553 fallthrough.push(node); |
| 525 js.Statement jsBody = buildBodyStatement(node.body); | 554 js.Statement body = buildBodyStatement(node.body); |
| 526 fallthrough.pop(); | 555 fallthrough.pop(); |
| 527 shortContinue.pop(); | 556 shortContinue.pop(); |
| 528 shortBreak.pop(); | 557 shortBreak.pop(); |
| 529 accumulator.add(insertLabel(node.label, new js.While(condition, jsBody))); | 558 js.Statement loopNode; |
| 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)); |
| 530 visitStatement(node.next); | 574 visitStatement(node.next); |
| 531 } | 575 } |
| 532 | 576 |
| 533 @override | 577 @override |
| 534 void visitWhileTrue(tree_ir.WhileTrue node) { | 578 void visitWhileTrue(tree_ir.WhileTrue node) { |
| 535 js.Expression condition = new js.LiteralBool(true); | 579 js.Expression condition = new js.LiteralBool(true); |
| 536 // A short break in the while will jump to the current fallthrough target. | 580 // A short break in the while will jump to the current fallthrough target. |
| 537 shortBreak.push(fallthrough.target); | 581 shortBreak.push(fallthrough.target); |
| 538 shortContinue.push(node); | 582 shortContinue.push(node); |
| 539 fallthrough.push(node); | 583 fallthrough.push(node); |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 js.Expression visitAwait(tree_ir.Await node) { | 896 js.Expression visitAwait(tree_ir.Await node) { |
| 853 return new js.Await(visitExpression(node.input)); | 897 return new js.Await(visitExpression(node.input)); |
| 854 } | 898 } |
| 855 | 899 |
| 856 visitFunctionExpression(tree_ir.FunctionExpression node) { | 900 visitFunctionExpression(tree_ir.FunctionExpression node) { |
| 857 // FunctionExpressions are currently unused. | 901 // FunctionExpressions are currently unused. |
| 858 // We might need them if we want to emit raw JS nested functions. | 902 // We might need them if we want to emit raw JS nested functions. |
| 859 throw 'FunctionExpressions should not be used'; | 903 throw 'FunctionExpressions should not be used'; |
| 860 } | 904 } |
| 861 } | 905 } |
| OLD | NEW |