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 '../constants/values.dart'; | 7 import '../constants/values.dart'; |
8 import '../util/util.dart'; | 8 import '../util/util.dart'; |
9 import 'cps_ir_nodes.dart'; | 9 import 'cps_ir_nodes.dart'; |
10 import '../universe/call_structure.dart' show | 10 import '../universe/call_structure.dart' show CallStructure; |
11 CallStructure; | |
12 | 11 |
13 /// A [Decorator] is a function used by [SExpressionStringifier] to augment the | 12 /// A [Decorator] is a function used by [SExpressionStringifier] to augment the |
14 /// output produced for a node or reference. It can be provided to the | 13 /// output produced for a node or reference. It can be provided to the |
15 /// constructor. | 14 /// constructor. |
16 typedef String Decorator(node, String s); | 15 typedef String Decorator(node, String s); |
17 | 16 |
18 /// Generate a Lisp-like S-expression representation of an IR node as a string. | 17 /// Generate a Lisp-like S-expression representation of an IR node as a string. |
19 class SExpressionStringifier extends Indentation implements Visitor<String> { | 18 class SExpressionStringifier extends Indentation implements Visitor<String> { |
20 final _Namer namer = new _Namer(); | 19 final _Namer namer = new _Namer(); |
21 | 20 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 return '$indentation(LetHandler (($parameters)\n$handlerBody)\n$body)'; | 170 return '$indentation(LetHandler (($parameters)\n$handlerBody)\n$body)'; |
172 } | 171 } |
173 | 172 |
174 String visitLetMutable(LetMutable node) { | 173 String visitLetMutable(LetMutable node) { |
175 String name = visit(node.variable); | 174 String name = visit(node.variable); |
176 String value = access(node.valueRef); | 175 String value = access(node.valueRef); |
177 String body = indentBlock(() => visit(node.body)); | 176 String body = indentBlock(() => visit(node.body)); |
178 return '$indentation(LetMutable ($name $value)\n$body)'; | 177 return '$indentation(LetMutable ($name $value)\n$body)'; |
179 } | 178 } |
180 | 179 |
181 String formatArguments(CallStructure call, | 180 String formatArguments( |
182 List<Reference<Primitive>> arguments, | 181 CallStructure call, List<Reference<Primitive>> arguments, |
183 [CallingConvention callingConvention = CallingConvention.Normal]) { | 182 [CallingConvention callingConvention = CallingConvention.Normal]) { |
184 int positionalArgumentCount = call.positionalArgumentCount; | 183 int positionalArgumentCount = call.positionalArgumentCount; |
185 List<String> args = | 184 List<String> args = |
186 arguments.take(positionalArgumentCount).map(access).toList(); | 185 arguments.take(positionalArgumentCount).map(access).toList(); |
187 List<String> argumentNames = call.getOrderedNamedArguments(); | 186 List<String> argumentNames = call.getOrderedNamedArguments(); |
188 for (int i = 0; i < argumentNames.length; ++i) { | 187 for (int i = 0; i < argumentNames.length; ++i) { |
189 String name = argumentNames[i]; | 188 String name = argumentNames[i]; |
190 String arg = access(arguments[positionalArgumentCount + i]); | 189 String arg = access(arguments[positionalArgumentCount + i]); |
191 args.add("($name: $arg)"); | 190 args.add("($name: $arg)"); |
192 } | 191 } |
193 // Constructors can have type parameter after the named arguments. | 192 // Constructors can have type parameter after the named arguments. |
194 args.addAll( | 193 args.addAll(arguments |
195 arguments.skip(positionalArgumentCount + argumentNames.length) | 194 .skip(positionalArgumentCount + argumentNames.length) |
196 .map(access)); | 195 .map(access)); |
197 return '(${args.join(' ')})'; | 196 return '(${args.join(' ')})'; |
198 } | 197 } |
199 | 198 |
200 String visitInvokeStatic(InvokeStatic node) { | 199 String visitInvokeStatic(InvokeStatic node) { |
201 String name = node.target.name; | 200 String name = node.target.name; |
202 String args = formatArguments(node.selector.callStructure, node.argumentRefs
); | 201 String args = |
| 202 formatArguments(node.selector.callStructure, node.argumentRefs); |
203 return '(InvokeStatic $name $args)'; | 203 return '(InvokeStatic $name $args)'; |
204 } | 204 } |
205 | 205 |
206 String visitInvokeMethod(InvokeMethod node) { | 206 String visitInvokeMethod(InvokeMethod node) { |
207 String name = node.selector.name; | 207 String name = node.selector.name; |
208 String interceptor = optionalAccess(node.interceptorRef); | 208 String interceptor = optionalAccess(node.interceptorRef); |
209 String receiver = access(node.receiverRef); | 209 String receiver = access(node.receiverRef); |
210 String arguments = formatArguments(node.selector.callStructure, | 210 String arguments = formatArguments( |
211 node.argumentRefs, node.callingConvention); | 211 node.selector.callStructure, node.argumentRefs, node.callingConvention); |
212 return '(InvokeMethod $interceptor $receiver $name $arguments)'; | 212 return '(InvokeMethod $interceptor $receiver $name $arguments)'; |
213 } | 213 } |
214 | 214 |
215 String visitInvokeMethodDirectly(InvokeMethodDirectly node) { | 215 String visitInvokeMethodDirectly(InvokeMethodDirectly node) { |
216 String interceptor = optionalAccess(node.interceptorRef); | 216 String interceptor = optionalAccess(node.interceptorRef); |
217 String receiver = access(node.receiverRef); | 217 String receiver = access(node.receiverRef); |
218 String name = node.selector.name; | 218 String name = node.selector.name; |
219 String arguments = formatArguments(node.selector.callStructure, | 219 String arguments = formatArguments( |
220 node.argumentRefs, node.callingConvention); | 220 node.selector.callStructure, node.argumentRefs, node.callingConvention); |
221 return '(InvokeMethodDirectly $interceptor $receiver $name $arguments)'; | 221 return '(InvokeMethodDirectly $interceptor $receiver $name $arguments)'; |
222 } | 222 } |
223 | 223 |
224 String visitInvokeConstructor(InvokeConstructor node) { | 224 String visitInvokeConstructor(InvokeConstructor node) { |
225 // TODO(karlklose): for illegal nodes constructed for tests or unresolved | 225 // TODO(karlklose): for illegal nodes constructed for tests or unresolved |
226 // constructor calls in the DartBackend, we get an element with no enclosing | 226 // constructor calls in the DartBackend, we get an element with no enclosing |
227 // class. Clean this up by introducing a name field to the node and | 227 // class. Clean this up by introducing a name field to the node and |
228 // removing [ErroneousElement]s from the IR. | 228 // removing [ErroneousElement]s from the IR. |
229 String name = node.dartType != null | 229 String name = node.dartType != null |
230 ? node.dartType.toString() | 230 ? node.dartType.toString() |
231 : node.target.enclosingClass.name; | 231 : node.target.enclosingClass.name; |
232 if (!node.target.name.isEmpty) { | 232 if (!node.target.name.isEmpty) { |
233 name = '${name}.${node.target.name}'; | 233 name = '${name}.${node.target.name}'; |
234 } | 234 } |
235 String args = formatArguments(node.selector.callStructure, node.argumentRefs
); | 235 String args = |
| 236 formatArguments(node.selector.callStructure, node.argumentRefs); |
236 return '(InvokeConstructor $name $args)'; | 237 return '(InvokeConstructor $name $args)'; |
237 } | 238 } |
238 | 239 |
239 String visitInvokeContinuation(InvokeContinuation node) { | 240 String visitInvokeContinuation(InvokeContinuation node) { |
240 String name = access(node.continuationRef); | 241 String name = access(node.continuationRef); |
241 if (node.isRecursive) name = 'rec $name'; | 242 if (node.isRecursive) name = 'rec $name'; |
242 String args = node.argumentRefs == null | 243 String args = node.argumentRefs == null |
243 ? '**** NULL ****' | 244 ? '**** NULL ****' |
244 » : node.argumentRefs.map(access).join(' '); | 245 : node.argumentRefs.map(access).join(' '); |
245 String escaping = node.isEscapingTry ? ' escape' : ''; | 246 String escaping = node.isEscapingTry ? ' escape' : ''; |
246 return '$indentation(InvokeContinuation $name ($args)$escaping)'; | 247 return '$indentation(InvokeContinuation $name ($args)$escaping)'; |
247 } | 248 } |
248 | 249 |
249 String visitThrow(Throw node) { | 250 String visitThrow(Throw node) { |
250 String value = access(node.valueRef); | 251 String value = access(node.valueRef); |
251 return '$indentation(Throw $value)'; | 252 return '$indentation(Throw $value)'; |
252 } | 253 } |
253 | 254 |
254 String visitRethrow(Rethrow node) { | 255 String visitRethrow(Rethrow node) { |
255 return '$indentation(Rethrow)'; | 256 return '$indentation(Rethrow)'; |
256 } | 257 } |
257 | 258 |
258 String visitBranch(Branch node) { | 259 String visitBranch(Branch node) { |
259 String condition = access(node.conditionRef); | 260 String condition = access(node.conditionRef); |
260 assert(isBranchTarget(node.trueContinuation)); | 261 assert(isBranchTarget(node.trueContinuation)); |
261 assert(isBranchTarget(node.falseContinuation)); | 262 assert(isBranchTarget(node.falseContinuation)); |
262 String trueCont = | 263 String trueCont = indentBlock(() => visit(node.trueContinuation)); |
263 indentBlock(() => visit(node.trueContinuation)); | 264 String falseCont = indentBlock(() => visit(node.falseContinuation)); |
264 String falseCont = | |
265 indentBlock(() => visit(node.falseContinuation)); | |
266 String strict = node.isStrictCheck ? 'Strict' : 'NonStrict'; | 265 String strict = node.isStrictCheck ? 'Strict' : 'NonStrict'; |
267 return '$indentation(Branch $strict $condition\n$trueCont\n$falseCont)'; | 266 return '$indentation(Branch $strict $condition\n$trueCont\n$falseCont)'; |
268 } | 267 } |
269 | 268 |
270 String visitUnreachable(Unreachable node) { | 269 String visitUnreachable(Unreachable node) { |
271 return '$indentation(Unreachable)'; | 270 return '$indentation(Unreachable)'; |
272 } | 271 } |
273 | 272 |
274 String visitConstant(Constant node) { | 273 String visitConstant(Constant node) { |
275 String value = node.value.accept(new ConstantStringifier(), null); | 274 String value = node.value.accept(new ConstantStringifier(), null); |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 String visitBool(BoolConstantValue constant, _) { | 486 String visitBool(BoolConstantValue constant, _) { |
488 return '(Bool ${constant.unparse()})'; | 487 return '(Bool ${constant.unparse()})'; |
489 } | 488 } |
490 | 489 |
491 String visitString(StringConstantValue constant, _) { | 490 String visitString(StringConstantValue constant, _) { |
492 return '(String ${constant.unparse()})'; | 491 return '(String ${constant.unparse()})'; |
493 } | 492 } |
494 | 493 |
495 String visitList(ListConstantValue constant, _) { | 494 String visitList(ListConstantValue constant, _) { |
496 String entries = | 495 String entries = |
497 constant.entries.map((entry) => entry.accept(this, _)).join(' '); | 496 constant.entries.map((entry) => entry.accept(this, _)).join(' '); |
498 return '(List $entries)'; | 497 return '(List $entries)'; |
499 } | 498 } |
500 | 499 |
501 String visitMap(MapConstantValue constant, _) { | 500 String visitMap(MapConstantValue constant, _) { |
502 List<String> elements = <String>[]; | 501 List<String> elements = <String>[]; |
503 for (int i = 0; i < constant.keys.length; ++i) { | 502 for (int i = 0; i < constant.keys.length; ++i) { |
504 ConstantValue key = constant.keys[i]; | 503 ConstantValue key = constant.keys[i]; |
505 ConstantValue value = constant.values[i]; | 504 ConstantValue value = constant.values[i]; |
506 elements.add('(${key.accept(this, _)} . ${value.accept(this, _)})'); | 505 elements.add('(${key.accept(this, _)} . ${value.accept(this, _)})'); |
507 } | 506 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 void setReturnContinuation(Continuation node) { | 561 void setReturnContinuation(Continuation node) { |
563 assert(!_names.containsKey(node) || _names[node] == 'return'); | 562 assert(!_names.containsKey(node) || _names[node] == 'return'); |
564 _names[node] = 'return'; | 563 _names[node] = 'return'; |
565 } | 564 } |
566 | 565 |
567 String getName(Node node) { | 566 String getName(Node node) { |
568 if (!_names.containsKey(node)) return 'MISSING_NAME'; | 567 if (!_names.containsKey(node)) return 'MISSING_NAME'; |
569 return _names[node]; | 568 return _names[node]; |
570 } | 569 } |
571 } | 570 } |
OLD | NEW |