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 dart2js.ir_nodes_sexpr; | 5 library dart2js.ir_nodes_sexpr; |
6 | 6 |
7 import '../util/util.dart'; | 7 import '../util/util.dart'; |
8 import 'cps_ir_nodes.dart'; | 8 import 'cps_ir_nodes.dart'; |
9 | 9 |
10 /// A [Decorator] is a function used by [SExpressionStringifier] to augment the | 10 /// A [Decorator] is a function used by [SExpressionStringifier] to augment the |
11 /// output produced for a node. It can be provided to the constructor. | 11 /// output produced for a node. It can be provided to the constructor. |
12 typedef String Decorator(Node node, String s); | 12 typedef String Decorator(Node node, String s); |
13 | 13 |
14 /// Generate a Lisp-like S-expression representation of an IR node as a string. | 14 /// Generate a Lisp-like S-expression representation of an IR node as a string. |
15 class SExpressionStringifier extends Visitor<String> with Indentation { | 15 class SExpressionStringifier extends Visitor<String> with Indentation { |
16 final _Namer namer = new _Namer(); | 16 final _Namer namer = new _Namer(); |
17 | 17 |
18 String newValueName(Node node) => namer.defineValueName(node); | 18 String newValueName(Node node) => namer.defineValueName(node); |
19 String newContinuationName(Node node) => namer.defineContinuationName(node); | 19 String newContinuationName(Node node) => namer.defineContinuationName(node); |
20 final Decorator decorator; | 20 final Decorator decorator; |
21 | 21 |
22 SExpressionStringifier([this.decorator]); | 22 SExpressionStringifier([this.decorator]); |
23 | 23 |
24 String access(Reference<Definition> r) => namer.getName(r.definition); | 24 String access(Reference<Definition> r) => namer.getName(r.definition); |
25 | 25 |
26 String visitParameter(Parameter node) { | 26 String visitParameter(Parameter node) { |
27 return namer.useElementName(node); | 27 return namer.useElementName(node); |
28 } | 28 } |
29 | 29 |
| 30 String visitClosureVariable(ClosureVariable node) { |
| 31 return namer.getName(node); |
| 32 } |
| 33 |
30 /// Main entry point for creating a [String] from a [Node]. All recursive | 34 /// Main entry point for creating a [String] from a [Node]. All recursive |
31 /// calls must go through this method. | 35 /// calls must go through this method. |
32 String visit(Node node) { | 36 String visit(Node node) { |
33 String s = super.visit(node); | 37 String s = super.visit(node); |
34 return (decorator == null) ? s : decorator(node, s); | 38 return (decorator == null) ? s : decorator(node, s); |
35 } | 39 } |
36 | 40 |
37 String visitFunctionDefinition(FunctionDefinition node) { | 41 String visitFunctionDefinition(FunctionDefinition node) { |
38 String name = node.element.name; | 42 String name = node.element.name; |
39 namer.useReturnName(node.returnContinuation); | 43 namer.useReturnName(node.returnContinuation); |
| 44 String closureVariables = node.closureVariables.isEmpty |
| 45 ? '' |
| 46 : '{${node.closureVariables.map(namer.defineClosureName).join(' ')}} '; |
40 String parameters = node.parameters.map(visit).join(' '); | 47 String parameters = node.parameters.map(visit).join(' '); |
41 String body = indentBlock(() => visit(node.body)); | 48 String body = indentBlock(() => visit(node.body)); |
42 return '$indentation(FunctionDefinition $name ($parameters return)\n' | 49 return '$indentation(FunctionDefinition $name $closureVariables' |
43 '$body)'; | 50 '($parameters return)\n$body)'; |
44 } | 51 } |
45 | 52 |
46 String visitFieldDefinition(FieldDefinition node) { | 53 String visitFieldDefinition(FieldDefinition node) { |
47 String name = node.element.name; | 54 String name = node.element.name; |
48 if (node.hasInitializer) { | 55 if (node.hasInitializer) { |
49 namer.useReturnName(node.returnContinuation); | 56 namer.useReturnName(node.returnContinuation); |
50 String body = indentBlock(() => visit(node.body)); | 57 String body = indentBlock(() => visit(node.body)); |
51 return '$indentation(FieldDefinition $name (return)\n' | 58 return '$indentation(FieldDefinition $name (return)\n' |
52 '$body)'; | 59 '$body)'; |
53 } else { | 60 } else { |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 String function = indentBlock(() => visit(node.definition)); | 169 String function = indentBlock(() => visit(node.definition)); |
163 return '(CreateFunction\n$function)'; | 170 return '(CreateFunction\n$function)'; |
164 } | 171 } |
165 | 172 |
166 String visitContinuation(Continuation node) { | 173 String visitContinuation(Continuation node) { |
167 // Continuations are visited directly in visitLetCont. | 174 // Continuations are visited directly in visitLetCont. |
168 return '(Unexpected Continuation)'; | 175 return '(Unexpected Continuation)'; |
169 } | 176 } |
170 | 177 |
171 String visitGetClosureVariable(GetClosureVariable node) { | 178 String visitGetClosureVariable(GetClosureVariable node) { |
172 return '(GetClosureVariable ${node.variable.name})'; | 179 return '(GetClosureVariable ${visit(node.variable.definition)})'; |
173 } | 180 } |
174 | 181 |
175 String visitSetClosureVariable(SetClosureVariable node) { | 182 String visitSetClosureVariable(SetClosureVariable node) { |
176 String value = access(node.value); | 183 String value = access(node.value); |
177 String body = indentBlock(() => visit(node.body)); | 184 String body = indentBlock(() => visit(node.body)); |
178 return '$indentation(SetClosureVariable ${node.variable.name} $value\n' | 185 return '$indentation(SetClosureVariable ${visit(node.variable.definition)} ' |
179 '$body)'; | 186 '$value\n$body)'; |
180 } | 187 } |
181 | 188 |
182 String visitTypeOperator(TypeOperator node) { | 189 String visitTypeOperator(TypeOperator node) { |
183 String receiver = access(node.receiver); | 190 String receiver = access(node.receiver); |
184 String cont = access(node.continuation); | 191 String cont = access(node.continuation); |
185 String operator = node.isTypeTest ? 'is' : 'as'; | 192 String operator = node.isTypeTest ? 'is' : 'as'; |
186 return '$indentation(TypeOperator $operator $receiver ${node.type} $cont)'; | 193 return '$indentation(TypeOperator $operator $receiver ${node.type} $cont)'; |
187 } | 194 } |
188 | 195 |
189 String visitLiteralList(LiteralList node) { | 196 String visitLiteralList(LiteralList node) { |
190 String values = node.values.map(access).join(' '); | 197 String values = node.values.map(access).join(' '); |
191 return '(LiteralList ($values))'; | 198 return '(LiteralList ($values))'; |
192 } | 199 } |
193 | 200 |
194 String visitLiteralMap(LiteralMap node) { | 201 String visitLiteralMap(LiteralMap node) { |
195 String keys = node.entries.map((e) => access(e.key)).join(' '); | 202 String keys = node.entries.map((e) => access(e.key)).join(' '); |
196 String values = node.entries.map((e) => access(e.value)).join(' '); | 203 String values = node.entries.map((e) => access(e.value)).join(' '); |
197 return '(LiteralMap ($keys) ($values))'; | 204 return '(LiteralMap ($keys) ($values))'; |
198 } | 205 } |
199 | 206 |
200 String visitDeclareFunction(DeclareFunction node) { | 207 String visitDeclareFunction(DeclareFunction node) { |
201 String function = indentBlock(() => visit(node.definition)); | 208 String function = indentBlock(() => visit(node.definition)); |
202 String body = indentBlock(() => visit(node.body)); | 209 String body = indentBlock(() => visit(node.body)); |
203 return '$indentation(DeclareFunction ${node.variable.name} =\n' | 210 String name = namer.getName(node.variable.definition); |
| 211 return '$indentation(DeclareFunction $name =\n' |
204 '$function in\n' | 212 '$function in\n' |
205 '$body)'; | 213 '$body)'; |
206 } | 214 } |
207 | 215 |
208 String visitIsTrue(IsTrue node) { | 216 String visitIsTrue(IsTrue node) { |
209 String value = access(node.value); | 217 String value = access(node.value); |
210 return '(IsTrue $value)'; | 218 return '(IsTrue $value)'; |
211 } | 219 } |
212 | 220 |
213 String visitIdentical(Identical node) { | 221 String visitIdentical(Identical node) { |
214 String left = access(node.left); | 222 String left = access(node.left); |
215 String right = access(node.right); | 223 String right = access(node.right); |
216 return '(Identical $left $right)'; | 224 return '(Identical $left $right)'; |
217 } | 225 } |
218 } | 226 } |
219 | 227 |
220 class _Namer { | 228 class _Namer { |
221 final Map<Node, String> _names = <Node, String>{}; | 229 final Map<Node, String> _names = <Node, String>{}; |
222 int _valueCounter = 0; | 230 int _valueCounter = 0; |
223 int _continuationCounter = 0; | 231 int _continuationCounter = 0; |
224 | 232 |
225 String useElementName(Parameter parameter) { | 233 String useElementName(Parameter parameter) { |
226 assert(!_names.containsKey(parameter)); | 234 assert(!_names.containsKey(parameter)); |
227 return _names[parameter] = parameter.hint.name; | 235 return _names[parameter] = parameter.hint.name; |
228 } | 236 } |
229 | 237 |
| 238 String defineClosureName(ClosureVariable variable) { |
| 239 assert(!_names.containsKey(variable)); |
| 240 return _names[variable] = variable.hint.name; |
| 241 } |
| 242 |
230 String defineContinuationName(Node node) { | 243 String defineContinuationName(Node node) { |
231 assert(!_names.containsKey(node)); | 244 assert(!_names.containsKey(node)); |
232 return _names[node] = 'k${_continuationCounter++}'; | 245 return _names[node] = 'k${_continuationCounter++}'; |
233 } | 246 } |
234 | 247 |
235 String defineValueName(Node node) { | 248 String defineValueName(Node node) { |
236 assert(!_names.containsKey(node)); | 249 assert(!_names.containsKey(node)); |
237 return _names[node] = 'v${_valueCounter++}'; | 250 return _names[node] = 'v${_valueCounter++}'; |
238 } | 251 } |
239 | 252 |
240 String useReturnName(Continuation node) { | 253 String useReturnName(Continuation node) { |
241 assert(!_names.containsKey(node) || _names[node] == 'return'); | 254 assert(!_names.containsKey(node) || _names[node] == 'return'); |
242 return _names[node] = 'return'; | 255 return _names[node] = 'return'; |
243 } | 256 } |
244 | 257 |
245 String getName(Node node) { | 258 String getName(Node node) { |
246 assert(_names.containsKey(node)); | 259 assert(_names.containsKey(node)); |
247 return _names[node]; | 260 return _names[node]; |
248 } | 261 } |
249 } | 262 } |
OLD | NEW |