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 |