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

Side by Side Diff: pkg/compiler/lib/src/js_backend/codegen/codegen.dart

Issue 726543002: Add support for local variables(including parameters) to cps->js. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 6 years, 1 month 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 code_generator; 5 library code_generator;
6 6
7 import 'glue.dart'; 7 import 'glue.dart';
8 8
9 import '../../tree_ir/tree_ir_nodes.dart' as tree_ir; 9 import '../../tree_ir/tree_ir_nodes.dart' as tree_ir;
10 import '../../js/js.dart' as js; 10 import '../../js/js.dart' as js;
11 import '../../elements/elements.dart'; 11 import '../../elements/elements.dart';
12 import '../../util/maplet.dart'; 12 import '../../util/maplet.dart';
13 import '../../constants/values.dart'; 13 import '../../constants/values.dart';
14 import '../../dart2jslib.dart'; 14 import '../../dart2jslib.dart';
15 15
16 class CodegenBailout { 16 class CodegenBailout {
17 final tree_ir.Node node; 17 final tree_ir.Node node;
18 final String reason; 18 final String reason;
19 CodegenBailout(this.node, this.reason); 19 CodegenBailout(this.node, this.reason);
20 String get message { 20 String get message {
21 return 'bailout${node != null ? " on $node" : ""}: $reason'; 21 return 'bailout${node != null ? " on $node" : ""}: $reason';
22 } 22 }
23 } 23 }
24 24
25 class CodeGenerator extends tree_ir.Visitor<dynamic, js.Expression> { 25 class CodeGenerator extends tree_ir.Visitor<dynamic, js.Expression> {
26 final CodegenRegistry registry; 26 final CodegenRegistry registry;
27 27
28 final Glue glue; 28 final Glue glue;
29 29
30 /// Variables to be hoisted at the top of the current function. 30 ExecutableElement currentFunction;
31 List<js.VariableDeclaration> variables = <js.VariableDeclaration>[];
32 31
33 /// Maps variables to their name. 32 /// Maps variables to their name.
34 Map<tree_ir.Variable, String> variableNames = <tree_ir.Variable, String>{}; 33 Map<tree_ir.Variable, String> variableNames = <tree_ir.Variable, String>{};
35 34
36 /// Maps local constants to their name. 35 /// Maps local constants to their name.
37 Maplet<VariableElement, String> constantNames = 36 Maplet<VariableElement, String> constantNames =
38 new Maplet<VariableElement, String>(); 37 new Maplet<VariableElement, String>();
39 38
40 /// Variables that have had their declaration created.
41 Set<tree_ir.Variable> declaredVariables = new Set<tree_ir.Variable>();
42
43 /// Variable names that have already been used. Used to avoid name clashes. 39 /// Variable names that have already been used. Used to avoid name clashes.
44 Set<String> usedVariableNames; 40 Set<String> usedVariableNames = new Set<String>();
45 41
46 List<js.Parameter> parameters = new List<js.Parameter>(); 42 List<js.Parameter> parameters = new List<js.Parameter>();
47 List<js.Statement> accumulator = new List<js.Statement>(); 43 List<js.Statement> accumulator = new List<js.Statement>();
48 44
49 js.Block body; 45 js.Block body;
50 46
51 /// Generates JavaScript code for the body of [function]. 47 /// Generates JavaScript code for the body of [function].
52 /// The code will be in [body] and the parameters will be in [parameters]. 48 /// The code will be in [body] and the parameters will be in [parameters].
53 CodeGenerator(this.glue, this.registry); 49 CodeGenerator(this.glue, this.registry);
54 50
55 void buildFunction(tree_ir.FunctionDefinition function) { 51 void buildFunction(tree_ir.FunctionDefinition function) {
52 currentFunction = function.element;
56 visitStatement(function.body); 53 visitStatement(function.body);
57 for (tree_ir.Variable parameter in function.parameters) { 54 for (tree_ir.Variable parameter in function.parameters) {
58 parameters.add(new js.Parameter(variableNames[parameter])); 55 String name = getVariableName(parameter);
56 parameters.add(new js.Parameter(name));
57 }
58
59 List<js.VariableInitialization> jsVariables = <js.VariableInitialization>[];
60
61 for (tree_ir.Variable variable in variableNames.keys) {
62 String name = getVariableName(variable);
63 js.VariableInitialization jsVariable = new js.VariableInitialization(
64 new js.VariableDeclaration(name),
65 null);
66 jsVariables.add(jsVariable);
67 }
68
69 if (jsVariables.length > 0) {
70 // Would be nice to avoid inserting at the beginning of list.
71 accumulator.insert(0, new js.ExpressionStatement(
72 new js.VariableDeclarationList(jsVariables)));
59 } 73 }
60 body = new js.Block(accumulator); 74 body = new js.Block(accumulator);
61 } 75 }
62 76
77 /// Generates a name for the given variable. First trying with the name of
78 /// the [Variable.element] if it is non-null.
79 String getVariableName(tree_ir.Variable variable) {
80 // TODO(sigurdm): Handle case where the variable belongs to an enclosing
81 // function.
82 if (variable.host.element != currentFunction) giveup(variable);
83
84 // Get the name if we already have one.
85 String name = variableNames[variable];
86 if (name != null) {
87 return name;
88 }
89
90 // Synthesize a variable name that isn't used elsewhere.
91 // The [usedVariableNames] set is shared between nested emitters,
92 // so this also prevents clash with variables in an enclosing/inner scope.
93 // The renaming phase after codegen will further prefix local variables
94 // so they cannot clash with top-level variables or fields.
95 String prefix = variable.element == null ? 'v' : variable.element.name;
96 int counter = 0;
97 name = glue.safeVariableName(variable.element == null
98 ? '$prefix$counter'
99 : variable.element.name);
100 while (!usedVariableNames.add(name)) {
101 ++counter;
102 name = '$prefix$counter';
103 }
104 variableNames[variable] = name;
105
106 return name;
107 }
108
63 List<js.Expression> visitArguments(List<tree_ir.Expression> arguments) { 109 List<js.Expression> visitArguments(List<tree_ir.Expression> arguments) {
64 return arguments.map(visitExpression).toList(); 110 return arguments.map(visitExpression).toList();
65 } 111 }
66 112
67 giveup(tree_ir.Node node, 113 giveup(tree_ir.Node node,
68 [String reason = 'unimplemented in CodeGenerator']) { 114 [String reason = 'unimplemented in CodeGenerator']) {
69 throw new CodegenBailout(node, reason); 115 throw new CodegenBailout(node, reason);
70 } 116 }
71 117
72 @override 118 @override
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 } 205 }
160 206
161 @override 207 @override
162 js.Expression visitTypeOperator(tree_ir.TypeOperator node) { 208 js.Expression visitTypeOperator(tree_ir.TypeOperator node) {
163 return giveup(node); 209 return giveup(node);
164 // TODO: implement visitTypeOperator 210 // TODO: implement visitTypeOperator
165 } 211 }
166 212
167 @override 213 @override
168 js.Expression visitVariable(tree_ir.Variable node) { 214 js.Expression visitVariable(tree_ir.Variable node) {
169 return giveup(node); 215 return new js.VariableUse(getVariableName(node));
170 // TODO: implement visitVariable 216 // TODO: implement visitVariable
171 } 217 }
172 218
173 @override 219 @override
174 void visitContinue(tree_ir.Continue node) { 220 void visitContinue(tree_ir.Continue node) {
175 return giveup(node); 221 return giveup(node);
176 // TODO: implement visitContinue 222 // TODO: implement visitContinue
177 } 223 }
178 224
179 @override 225 @override
(...skipping 16 matching lines...) Expand all
196 } 242 }
197 243
198 @override 244 @override
199 void visitLabeledStatement(tree_ir.LabeledStatement node) { 245 void visitLabeledStatement(tree_ir.LabeledStatement node) {
200 giveup(node); 246 giveup(node);
201 // TODO: implement visitLabeledStatement 247 // TODO: implement visitLabeledStatement
202 } 248 }
203 249
204 @override 250 @override
205 void visitAssign(tree_ir.Assign node) { 251 void visitAssign(tree_ir.Assign node) {
206 giveup(node); 252
207 // TODO: implement visitAssign 253 bool isFirstOccurrence = (variableNames[node.variable] == null);
floitsch 2014/11/19 12:02:19 unused
sigurdm 2014/11/20 12:22:40 Fixed by https://codereview.chromium.org/737363002
254 bool isDeclaredHere = node.variable.host.element == currentFunction;
floitsch 2014/11/19 12:02:19 unused.
sigurdm 2014/11/20 12:22:40 Done.
255 String name = getVariableName(node.variable);
floitsch 2014/11/19 12:02:19 unused.
sigurdm 2014/11/20 12:22:40 Done.
256 tree_ir.Expression value = node.definition;
257 js.Expression definition = visitExpression(value);
258
259 accumulator.add(new js.ExpressionStatement(new js.Assignment(
260 visitVariable(node.variable),
261 definition)));
262 visitStatement(node.next);
208 } 263 }
209 264
210 @override 265 @override
211 void visitBreak(tree_ir.Break node) { 266 void visitBreak(tree_ir.Break node) {
212 giveup(node); 267 giveup(node);
213 // TODO: implement visitBreak 268 // TODO: implement visitBreak
214 } 269 }
215 270
216 @override 271 @override
217 void visitWhileCondition(tree_ir.WhileCondition node) { 272 void visitWhileCondition(tree_ir.WhileCondition node) {
218 giveup(node); 273 giveup(node);
219 // TODO: implement visitWhileCondition 274 // TODO: implement visitWhileCondition
220 } 275 }
221 276
222 @override 277 @override
223 void visitWhileTrue(tree_ir.WhileTrue node) { 278 void visitWhileTrue(tree_ir.WhileTrue node) {
224 giveup(node); 279 giveup(node);
225 // TODO: implement visitWhileTrue 280 // TODO: implement visitWhileTrue
226 } 281 }
227 282
228 @override 283 @override
229 void visitReturn(tree_ir.Return node) { 284 void visitReturn(tree_ir.Return node) {
230 if (node.value != null) { 285 if (node.value != null) {
231 accumulator.add(new js.Return(visitExpression(node.value))); 286 accumulator.add(new js.Return(visitExpression(node.value)));
232 } 287 }
233 } 288 }
289
290 bool isNullLiteral(js.Expression exp) => exp is js.LiteralNull;
291
234 } 292 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart ('k') | pkg/compiler/lib/src/js_backend/codegen/glue.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698