| 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 backend_ast_emitter; | 5 library backend_ast_emitter; |
| 6 | 6 |
| 7 import '../tree_ir/tree_ir_nodes.dart' as tree; | 7 import '../tree_ir/tree_ir_nodes.dart' as tree; |
| 8 import 'backend_ast_nodes.dart'; | 8 import 'backend_ast_nodes.dart'; |
| 9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
| 10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 // and local function declarations. | 89 // and local function declarations. |
| 90 void addDeclaration(tree.Variable variable, [Expression initializer]) { | 90 void addDeclaration(tree.Variable variable, [Expression initializer]) { |
| 91 assert(!declaredVariables.contains(variable)); | 91 assert(!declaredVariables.contains(variable)); |
| 92 String name = getVariableName(variable); | 92 String name = getVariableName(variable); |
| 93 VariableDeclaration decl = new VariableDeclaration(name, initializer); | 93 VariableDeclaration decl = new VariableDeclaration(name, initializer); |
| 94 decl.element = variable.element; | 94 decl.element = variable.element; |
| 95 declaredVariables.add(variable); | 95 declaredVariables.add(variable); |
| 96 variables.add(decl); | 96 variables.add(decl); |
| 97 } | 97 } |
| 98 | 98 |
| 99 /// Creates an [Identifier] referring to the given variable. |
| 100 Expression makeVariableAccess(tree.Variable variable) { |
| 101 return new Identifier(getVariableName(variable)) |
| 102 ..element = variable.element; |
| 103 } |
| 104 |
| 99 /// Generates a name for the given variable and synthesizes an element for it, | 105 /// Generates a name for the given variable and synthesizes an element for it, |
| 100 /// if necessary. | 106 /// if necessary. |
| 101 String getVariableName(tree.Variable variable) { | 107 String getVariableName(tree.Variable variable) { |
| 102 // If the variable belongs to an enclosing function, ask the parent emitter | 108 // If the variable belongs to an enclosing function, ask the parent emitter |
| 103 // for the variable name. | 109 // for the variable name. |
| 104 if (!inInitializer && variable.host != currentElement) { | 110 if (!inInitializer && variable.host != currentElement) { |
| 105 return _parent.getVariableName(variable); | 111 return _parent.getVariableName(variable); |
| 106 } | 112 } |
| 107 | 113 |
| 108 // Get the name if we already have one. | 114 // Get the name if we already have one. |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 // Try to pull into initializer. | 539 // Try to pull into initializer. |
| 534 if (context.firstStatement == stmt && isFirstOccurrence && isDeclaredHere) { | 540 if (context.firstStatement == stmt && isFirstOccurrence && isDeclaredHere) { |
| 535 if (isNullLiteral(definition)) definition = null; | 541 if (isNullLiteral(definition)) definition = null; |
| 536 context.addDeclaration(stmt.variable, definition); | 542 context.addDeclaration(stmt.variable, definition); |
| 537 context.firstStatement = stmt.next; | 543 context.firstStatement = stmt.next; |
| 538 visitStatement(stmt.next, context); | 544 visitStatement(stmt.next, context); |
| 539 return; | 545 return; |
| 540 } | 546 } |
| 541 | 547 |
| 542 // Emit a variable declaration if we are required to do so. | 548 // Emit a variable declaration if we are required to do so. |
| 543 // This is to ensure that a fresh closure variable is created. | 549 // For captured variables, this ensures that a fresh variable is created. |
| 544 if (stmt.isDeclaration) { | 550 if (stmt.isDeclaration) { |
| 545 assert(isFirstOccurrence); | 551 assert(isFirstOccurrence); |
| 546 assert(isDeclaredHere); | 552 assert(isDeclaredHere); |
| 547 if (isNullLiteral(definition)) definition = null; | 553 if (isNullLiteral(definition)) definition = null; |
| 548 VariableDeclaration decl = new VariableDeclaration(name, definition) | 554 VariableDeclaration decl = new VariableDeclaration(name, definition) |
| 549 ..element = stmt.variable.element; | 555 ..element = stmt.variable.element; |
| 550 context.declaredVariables.add(stmt.variable); | 556 context.declaredVariables.add(stmt.variable); |
| 551 context.addStatement(new VariableDeclarations([decl])); | 557 context.addStatement(new VariableDeclarations([decl])); |
| 552 visitStatement(stmt.next, context); | 558 visitStatement(stmt.next, context); |
| 553 return; | 559 return; |
| 554 } | 560 } |
| 555 | 561 |
| 556 context.addStatement(new ExpressionStatement(makeAssignment( | 562 context.addStatement(new ExpressionStatement(makeAssignment( |
| 557 visitVariable(stmt.variable, context), | 563 context.makeVariableAccess(stmt.variable), |
| 558 definition))); | 564 definition))); |
| 559 visitStatement(stmt.next, context); | 565 visitStatement(stmt.next, context); |
| 560 } | 566 } |
| 561 | 567 |
| 562 @override | 568 @override |
| 563 void visitReturn(tree.Return stmt, | 569 void visitReturn(tree.Return stmt, |
| 564 BuilderContext<Statement> context) { | 570 BuilderContext<Statement> context) { |
| 565 if (context.currentElement.isGenerativeConstructor && | 571 if (context.currentElement.isGenerativeConstructor && |
| 566 !context.inInitializer) { | 572 !context.inInitializer) { |
| 567 assert(() { | 573 assert(() { |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 visitExpression(exp.right, context)); | 862 visitExpression(exp.right, context)); |
| 857 } | 863 } |
| 858 | 864 |
| 859 @override | 865 @override |
| 860 Expression visitNot(tree.Not exp, | 866 Expression visitNot(tree.Not exp, |
| 861 BuilderContext<Statement> context) { | 867 BuilderContext<Statement> context) { |
| 862 return new UnaryOperator('!', visitExpression(exp.operand, context)); | 868 return new UnaryOperator('!', visitExpression(exp.operand, context)); |
| 863 } | 869 } |
| 864 | 870 |
| 865 @override | 871 @override |
| 866 Expression visitVariable(tree.Variable exp, | 872 Expression visitVariableUse(tree.VariableUse exp, |
| 867 BuilderContext<Statement> context) { | 873 BuilderContext<Statement> context) { |
| 868 return new Identifier(context.getVariableName(exp)) | 874 return context.makeVariableAccess(exp.variable); |
| 869 ..element = exp.element; | |
| 870 } | 875 } |
| 871 | 876 |
| 872 FunctionExpression makeSubFunction(tree.FunctionDefinition function, | 877 FunctionExpression makeSubFunction(tree.FunctionDefinition function, |
| 873 BuilderContext<Statement> context) { | 878 BuilderContext<Statement> context) { |
| 874 return emit(function, new BuilderContext<Statement>.inner(context)); | 879 return emit(function, new BuilderContext<Statement>.inner(context)); |
| 875 } | 880 } |
| 876 | 881 |
| 877 @override | 882 @override |
| 878 Expression visitFunctionExpression(tree.FunctionExpression exp, | 883 Expression visitFunctionExpression(tree.FunctionExpression exp, |
| 879 BuilderContext<Statement> context) { | 884 BuilderContext<Statement> context) { |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 visitStatement(definition.body); | 1263 visitStatement(definition.body); |
| 1259 environment = oldEnvironment; | 1264 environment = oldEnvironment; |
| 1260 shadowedParameters = oldShadow; | 1265 shadowedParameters = oldShadow; |
| 1261 | 1266 |
| 1262 for (int i=0; i<definition.parameters.length; i++) { | 1267 for (int i=0; i<definition.parameters.length; i++) { |
| 1263 tree.Variable param = definition.parameters[i]; | 1268 tree.Variable param = definition.parameters[i]; |
| 1264 if (hasShadowedUse.remove(param)) { | 1269 if (hasShadowedUse.remove(param)) { |
| 1265 tree.Variable newParam = new tree.Variable(definition.element, | 1270 tree.Variable newParam = new tree.Variable(definition.element, |
| 1266 param.element); | 1271 param.element); |
| 1267 definition.parameters[i] = newParam; | 1272 definition.parameters[i] = newParam; |
| 1268 definition.body = new tree.Assign(param, newParam, definition.body); | 1273 definition.body = new tree.Assign(param, new tree.VariableUse(newParam), |
| 1274 definition.body); |
| 1269 newParam.writeCount = 1; // Being a parameter counts as a write. | 1275 newParam.writeCount = 1; // Being a parameter counts as a write. |
| 1276 param.writeCount--; // Not a parameter anymore. |
| 1270 } | 1277 } |
| 1271 } | 1278 } |
| 1272 } | 1279 } |
| 1273 | 1280 |
| 1281 @override |
| 1274 visitVariable(tree.Variable variable) { | 1282 visitVariable(tree.Variable variable) { |
| 1275 if (shadowedParameters.contains(variable)) { | 1283 if (shadowedParameters.contains(variable)) { |
| 1276 hasShadowedUse.add(variable); | 1284 hasShadowedUse.add(variable); |
| 1277 } | 1285 } |
| 1278 } | 1286 } |
| 1279 | 1287 |
| 1280 } | 1288 } |
| 1281 | 1289 |
| 1282 // TODO(johnniwinther): Remove this when the dart `backend_ast` does not need | 1290 // TODO(johnniwinther): Remove this when the dart `backend_ast` does not need |
| 1283 // [Element] for entities. | 1291 // [Element] for entities. |
| 1284 class _SyntheticLocalVariableElement extends modelx.VariableElementX | 1292 class _SyntheticLocalVariableElement extends modelx.VariableElementX |
| 1285 implements LocalVariableElement { | 1293 implements LocalVariableElement { |
| 1286 | 1294 |
| 1287 _SyntheticLocalVariableElement(String name, | 1295 _SyntheticLocalVariableElement(String name, |
| 1288 ExecutableElement enclosingElement, | 1296 ExecutableElement enclosingElement, |
| 1289 modelx.VariableList variables) | 1297 modelx.VariableList variables) |
| 1290 : super(name, ElementKind.VARIABLE, enclosingElement, variables, null); | 1298 : super(name, ElementKind.VARIABLE, enclosingElement, variables, null); |
| 1291 | 1299 |
| 1292 ExecutableElement get executableContext => enclosingElement; | 1300 ExecutableElement get executableContext => enclosingElement; |
| 1293 | 1301 |
| 1294 ExecutableElement get memberContext => executableContext.memberContext; | 1302 ExecutableElement get memberContext => executableContext.memberContext; |
| 1295 | 1303 |
| 1296 bool get isLocal => true; | 1304 bool get isLocal => true; |
| 1297 | 1305 |
| 1298 LibraryElement get implementationLibrary => enclosingElement.library; | 1306 LibraryElement get implementationLibrary => enclosingElement.library; |
| 1299 } | 1307 } |
| OLD | NEW |