| 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 |