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

Side by Side Diff: pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart

Issue 1068243002: Overhaul tree IR visitor and rename IR classes. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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) 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';
11 import '../dart_types.dart'; 11 import '../dart_types.dart';
12 import '../elements/elements.dart'; 12 import '../elements/elements.dart';
13 import '../elements/modelx.dart' as modelx; 13 import '../elements/modelx.dart' as modelx;
14 import '../universe/universe.dart'; 14 import '../universe/universe.dart';
15 import '../tree/tree.dart' as tree show Modifiers; 15 import '../tree/tree.dart' as tree show Modifiers;
16 16
17 /// Translates the dart_tree IR to Dart backend AST. 17 /// Translates the dart_tree IR to Dart backend AST.
18 ExecutableDefinition emit(tree.ExecutableDefinition definition) { 18 RootNode emit(tree.RootNode definition) {
Kevin Millikin (Google) 2015/04/08 15:10:15 definition ==> root
asgerf 2015/04/09 09:58:23 Done.
19 return new ASTEmitter().emit(definition, new BuilderContext<Statement>()); 19 return new ASTEmitter().emit(definition);
20 } 20 }
21 21
22 // TODO(johnniwinther): Split into function/block state. 22 // TODO(johnniwinther): Split into function/block state.
23 class BuilderContext<T> { 23 class BuilderContext<T> {
24 /// Builder context for the enclosing function, or null if the current 24 /// Builder context for the enclosing function, or null if the current
25 /// function is not a local function. 25 /// function is not a local function.
26 BuilderContext<T> _parent; 26 BuilderContext<T> _parent;
27 27
28 /// Variables to be hoisted at the top of the current function. 28 /// Variables to be hoisted at the top of the current function.
29 final List<VariableDeclaration> variables = <VariableDeclaration>[]; 29 final List<VariableDeclaration> variables = <VariableDeclaration>[];
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 196
197 /// Add [statement] to the current block. 197 /// Add [statement] to the current block.
198 void addStatement(T statement) { 198 void addStatement(T statement) {
199 _statementBuffer.add(statement); 199 _statementBuffer.add(statement);
200 } 200 }
201 201
202 /// The statements in the current block. 202 /// The statements in the current block.
203 Iterable<T> get statements => _statementBuffer; 203 Iterable<T> get statements => _statementBuffer;
204 } 204 }
205 205
206
207 /// Translates the dart_tree IR to Dart backend AST. 206 /// Translates the dart_tree IR to Dart backend AST.
208 /// An instance of this class should only be used once; a fresh emitter 207 /// An instance of this class should only be used once; a fresh emitter
209 /// must be created for each function to be emitted. 208 /// must be created for each function to be emitted.
210 class ASTEmitter 209 class ASTEmitter
211 extends tree.Visitor1<dynamic, Expression, BuilderContext<Statement>> { 210 extends tree.StatementVisitor1<dynamic, BuilderContext<Statement>>
211 with tree.ExpressionVisitor1<Expression, BuilderContext<Statement>>,
212 tree.RootVisitor1<RootNode, BuilderContext<Statement>>,
213 tree.InitializerVisitor1<Initializer, BuilderContext<Statement>> {
212 214
213 ExecutableDefinition emit(tree.ExecutableDefinition definition, 215 RootNode emit(tree.RootNode node) {
214 BuilderContext<Statement> context) { 216 return visitRootNode(node, new BuilderContext<Statement>());
215 if (definition is tree.FieldDefinition) {
216 return emitField(definition, context);
217 } else if (definition is tree.ConstructorDefinition) {
218 return emitConstructor(definition, context);
219 }
220 assert(definition is tree.FunctionDefinition);
221 return emitFunction(definition, context);
222 } 217 }
223 218
224 FieldDefinition emitField(tree.FieldDefinition definition, 219 @override
225 BuilderContext<Statement> context) { 220 FieldDefinition visitFieldDefinition(tree.FieldDefinition definition,
221 BuilderContext<Statement> context) {
226 context.currentElement = definition.element; 222 context.currentElement = definition.element;
227 Expression initializer; 223 Expression initializer;
228 if (definition.hasInitializer) { 224 if (!definition.isEmpty) {
229 visitStatement(definition.body, context); 225 visitStatement(definition.body, context);
230 List<Statement> bodyParts; 226 List<Statement> bodyParts;
231 for (tree.Variable variable in context.variableNames.keys) { 227 for (tree.Variable variable in context.variableNames.keys) {
232 if (!context.declaredVariables.contains(variable)) { 228 if (!context.declaredVariables.contains(variable)) {
233 context.addDeclaration(variable); 229 context.addDeclaration(variable);
234 } 230 }
235 } 231 }
236 if (context.variables.length > 0) { 232 if (context.variables.length > 0) {
237 bodyParts = new List<Statement>(); 233 bodyParts = new List<Statement>();
238 bodyParts.add(new VariableDeclarations(context.variables)); 234 bodyParts.add(new VariableDeclarations(context.variables));
(...skipping 27 matching lines...) Expand all
266 bool _recognizeTrailingReturn(Statement statement) { 262 bool _recognizeTrailingReturn(Statement statement) {
267 if (statement is Return) { 263 if (statement is Return) {
268 Expression expr = statement.expression; 264 Expression expr = statement.expression;
269 if (expr == null || expr is Literal && expr.value.isNull) { 265 if (expr == null || expr is Literal && expr.value.isNull) {
270 return true; 266 return true;
271 } 267 }
272 } 268 }
273 return false; 269 return false;
274 } 270 }
275 271
276 FunctionExpression emitConstructor(tree.ConstructorDefinition definition, 272 @override
277 BuilderContext<Statement> context) { 273 FunctionExpression visitConstructorDefinition(
274 tree.ConstructorDefinition definition,
275 BuilderContext<Statement> context) {
278 context.currentElement = definition.element; 276 context.currentElement = definition.element;
279 277
280 Parameters parameters = emitRootParameters(definition, context); 278 Parameters parameters = emitRootParameters(
279 definition, definition.defaultParameterValues, context);
281 280
282 // Declare parameters. 281 // Declare parameters.
283 for (tree.Variable param in definition.parameters) { 282 for (tree.Variable param in definition.parameters) {
284 context.variableNames[param] = param.element.name; 283 context.variableNames[param] = param.element.name;
285 context.usedVariableNames.add(param.element.name); 284 context.usedVariableNames.add(param.element.name);
286 context.declaredVariables.add(param); 285 context.declaredVariables.add(param);
287 } 286 }
288 287
289 List<Expression> initializers; 288 List<Initializer> initializers;
290 Statement body; 289 Statement body;
291 290
292 if (!definition.isAbstract) { 291 if (!definition.isEmpty) {
293 initializers = 292 initializers =
294 definition.initializers.map((tree.Initializer initializer) { 293 definition.initializers.map((tree.Initializer initializer) {
295 return visitExpression(initializer, context); 294 return visitInitializer(initializer, context);
296 }).toList(); 295 }).toList();
297 296
298 context.firstStatement = definition.body; 297 context.firstStatement = definition.body;
299 visitStatement(definition.body, context); 298 visitStatement(definition.body, context);
300 context.removeTrailingReturn(_recognizeTrailingReturn); 299 context.removeTrailingReturn(_recognizeTrailingReturn);
301 300
302 // Some of the variable declarations have already been added 301 // Some of the variable declarations have already been added
303 // if their first assignment could be pulled into the initializer. 302 // if their first assignment could be pulled into the initializer.
304 // Add the remaining variable declarations now. 303 // Add the remaining variable declarations now.
305 for (tree.Variable variable in context.variableNames.keys) { 304 for (tree.Variable variable in context.variableNames.keys) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 FunctionType functionType = context.currentElement.type; 336 FunctionType functionType = context.currentElement.type;
338 337
339 return new ConstructorDefinition( 338 return new ConstructorDefinition(
340 parameters, 339 parameters,
341 body, 340 body,
342 initializers, 341 initializers,
343 context.currentElement.name, definition.element.isConst) 342 context.currentElement.name, definition.element.isConst)
344 ..element = context.currentElement; 343 ..element = context.currentElement;
345 } 344 }
346 345
347 FunctionExpression emitFunction(tree.FunctionDefinition definition, 346 @override
348 BuilderContext<Statement> context) { 347 FunctionExpression visitFunctionDefinition(
348 tree.FunctionDefinition definition,
349 BuilderContext<Statement> context) {
349 context.currentElement = definition.element; 350 context.currentElement = definition.element;
350 351
351 Parameters parameters = emitRootParameters(definition, context); 352 Parameters parameters = emitRootParameters(
353 definition, definition.defaultParameterValues, context);
352 354
353 // Declare parameters. 355 // Declare parameters.
354 for (tree.Variable param in definition.parameters) { 356 for (tree.Variable param in definition.parameters) {
355 context.variableNames[param] = param.element.name; 357 context.variableNames[param] = param.element.name;
356 context.usedVariableNames.add(param.element.name); 358 context.usedVariableNames.add(param.element.name);
357 context.declaredVariables.add(param); 359 context.declaredVariables.add(param);
358 } 360 }
359 361
360 Statement body; 362 Statement body;
361 if (definition.isAbstract) { 363 if (definition.isEmpty) {
362 body = new EmptyStatement(); 364 body = new EmptyStatement();
363 } else { 365 } else {
364 context.firstStatement = definition.body; 366 context.firstStatement = definition.body;
365 visitStatement(definition.body, context); 367 visitStatement(definition.body, context);
366 context.removeTrailingReturn(_recognizeTrailingReturn); 368 context.removeTrailingReturn(_recognizeTrailingReturn);
367 369
368 // Some of the variable declarations have already been added 370 // Some of the variable declarations have already been added
369 // if their first assignment could be pulled into the initializer. 371 // if their first assignment could be pulled into the initializer.
370 // Add the remaining variable declarations now. 372 // Add the remaining variable declarations now.
371 for (tree.Variable variable in context.variableNames.keys) { 373 for (tree.Variable variable in context.variableNames.keys) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 body, 409 body,
408 name: context.currentElement.name, 410 name: context.currentElement.name,
409 returnType: TypeGenerator.createOptionalType(functionType.returnType), 411 returnType: TypeGenerator.createOptionalType(functionType.returnType),
410 isGetter: context.currentElement.isGetter, 412 isGetter: context.currentElement.isGetter,
411 isSetter: context.currentElement.isSetter) 413 isSetter: context.currentElement.isSetter)
412 ..element = context.currentElement; 414 ..element = context.currentElement;
413 } 415 }
414 416
415 /// Emits parameters that are not nested inside other parameters. 417 /// Emits parameters that are not nested inside other parameters.
416 /// Root parameters can have default values, while inner parameters cannot. 418 /// Root parameters can have default values, while inner parameters cannot.
417 Parameters emitRootParameters(tree.FunctionDefinition function, 419 Parameters emitRootParameters(tree.RootNode function,
420 List<ConstantExpression> defaults,
418 BuilderContext<Statement> context) { 421 BuilderContext<Statement> context) {
419 FunctionType functionType = function.element.type; 422 FunctionType functionType = function.element.type;
420 List<Parameter> required = TypeGenerator.createParameters( 423 List<Parameter> required = TypeGenerator.createParameters(
421 functionType.parameterTypes, 424 functionType.parameterTypes,
422 context: context, 425 context: context,
423 elements: function.parameters.map((p) => p.element)); 426 elements: function.parameters.map((p) => p.element));
424 bool optionalParametersAreNamed = !functionType.namedParameters.isEmpty; 427 bool optionalParametersAreNamed = !functionType.namedParameters.isEmpty;
425 List<Parameter> optional = TypeGenerator.createParameters( 428 List<Parameter> optional = TypeGenerator.createParameters(
426 optionalParametersAreNamed 429 optionalParametersAreNamed
427 ? functionType.namedParameterTypes 430 ? functionType.namedParameterTypes
428 : functionType.optionalParameterTypes, 431 : functionType.optionalParameterTypes,
429 context: context, 432 context: context,
430 defaultValues: function.defaultParameterValues, 433 defaultValues: defaults,
431 elements: function.parameters.skip(required.length) 434 elements: function.parameters.skip(required.length)
432 .map((p) => p.element)); 435 .map((p) => p.element));
433 return new Parameters(required, optional, optionalParametersAreNamed); 436 return new Parameters(required, optional, optionalParametersAreNamed);
434 } 437 }
435 438
436 /// True if the two expressions are a reference to the same variable. 439 /// True if the two expressions are a reference to the same variable.
437 bool isSameVariable(Receiver e1, Receiver e2) { 440 bool isSameVariable(Receiver e1, Receiver e2) {
438 return e1 is Identifier && 441 return e1 is Identifier &&
439 e2 is Identifier && 442 e2 is Identifier &&
440 e1.element is VariableElement && 443 e1.element is VariableElement &&
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 } 873 }
871 874
872 @override 875 @override
873 Expression visitVariableUse(tree.VariableUse exp, 876 Expression visitVariableUse(tree.VariableUse exp,
874 BuilderContext<Statement> context) { 877 BuilderContext<Statement> context) {
875 return context.makeVariableAccess(exp.variable); 878 return context.makeVariableAccess(exp.variable);
876 } 879 }
877 880
878 FunctionExpression makeSubFunction(tree.FunctionDefinition function, 881 FunctionExpression makeSubFunction(tree.FunctionDefinition function,
879 BuilderContext<Statement> context) { 882 BuilderContext<Statement> context) {
880 return emit(function, new BuilderContext<Statement>.inner(context)); 883 return visitFunctionDefinition(function,
884 new BuilderContext<Statement>.inner(context));
881 } 885 }
882 886
883 @override 887 @override
884 Expression visitFunctionExpression(tree.FunctionExpression exp, 888 Expression visitFunctionExpression(tree.FunctionExpression exp,
885 BuilderContext<Statement> context) { 889 BuilderContext<Statement> context) {
886 return makeSubFunction(exp.definition, context)..name = null; 890 return makeSubFunction(exp.definition, context)..name = null;
887 } 891 }
888 892
889 @override 893 @override
890 void visitFunctionDeclaration(tree.FunctionDeclaration node, 894 void visitFunctionDeclaration(tree.FunctionDeclaration node,
(...skipping 23 matching lines...) Expand all
914 bodyParts = new List<Statement>(); 918 bodyParts = new List<Statement>();
915 bodyParts.add(new VariableDeclarations(inner.variables)); 919 bodyParts.add(new VariableDeclarations(inner.variables));
916 bodyParts.addAll(inner.statements); 920 bodyParts.addAll(inner.statements);
917 } else { 921 } else {
918 bodyParts = inner.statements; 922 bodyParts = inner.statements;
919 } 923 }
920 return bodyParts; 924 return bodyParts;
921 } 925 }
922 926
923 @override 927 @override
924 Expression visitFieldInitializer(tree.FieldInitializer node, 928 Initializer visitFieldInitializer(tree.FieldInitializer node,
925 BuilderContext<Statement> context) { 929 BuilderContext<Statement> context) {
926 return new FieldInitializer(node.element, 930 return new FieldInitializer(node.element,
927 ensureExpression(buildInInitializerContext(node.body, context))); 931 ensureExpression(buildInInitializerContext(node.body, context)));
928 } 932 }
929 933
930 @override 934 @override
931 Expression visitSuperInitializer(tree.SuperInitializer node, 935 Initializer visitSuperInitializer(tree.SuperInitializer node,
932 BuilderContext<Statement> context) { 936 BuilderContext<Statement> context) {
933 List<Argument> arguments = node.arguments.map((tree.Statement argument) { 937 List<Argument> arguments = node.arguments.map((tree.Statement argument) {
934 return ensureExpression(buildInInitializerContext(argument, context)); 938 return ensureExpression(buildInInitializerContext(argument, context));
935 }).toList(); 939 }).toList();
936 return new SuperInitializer(node.target, 940 return new SuperInitializer(node.target,
937 emitArguments(arguments, node.selector)); 941 emitArguments(arguments, node.selector));
938 } 942 }
939 943
940 @override 944 @override
941 Expression visitTypeExpression(tree.TypeExpression node, arg) { 945 Expression visitTypeExpression(tree.TypeExpression node, arg) {
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
1251 1255
1252 /// Maps parameter names to their bindings. 1256 /// Maps parameter names to their bindings.
1253 Map<String, tree.Variable> environment = <String, tree.Variable>{}; 1257 Map<String, tree.Variable> environment = <String, tree.Variable>{};
1254 1258
1255 /// Parameters that are currently shadowed by another parameter. 1259 /// Parameters that are currently shadowed by another parameter.
1256 Set<tree.Variable> shadowedParameters = new Set<tree.Variable>(); 1260 Set<tree.Variable> shadowedParameters = new Set<tree.Variable>();
1257 1261
1258 /// Parameters that are used in a context where it is shadowed. 1262 /// Parameters that are used in a context where it is shadowed.
1259 Set<tree.Variable> hasShadowedUse = new Set<tree.Variable>(); 1263 Set<tree.Variable> hasShadowedUse = new Set<tree.Variable>();
1260 1264
1261 void unshadow(tree.ExecutableDefinition definition) { 1265 void unshadow(tree.RootNode definition) {
1262 // Fields have no parameters. 1266 if (definition.isEmpty) return;
1263 if (definition is tree.FieldDefinition) return; 1267 unshadowFunction(definition);
1264 visitFunctionDefinition(definition);
1265 } 1268 }
1266 1269
1267 visitFunctionDefinition(tree.FunctionDefinition definition) { 1270 void unshadowFunction(tree.RootNode definition) {
1268 if (definition.isAbstract) return;
1269 var oldShadow = shadowedParameters; 1271 var oldShadow = shadowedParameters;
1270 var oldEnvironment = environment; 1272 var oldEnvironment = environment;
1271 environment = new Map<String, tree.Variable>.from(environment); 1273 environment = new Map<String, tree.Variable>.from(environment);
1272 shadowedParameters = new Set<tree.Variable>.from(shadowedParameters); 1274 shadowedParameters = new Set<tree.Variable>.from(shadowedParameters);
1273 for (tree.Variable param in definition.parameters) { 1275 for (tree.Variable param in definition.parameters) {
1274 tree.Variable oldVariable = environment[param.element.name]; 1276 tree.Variable oldVariable = environment[param.element.name];
1275 if (oldVariable != null) { 1277 if (oldVariable != null) {
1276 shadowedParameters.add(oldVariable); 1278 shadowedParameters.add(oldVariable);
1277 } 1279 }
1278 environment[param.element.name] = param; 1280 environment[param.element.name] = param;
1279 } 1281 }
1280 visitStatement(definition.body); 1282 definition.forEachBody(visitStatement);
1281 environment = oldEnvironment; 1283 environment = oldEnvironment;
1282 shadowedParameters = oldShadow; 1284 shadowedParameters = oldShadow;
1283 1285
1284 for (int i=0; i<definition.parameters.length; i++) { 1286 for (int i=0; i<definition.parameters.length; i++) {
1285 tree.Variable param = definition.parameters[i]; 1287 tree.Variable param = definition.parameters[i];
1286 if (hasShadowedUse.remove(param)) { 1288 if (hasShadowedUse.remove(param)) {
1287 tree.Variable newParam = new tree.Variable(definition.element, 1289 tree.Variable newParam = new tree.Variable(definition.element,
1288 param.element); 1290 param.element);
1289 definition.parameters[i] = newParam; 1291 definition.parameters[i] = newParam;
1290 definition.body = new tree.Assign(param, new tree.VariableUse(newParam), 1292 definition.replaceEachBody((tree.Statement body) {
1291 definition.body); 1293 return new tree.Assign(param, new tree.VariableUse(newParam), body);
1294 });
1292 newParam.writeCount = 1; // Being a parameter counts as a write. 1295 newParam.writeCount = 1; // Being a parameter counts as a write.
1293 param.writeCount--; // Not a parameter anymore. 1296 param.writeCount--; // Not a parameter anymore.
1294 } 1297 }
1295 } 1298 }
1296 } 1299 }
1297 1300
1298 @override 1301 @override
1302 void visitInnerFunction(tree.FunctionDefinition definition) {
1303 unshadowFunction(definition);
1304 }
1305
1306 @override
1299 visitVariable(tree.Variable variable) { 1307 visitVariable(tree.Variable variable) {
1300 if (shadowedParameters.contains(variable)) { 1308 if (shadowedParameters.contains(variable)) {
1301 hasShadowedUse.add(variable); 1309 hasShadowedUse.add(variable);
1302 } 1310 }
1303 } 1311 }
1304 1312
1305 } 1313 }
1306 1314
1307 // TODO(johnniwinther): Remove this when the dart `backend_ast` does not need 1315 // TODO(johnniwinther): Remove this when the dart `backend_ast` does not need
1308 // [Element] for entities. 1316 // [Element] for entities.
1309 class _SyntheticLocalVariableElement extends modelx.VariableElementX 1317 class _SyntheticLocalVariableElement extends modelx.VariableElementX
1310 implements LocalVariableElement { 1318 implements LocalVariableElement {
1311 1319
1312 _SyntheticLocalVariableElement(String name, 1320 _SyntheticLocalVariableElement(String name,
1313 ExecutableElement enclosingElement, 1321 ExecutableElement enclosingElement,
1314 modelx.VariableList variables) 1322 modelx.VariableList variables)
1315 : super(name, ElementKind.VARIABLE, enclosingElement, variables, null); 1323 : super(name, ElementKind.VARIABLE, enclosingElement, variables, null);
1316 1324
1317 ExecutableElement get executableContext => enclosingElement; 1325 ExecutableElement get executableContext => enclosingElement;
1318 1326
1319 ExecutableElement get memberContext => executableContext.memberContext; 1327 ExecutableElement get memberContext => executableContext.memberContext;
1320 1328
1321 bool get isLocal => true; 1329 bool get isLocal => true;
1322 1330
1323 LibraryElement get implementationLibrary => enclosingElement.library; 1331 LibraryElement get implementationLibrary => enclosingElement.library;
1324 } 1332 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698