Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(215)

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart

Issue 846353002: Dart2dart: Support for-loop variables captured in loop body. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 part of dart2js.ir_builder; 5 part of dart2js.ir_builder;
6 6
7 /** 7 /**
8 * This task iterates through all resolved elements and builds [ir.Node]s. The 8 * This task iterates through all resolved elements and builds [ir.Node]s. The
9 * nodes are stored in the [nodes] map and accessible through [hasIr] and 9 * nodes are stored in the [nodes] map and accessible through [hasIr] and
10 * [getIr]. 10 * [getIr].
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 403
404 // Build(ExpressionStatement(e), C) = C' 404 // Build(ExpressionStatement(e), C) = C'
405 // where (C', _) = Build(e, C) 405 // where (C', _) = Build(e, C)
406 ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) { 406 ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) {
407 assert(irBuilder.isOpen); 407 assert(irBuilder.isOpen);
408 visit(node.expression); 408 visit(node.expression);
409 return null; 409 return null;
410 } 410 }
411 411
412 visitFor(ast.For node) { 412 visitFor(ast.For node) {
413 // TODO(asgerf): Handle closure variables declared in a for-loop. 413 List<LocalElement> loopVariables = <LocalElement>[];
414 if (!isJavaScriptBackend && node.initializer is ast.VariableDefinitions) { 414 if (node.initializer is ast.VariableDefinitions) {
415 ast.VariableDefinitions definitions = node.initializer; 415 ast.VariableDefinitions definitions = node.initializer;
416 for (ast.Node definition in definitions.definitions.nodes) { 416 for (ast.Node node in definitions.definitions.nodes) {
417 LocalElement element = elements[definition]; 417 LocalElement loopVariable = elements[node];
418 DartIrBuilder dartIrBuilder = irBuilder; 418 loopVariables.add(loopVariable);
419 if (dartIrBuilder.isInClosureVariable(element)) {
420 return giveup(definition, 'Closure variable in for loop initializer');
421 }
422 } 419 }
423 } 420 }
424 421
425 JumpTarget target = elements.getTargetDefinition(node); 422 JumpTarget target = elements.getTargetDefinition(node);
426 irBuilder.buildFor( 423 irBuilder.buildFor(
427 buildInitializer: subbuild(node.initializer), 424 buildInitializer: subbuild(node.initializer),
428 buildCondition: subbuild(node.condition), 425 buildCondition: subbuild(node.condition),
429 buildBody: subbuild(node.body), 426 buildBody: subbuild(node.body),
430 buildUpdate: subbuildSequence(node.update), 427 buildUpdate: subbuildSequence(node.update),
431 closureScope: getClosureScope(node), 428 closureScope: getClosureScope(node),
429 loopVariables: loopVariables,
432 target: target); 430 target: target);
433 } 431 }
434 432
435 visitIf(ast.If node) { 433 visitIf(ast.If node) {
436 irBuilder.buildIf( 434 irBuilder.buildIf(
437 build(node.condition), 435 build(node.condition),
438 subbuild(node.thenPart), 436 subbuild(node.thenPart),
439 subbuild(node.elsePart)); 437 subbuild(node.elsePart));
440 } 438 }
441 439
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
1038 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) { 1036 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
1039 return irBuilder.buildFunctionExpression(makeSubFunction(node)); 1037 return irBuilder.buildFunctionExpression(makeSubFunction(node));
1040 } 1038 }
1041 1039
1042 visitFunctionDeclaration(ast.FunctionDeclaration node) { 1040 visitFunctionDeclaration(ast.FunctionDeclaration node) {
1043 LocalFunctionElement element = elements[node.function]; 1041 LocalFunctionElement element = elements[node.function];
1044 Object inner = makeSubFunction(node.function); 1042 Object inner = makeSubFunction(node.function);
1045 irBuilder.declareLocalFunction(element, inner); 1043 irBuilder.declareLocalFunction(element, inner);
1046 } 1044 }
1047 1045
1048 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
1049
1050 dynamic giveup(ast.Node node, [String reason]) {
1051 throw ABORT_IRNODE_BUILDER;
1052 }
1053
1054 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) { 1046 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) {
1055 try { 1047 try {
1056 return action(); 1048 return action();
1057 } catch(e, tr) { 1049 } catch(e, tr) {
1058 if (e == ABORT_IRNODE_BUILDER) { 1050 if (e == ABORT_IRNODE_BUILDER) {
1059 return null; 1051 return null;
1060 } 1052 }
1061 rethrow; 1053 rethrow;
1062 } 1054 }
1063 } 1055 }
1064 1056
1065 void internalError(String reason, {ast.Node node}) { 1057 void internalError(String reason, {ast.Node node}) {
1066 giveup(node); 1058 giveup(node);
1067 } 1059 }
1068 } 1060 }
1069 1061
1070 /// Classifies local variables and local functions as 'closure variables'. 1062 final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
1071 /// A closure variable is one that is accessed from an inner function nested 1063
1072 /// one or more levels inside the one that declares it. 1064 dynamic giveup(ast.Node node, [String reason]) {
1065 throw ABORT_IRNODE_BUILDER;
1066 }
1067
1068 /// Classifies local variables and local functions as captured, if they
1069 /// are accessed from within a nested function.
1070 ///
1071 /// This class is specific to the [DartIrBuilder], in that it gives up if it
1072 /// sees a feature that is currently unsupport by that builder. In particular,
1073 /// loop variables captured in a for-loop initializer, condition, or update
1074 /// expression are unsupported.
1073 class DetectClosureVariables extends ast.Visitor 1075 class DetectClosureVariables extends ast.Visitor
1074 implements ClosureVariableInfo { 1076 implements ClosureVariableInfo {
1075 final TreeElements elements; 1077 final TreeElements elements;
1076 DetectClosureVariables(this.elements); 1078 DetectClosureVariables(this.elements);
1077 1079
1078 FunctionElement currentFunction; 1080 FunctionElement currentFunction;
1079 bool insideInitializer = false; 1081 bool insideInitializer = false;
1080 Set<Local> capturedVariables = new Set<Local>(); 1082 Set<Local> capturedVariables = new Set<Local>();
1081 1083
1082 void markAsClosureVariable(Local local) { 1084 void markAsClosureVariable(Local local) {
1083 capturedVariables.add(local); 1085 capturedVariables.add(local);
1084 } 1086 }
1085 1087
1086 visit(ast.Node node) => node.accept(this); 1088 visit(ast.Node node) => node.accept(this);
1087 1089
1088 visitNode(ast.Node node) { 1090 visitNode(ast.Node node) {
1089 node.visitChildren(this); 1091 node.visitChildren(this);
1090 } 1092 }
1091 1093
1094 visitFor(ast.For node) {
1095 if (node.initializer != null) visit(node.initializer);
1096 if (node.condition != null) visit(node.condition);
1097 if (node.update != null) visit(node.update);
1098
1099 // Give up if a variable was captured outside of the loop body.
1100 if (node.initializer is ast.VariableDefinitions) {
1101 ast.VariableDefinitions definitions = node.initializer;
1102 for (ast.Node node in definitions.definitions.nodes) {
1103 LocalElement loopVariable = elements[node];
1104 if (capturedVariables.contains(loopVariable)) {
1105 return giveup(node, 'For-loop variable captured in loop header');
1106 }
1107 }
1108 }
1109
1110 if (node.body != null) visit(node.body);
1111 }
1112
1092 void handleSend(ast.Send node) { 1113 void handleSend(ast.Send node) {
1093 Element element = elements[node]; 1114 Element element = elements[node];
1094 if (Elements.isLocal(element) && 1115 if (Elements.isLocal(element) &&
1095 !element.isConst && 1116 !element.isConst &&
1096 element.enclosingElement != currentFunction) { 1117 element.enclosingElement != currentFunction) {
1097 LocalElement local = element; 1118 LocalElement local = element;
1098 markAsClosureVariable(local); 1119 markAsClosureVariable(local);
1099 } 1120 }
1100 } 1121 }
1101 1122
(...skipping 26 matching lines...) Expand all
1128 currentFunction = elements[node]; 1149 currentFunction = elements[node];
1129 if (node.initializers != null) { 1150 if (node.initializers != null) {
1130 insideInitializer = true; 1151 insideInitializer = true;
1131 visit(node.initializers); 1152 visit(node.initializers);
1132 insideInitializer = false; 1153 insideInitializer = false;
1133 } 1154 }
1134 visit(node.body); 1155 visit(node.body);
1135 currentFunction = oldFunction; 1156 currentFunction = oldFunction;
1136 } 1157 }
1137 } 1158 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698