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

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

Issue 759193005: Add support for fields to the new dart backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase Created 6 years 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 Expression emit(tree.FunctionDefinition definition) { 18 ExecutableDefinition emit(tree.ExecutableDefinition definition) {
19 return new ASTEmitter().emit(definition); 19 return new ASTEmitter().emit(definition);
20 } 20 }
21 21
22 /// Translates the dart_tree IR to Dart backend AST. 22 /// Translates the dart_tree IR to Dart backend AST.
23 /// An instance of this class should only be used once; a fresh emitter 23 /// An instance of this class should only be used once; a fresh emitter
24 /// must be created for each function to be emitted. 24 /// must be created for each function to be emitted.
25 class ASTEmitter extends tree.Visitor<dynamic, Expression> { 25 class ASTEmitter extends tree.Visitor<dynamic, Expression> {
26 /// Variables to be hoisted at the top of the current function. 26 /// Variables to be hoisted at the top of the current function.
27 List<VariableDeclaration> variables = <VariableDeclaration>[]; 27 List<VariableDeclaration> variables = <VariableDeclaration>[];
28 28
29 /// Maps variables to their name. 29 /// Maps variables to their name.
30 Map<tree.Variable, String> variableNames = <tree.Variable, String>{}; 30 Map<tree.Variable, String> variableNames = <tree.Variable, String>{};
31 31
32 /// Maps local constants to their name. 32 /// Maps local constants to their name.
33 Map<VariableElement, String> constantNames = <VariableElement, String>{}; 33 Map<VariableElement, String> constantNames = <VariableElement, String>{};
34 34
35 /// Variables that have had their declaration created. 35 /// Variables that have had their declaration created.
36 Set<tree.Variable> declaredVariables = new Set<tree.Variable>(); 36 Set<tree.Variable> declaredVariables = new Set<tree.Variable>();
37 37
38 /// Variable names that have already been used. Used to avoid name clashes. 38 /// Variable names that have already been used. Used to avoid name clashes.
39 Set<String> usedVariableNames; 39 Set<String> usedVariableNames;
40 40
41 /// Statements emitted by the most recent call to [visitStatement]. 41 /// Statements emitted by the most recent call to [visitStatement].
42 List<Statement> statementBuffer = <Statement>[]; 42 List<Statement> statementBuffer = <Statement>[];
43 43
44 /// The function currently being emitted. 44 /// The element currently being emitted.
45 FunctionElement functionElement; 45 ExecutableElement currentElement;
46 46
47 /// Bookkeeping object needed to synthesize a variable declaration. 47 /// Bookkeeping object needed to synthesize a variable declaration.
48 modelx.VariableList variableList 48 modelx.VariableList variableList
49 = new modelx.VariableList(tree.Modifiers.EMPTY); 49 = new modelx.VariableList(tree.Modifiers.EMPTY);
50 50
51 /// Input to [visitStatement]. Denotes the statement that will execute next 51 /// Input to [visitStatement]. Denotes the statement that will execute next
52 /// if the statements produced by [visitStatement] complete normally. 52 /// if the statements produced by [visitStatement] complete normally.
53 /// Set to null if control will fall over the end of the method. 53 /// Set to null if control will fall over the end of the method.
54 tree.Statement fallthrough = null; 54 tree.Statement fallthrough = null;
55 55
56 /// Labels that could not be eliminated using fallthrough. 56 /// Labels that could not be eliminated using fallthrough.
57 Set<tree.Label> usedLabels = new Set<tree.Label>(); 57 Set<tree.Label> usedLabels = new Set<tree.Label>();
58 58
59 /// The first dart_tree statement that is not converted to a variable 59 /// The first dart_tree statement that is not converted to a variable
60 /// initializer. 60 /// initializer.
61 tree.Statement firstStatement; 61 tree.Statement firstStatement;
62 62
63 /// Emitter for the enclosing function, or null if the current function is 63 /// Emitter for the enclosing function, or null if the current function is
64 /// not a local function. 64 /// not a local function.
65 ASTEmitter parent; 65 ASTEmitter parent;
66 66
67 ASTEmitter() : usedVariableNames = new Set<String>(); 67 ASTEmitter() : usedVariableNames = new Set<String>();
68 68
69 ASTEmitter.inner(ASTEmitter parent) 69 ASTEmitter.inner(ASTEmitter parent)
70 : this.parent = parent, 70 : this.parent = parent,
71 usedVariableNames = parent.usedVariableNames; 71 usedVariableNames = parent.usedVariableNames;
72 72
73 FunctionExpression emit(tree.FunctionDefinition definition) { 73 ExecutableDefinition emit(tree.ExecutableDefinition definition) {
74 functionElement = definition.element; 74 if (definition is tree.FieldDefinition) {
75 return emitField(definition);
76 }
77 assert(definition is tree.FunctionDefinition);
78 return emitFunction(definition);
79 }
80
81 FieldDefinition emitField(tree.FieldDefinition definition) {
82 currentElement = definition.element;
83 visitStatement(definition.body);
84 List<Statement> bodyParts;
85 for (tree.Variable variable in variableNames.keys) {
86 if (!declaredVariables.contains(variable)) {
87 addDeclaration(variable);
88 }
89 }
90 if (variables.length > 0) {
91 bodyParts = new List<Statement>();
92 bodyParts.add(new VariableDeclarations(variables));
93 bodyParts.addAll(statementBuffer);
94 } else {
95 bodyParts = statementBuffer;
96 }
97
98 return new FieldDefinition(definition.element, ensureExpression(bodyParts));
99 }
100
101 /// Returns an expression that will evaluate all of [bodyParts].
102 /// If [bodyParts] is a single [Return] return its value.
103 /// Otherwise wrap the body-parts in an immediately invoked closure.
104 Expression ensureExpression(List<Statement> bodyParts) {
105 if (bodyParts.length == 1) {
106 Statement onlyStatement = bodyParts.single;
107 if (onlyStatement is Return) {
108 return onlyStatement.expression;
109 }
110 }
111 Statement body = new Block(bodyParts);
112 FunctionExpression function =
113 new FunctionExpression(new Parameters([]), body);
114 function.element = null;
115 return new CallFunction(function, []);
116 }
117
118 FunctionExpression emitFunction(tree.FunctionDefinition definition) {
119 currentElement = definition.element;
75 120
76 Parameters parameters = emitRootParameters(definition); 121 Parameters parameters = emitRootParameters(definition);
77 122
78 // Declare parameters. 123 // Declare parameters.
79 for (tree.Variable param in definition.parameters) { 124 for (tree.Variable param in definition.parameters) {
80 variableNames[param] = param.element.name; 125 variableNames[param] = param.element.name;
81 usedVariableNames.add(param.element.name); 126 usedVariableNames.add(param.element.name);
82 declaredVariables.add(param); 127 declaredVariables.add(param);
83 } 128 }
84 129
(...skipping 30 matching lines...) Expand all
115 if (constants.length > 0) { 160 if (constants.length > 0) {
116 bodyParts.add(new VariableDeclarations(constants, isConst: true)); 161 bodyParts.add(new VariableDeclarations(constants, isConst: true));
117 } 162 }
118 if (variables.length > 0) { 163 if (variables.length > 0) {
119 bodyParts.add(new VariableDeclarations(variables)); 164 bodyParts.add(new VariableDeclarations(variables));
120 } 165 }
121 bodyParts.addAll(statementBuffer); 166 bodyParts.addAll(statementBuffer);
122 167
123 body = new Block(bodyParts); 168 body = new Block(bodyParts);
124 } 169 }
125 FunctionType functionType = functionElement.type; 170 FunctionType functionType = currentElement.type;
126 171
127 return new FunctionExpression( 172 return new FunctionExpression(
128 parameters, 173 parameters,
129 body, 174 body,
130 name: functionElement.name, 175 name: currentElement.name,
131 returnType: emitOptionalType(functionType.returnType), 176 returnType: emitOptionalType(functionType.returnType),
132 isGetter: functionElement.isGetter, 177 isGetter: currentElement.isGetter,
133 isSetter: functionElement.isSetter) 178 isSetter: currentElement.isSetter)
134 ..element = functionElement; 179 ..element = currentElement;
135 } 180 }
136 181
137 void addDeclaration(tree.Variable variable, [Expression initializer]) { 182 void addDeclaration(tree.Variable variable, [Expression initializer]) {
138 assert(!declaredVariables.contains(variable)); 183 assert(!declaredVariables.contains(variable));
139 String name = getVariableName(variable); 184 String name = getVariableName(variable);
140 VariableDeclaration decl = new VariableDeclaration(name, initializer); 185 VariableDeclaration decl = new VariableDeclaration(name, initializer);
141 decl.element = variable.element; 186 decl.element = variable.element;
142 declaredVariables.add(variable); 187 declaredVariables.add(variable);
143 variables.add(decl); 188 variables.add(decl);
144 } 189 }
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 fallthrough = savedFallthrough; 342 fallthrough = savedFallthrough;
298 statementBuffer = savedBuffer; 343 statementBuffer = savedBuffer;
299 visitStatement(stmt.next); 344 visitStatement(stmt.next);
300 } 345 }
301 346
302 /// Generates a name for the given variable and synthesizes an element for it, 347 /// Generates a name for the given variable and synthesizes an element for it,
303 /// if necessary. 348 /// if necessary.
304 String getVariableName(tree.Variable variable) { 349 String getVariableName(tree.Variable variable) {
305 // If the variable belongs to an enclosing function, ask the parent emitter 350 // If the variable belongs to an enclosing function, ask the parent emitter
306 // for the variable name. 351 // for the variable name.
307 if (variable.host.element != functionElement) { 352 if (variable.host != currentElement) {
308 return parent.getVariableName(variable); 353 return parent.getVariableName(variable);
309 } 354 }
310 355
311 // Get the name if we already have one. 356 // Get the name if we already have one.
312 String name = variableNames[variable]; 357 String name = variableNames[variable];
313 if (name != null) { 358 if (name != null) {
314 return name; 359 return name;
315 } 360 }
316 361
317 // Synthesize a variable name that isn't used elsewhere. 362 // Synthesize a variable name that isn't used elsewhere.
318 // The [usedVariableNames] set is shared between nested emitters, 363 // The [usedVariableNames] set is shared between nested emitters,
319 // so this also prevents clash with variables in an enclosing/inner scope. 364 // so this also prevents clash with variables in an enclosing/inner scope.
320 // The renaming phase after codegen will further prefix local variables 365 // The renaming phase after codegen will further prefix local variables
321 // so they cannot clash with top-level variables or fields. 366 // so they cannot clash with top-level variables or fields.
322 String prefix = variable.element == null ? 'v' : variable.element.name; 367 String prefix = variable.element == null ? 'v' : variable.element.name;
323 int counter = 0; 368 int counter = 0;
324 name = variable.element == null ? '$prefix$counter' : variable.element.name; 369 name = variable.element == null ? '$prefix$counter' : variable.element.name;
325 while (!usedVariableNames.add(name)) { 370 while (!usedVariableNames.add(name)) {
326 ++counter; 371 ++counter;
327 name = '$prefix$counter'; 372 name = '$prefix$counter';
328 } 373 }
329 variableNames[variable] = name; 374 variableNames[variable] = name;
330 375
331 // Synthesize an element for the variable 376 // Synthesize an element for the variable
332 if (variable.element == null || name != variable.element.name) { 377 if (variable.element == null || name != variable.element.name) {
333 // TODO(johnniwinther): Replace by synthetic [Entity]. 378 // TODO(johnniwinther): Replace by synthetic [Entity].
334 variable.element = new _SyntheticLocalVariableElement( 379 variable.element = new _SyntheticLocalVariableElement(
335 name, 380 name,
336 functionElement, 381 currentElement,
337 variableList); 382 variableList);
338 } 383 }
339 return name; 384 return name;
340 } 385 }
341 386
342 String getConstantName(VariableElement element) { 387 String getConstantName(VariableElement element) {
343 assert(element.kind == ElementKind.VARIABLE); 388 assert(element.kind == ElementKind.VARIABLE);
344 if (element.enclosingElement != functionElement) { 389 if (element.enclosingElement != currentElement) {
345 return parent.getConstantName(element); 390 return parent.getConstantName(element);
346 } 391 }
347 String name = constantNames[element]; 392 String name = constantNames[element];
348 if (name != null) { 393 if (name != null) {
349 return name; 394 return name;
350 } 395 }
351 String prefix = element.name; 396 String prefix = element.name;
352 int counter = 0; 397 int counter = 0;
353 name = element.name; 398 name = element.name;
354 while (!usedVariableNames.add(name)) { 399 while (!usedVariableNames.add(name)) {
(...skipping 15 matching lines...) Expand all
370 tree.FunctionExpression functionExp = stmt.definition; 415 tree.FunctionExpression functionExp = stmt.definition;
371 FunctionExpression function = makeSubFunction(functionExp.definition); 416 FunctionExpression function = makeSubFunction(functionExp.definition);
372 FunctionDeclaration decl = new FunctionDeclaration(function); 417 FunctionDeclaration decl = new FunctionDeclaration(function);
373 statementBuffer.add(decl); 418 statementBuffer.add(decl);
374 declaredVariables.add(stmt.variable); 419 declaredVariables.add(stmt.variable);
375 visitStatement(stmt.next); 420 visitStatement(stmt.next);
376 return; 421 return;
377 } 422 }
378 423
379 bool isFirstOccurrence = (variableNames[stmt.variable] == null); 424 bool isFirstOccurrence = (variableNames[stmt.variable] == null);
380 bool isDeclaredHere = stmt.variable.host.element == functionElement; 425 bool isDeclaredHere = stmt.variable.host == currentElement;
381 String name = getVariableName(stmt.variable); 426 String name = getVariableName(stmt.variable);
382 Expression definition = visitExpression(stmt.definition); 427 Expression definition = visitExpression(stmt.definition);
383 428
384 // Try to pull into initializer. 429 // Try to pull into initializer.
385 if (firstStatement == stmt && isFirstOccurrence && isDeclaredHere) { 430 if (firstStatement == stmt && isFirstOccurrence && isDeclaredHere) {
386 if (isNullLiteral(definition)) definition = null; 431 if (isNullLiteral(definition)) definition = null;
387 addDeclaration(stmt.variable, definition); 432 addDeclaration(stmt.variable, definition);
388 firstStatement = stmt.next; 433 firstStatement = stmt.next;
389 visitStatement(stmt.next); 434 visitStatement(stmt.next);
390 return; 435 return;
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 896
852 /// Maps parameter names to their bindings. 897 /// Maps parameter names to their bindings.
853 Map<String, tree.Variable> environment = <String, tree.Variable>{}; 898 Map<String, tree.Variable> environment = <String, tree.Variable>{};
854 899
855 /// Parameters that are currently shadowed by another parameter. 900 /// Parameters that are currently shadowed by another parameter.
856 Set<tree.Variable> shadowedParameters = new Set<tree.Variable>(); 901 Set<tree.Variable> shadowedParameters = new Set<tree.Variable>();
857 902
858 /// Parameters that are used in a context where it is shadowed. 903 /// Parameters that are used in a context where it is shadowed.
859 Set<tree.Variable> hasShadowedUse = new Set<tree.Variable>(); 904 Set<tree.Variable> hasShadowedUse = new Set<tree.Variable>();
860 905
861 void unshadow(tree.FunctionDefinition definition) { 906 void unshadow(tree.ExecutableDefinition definition) {
862 if (definition.isAbstract) return; 907 // Fields have no parameters.
863 908 if (definition is tree.FieldDefinition) return;
864 visitFunctionDefinition(definition); 909 visitFunctionDefinition(definition);
865 } 910 }
866 911
867 visitFunctionDefinition(tree.FunctionDefinition definition) { 912 visitFunctionDefinition(tree.FunctionDefinition definition) {
913 if (definition.isAbstract) return;
868 var oldShadow = shadowedParameters; 914 var oldShadow = shadowedParameters;
869 var oldEnvironment = environment; 915 var oldEnvironment = environment;
870 environment = new Map<String, tree.Variable>.from(environment); 916 environment = new Map<String, tree.Variable>.from(environment);
871 shadowedParameters = new Set<tree.Variable>.from(shadowedParameters); 917 shadowedParameters = new Set<tree.Variable>.from(shadowedParameters);
872 for (tree.Variable param in definition.parameters) { 918 for (tree.Variable param in definition.parameters) {
873 tree.Variable oldVariable = environment[param.element.name]; 919 tree.Variable oldVariable = environment[param.element.name];
874 if (oldVariable != null) { 920 if (oldVariable != null) {
875 shadowedParameters.add(oldVariable); 921 shadowedParameters.add(oldVariable);
876 } 922 }
877 environment[param.element.name] = param; 923 environment[param.element.name] = param;
878 } 924 }
879 visitStatement(definition.body); 925 visitStatement(definition.body);
880 environment = oldEnvironment; 926 environment = oldEnvironment;
881 shadowedParameters = oldShadow; 927 shadowedParameters = oldShadow;
882 928
883 for (int i=0; i<definition.parameters.length; i++) { 929 for (int i=0; i<definition.parameters.length; i++) {
884 tree.Variable param = definition.parameters[i]; 930 tree.Variable param = definition.parameters[i];
885 if (hasShadowedUse.remove(param)) { 931 if (hasShadowedUse.remove(param)) {
886 tree.Variable newParam = new tree.Variable(definition, param.element); 932 tree.Variable newParam = new tree.Variable(definition.element,
933 param.element);
887 definition.parameters[i] = newParam; 934 definition.parameters[i] = newParam;
888 definition.body = new tree.Assign(param, newParam, definition.body); 935 definition.body = new tree.Assign(param, newParam, definition.body);
889 newParam.writeCount = 1; // Being a parameter counts as a write. 936 newParam.writeCount = 1; // Being a parameter counts as a write.
890 } 937 }
891 } 938 }
892 } 939 }
893 940
894 visitVariable(tree.Variable variable) { 941 visitVariable(tree.Variable variable) {
895 if (shadowedParameters.contains(variable)) { 942 if (shadowedParameters.contains(variable)) {
896 hasShadowedUse.add(variable); 943 hasShadowedUse.add(variable);
(...skipping 13 matching lines...) Expand all
910 : super(name, ElementKind.VARIABLE, enclosingElement, variables, null); 957 : super(name, ElementKind.VARIABLE, enclosingElement, variables, null);
911 958
912 ExecutableElement get executableContext => enclosingElement; 959 ExecutableElement get executableContext => enclosingElement;
913 960
914 ExecutableElement get memberContext => executableContext.memberContext; 961 ExecutableElement get memberContext => executableContext.memberContext;
915 962
916 bool get isLocal => true; 963 bool get isLocal => true;
917 964
918 LibraryElement get implementationLibrary => enclosingElement.library; 965 LibraryElement get implementationLibrary => enclosingElement.library;
919 } 966 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/dart_backend/backend.dart ('k') | pkg/compiler/lib/src/dart_backend/backend_ast_nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698