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 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 .map((p) => '${decorator(p, newValueName(p))}') | 163 .map((p) => '${decorator(p, newValueName(p))}') |
164 .join(' '); | 164 .join(' '); |
165 String handlerBody = | 165 String handlerBody = |
166 indentBlock(() => indentBlock(() => visit(node.handler.body))); | 166 indentBlock(() => indentBlock(() => visit(node.handler.body))); |
167 String body = indentBlock(() => visit(node.body)); | 167 String body = indentBlock(() => visit(node.body)); |
168 return '$indentation(LetHandler (($parameters)\n$handlerBody)\n$body)'; | 168 return '$indentation(LetHandler (($parameters)\n$handlerBody)\n$body)'; |
169 } | 169 } |
170 | 170 |
171 String visitLetMutable(LetMutable node) { | 171 String visitLetMutable(LetMutable node) { |
172 String name = visit(node.variable); | 172 String name = visit(node.variable); |
173 String value = access(node.value); | 173 String value = access(node.valueRef); |
174 String body = indentBlock(() => visit(node.body)); | 174 String body = indentBlock(() => visit(node.body)); |
175 return '$indentation(LetMutable ($name $value)\n$body)'; | 175 return '$indentation(LetMutable ($name $value)\n$body)'; |
176 } | 176 } |
177 | 177 |
178 String formatArguments(CallStructure call, | 178 String formatArguments(CallStructure call, |
179 List<Reference<Primitive>> arguments, | 179 List<Reference<Primitive>> arguments, |
180 [CallingConvention callingConvention = CallingConvention.Normal]) { | 180 [CallingConvention callingConvention = CallingConvention.Normal]) { |
181 int positionalArgumentCount = call.positionalArgumentCount; | 181 int positionalArgumentCount = call.positionalArgumentCount; |
182 if (callingConvention == CallingConvention.Intercepted || | 182 if (callingConvention == CallingConvention.Intercepted || |
183 callingConvention == CallingConvention.DummyIntercepted) { | 183 callingConvention == CallingConvention.DummyIntercepted) { |
184 ++positionalArgumentCount; | 184 ++positionalArgumentCount; |
185 } | 185 } |
186 List<String> args = | 186 List<String> args = |
187 arguments.take(positionalArgumentCount).map(access).toList(); | 187 arguments.take(positionalArgumentCount).map(access).toList(); |
188 List<String> argumentNames = call.getOrderedNamedArguments(); | 188 List<String> argumentNames = call.getOrderedNamedArguments(); |
189 for (int i = 0; i < argumentNames.length; ++i) { | 189 for (int i = 0; i < argumentNames.length; ++i) { |
190 String name = argumentNames[i]; | 190 String name = argumentNames[i]; |
191 String arg = access(arguments[positionalArgumentCount + i]); | 191 String arg = access(arguments[positionalArgumentCount + i]); |
192 args.add("($name: $arg)"); | 192 args.add("($name: $arg)"); |
193 } | 193 } |
194 // Constructors can have type parameter after the named arguments. | 194 // Constructors can have type parameter after the named arguments. |
195 args.addAll( | 195 args.addAll( |
196 arguments.skip(positionalArgumentCount + argumentNames.length) | 196 arguments.skip(positionalArgumentCount + argumentNames.length) |
197 .map(access)); | 197 .map(access)); |
198 return '(${args.join(' ')})'; | 198 return '(${args.join(' ')})'; |
199 } | 199 } |
200 | 200 |
201 String visitInvokeStatic(InvokeStatic node) { | 201 String visitInvokeStatic(InvokeStatic node) { |
202 String name = node.target.name; | 202 String name = node.target.name; |
203 String args = formatArguments(node.selector.callStructure, node.arguments); | 203 String args = formatArguments(node.selector.callStructure, node.argumentRefs
); |
204 return '(InvokeStatic $name $args)'; | 204 return '(InvokeStatic $name $args)'; |
205 } | 205 } |
206 | 206 |
207 String visitInvokeMethod(InvokeMethod node) { | 207 String visitInvokeMethod(InvokeMethod node) { |
208 String name = node.selector.name; | 208 String name = node.selector.name; |
209 String rcv = access(node.receiver); | 209 String rcv = access(node.receiverRef); |
210 String args = formatArguments(node.selector.callStructure, node.arguments, | 210 String args = formatArguments(node.selector.callStructure, node.argumentRefs
, |
211 node.callingConvention); | 211 node.callingConvention); |
212 return '(InvokeMethod $rcv $name $args)'; | 212 return '(InvokeMethod $rcv $name $args)'; |
213 } | 213 } |
214 | 214 |
215 String visitInvokeMethodDirectly(InvokeMethodDirectly node) { | 215 String visitInvokeMethodDirectly(InvokeMethodDirectly node) { |
216 String receiver = access(node.receiver); | 216 String receiver = access(node.receiverRef); |
217 String name = node.selector.name; | 217 String name = node.selector.name; |
218 String args = formatArguments(node.selector.callStructure, node.arguments, | 218 String args = formatArguments(node.selector.callStructure, node.argumentRefs
, |
219 node.callingConvention); | 219 node.callingConvention); |
220 return '(InvokeMethodDirectly $receiver $name $args)'; | 220 return '(InvokeMethodDirectly $receiver $name $args)'; |
221 } | 221 } |
222 | 222 |
223 String visitInvokeConstructor(InvokeConstructor node) { | 223 String visitInvokeConstructor(InvokeConstructor node) { |
224 // TODO(karlklose): for illegal nodes constructed for tests or unresolved | 224 // TODO(karlklose): for illegal nodes constructed for tests or unresolved |
225 // constructor calls in the DartBackend, we get an element with no enclosing | 225 // constructor calls in the DartBackend, we get an element with no enclosing |
226 // class. Clean this up by introducing a name field to the node and | 226 // class. Clean this up by introducing a name field to the node and |
227 // removing [ErroneousElement]s from the IR. | 227 // removing [ErroneousElement]s from the IR. |
228 String name = node.dartType != null | 228 String name = node.dartType != null |
229 ? node.dartType.toString() | 229 ? node.dartType.toString() |
230 : node.target.enclosingClass.name; | 230 : node.target.enclosingClass.name; |
231 if (!node.target.name.isEmpty) { | 231 if (!node.target.name.isEmpty) { |
232 name = '${name}.${node.target.name}'; | 232 name = '${name}.${node.target.name}'; |
233 } | 233 } |
234 String args = formatArguments(node.selector.callStructure, node.arguments); | 234 String args = formatArguments(node.selector.callStructure, node.argumentRefs
); |
235 return '(InvokeConstructor $name $args)'; | 235 return '(InvokeConstructor $name $args)'; |
236 } | 236 } |
237 | 237 |
238 String visitInvokeContinuation(InvokeContinuation node) { | 238 String visitInvokeContinuation(InvokeContinuation node) { |
239 String name = access(node.continuation); | 239 String name = access(node.continuationRef); |
240 if (node.isRecursive) name = 'rec $name'; | 240 if (node.isRecursive) name = 'rec $name'; |
241 String args = node.arguments == null | 241 String args = node.argumentRefs == null |
242 ? '**** NULL ****' | 242 ? '**** NULL ****' |
243 » : node.arguments.map(access).join(' '); | 243 » : node.argumentRefs.map(access).join(' '); |
244 String escaping = node.isEscapingTry ? ' escape' : ''; | 244 String escaping = node.isEscapingTry ? ' escape' : ''; |
245 return '$indentation(InvokeContinuation $name ($args)$escaping)'; | 245 return '$indentation(InvokeContinuation $name ($args)$escaping)'; |
246 } | 246 } |
247 | 247 |
248 String visitThrow(Throw node) { | 248 String visitThrow(Throw node) { |
249 String value = access(node.value); | 249 String value = access(node.valueRef); |
250 return '$indentation(Throw $value)'; | 250 return '$indentation(Throw $value)'; |
251 } | 251 } |
252 | 252 |
253 String visitRethrow(Rethrow node) { | 253 String visitRethrow(Rethrow node) { |
254 return '$indentation(Rethrow)'; | 254 return '$indentation(Rethrow)'; |
255 } | 255 } |
256 | 256 |
257 String visitBranch(Branch node) { | 257 String visitBranch(Branch node) { |
258 String condition = access(node.condition); | 258 String condition = access(node.conditionRef); |
259 assert(isBranchTarget(node.trueContinuation.definition)); | 259 assert(isBranchTarget(node.trueContinuation)); |
260 assert(isBranchTarget(node.falseContinuation.definition)); | 260 assert(isBranchTarget(node.falseContinuation)); |
261 String trueCont = | 261 String trueCont = |
262 indentBlock(() => visit(node.trueContinuation.definition)); | 262 indentBlock(() => visit(node.trueContinuation)); |
263 String falseCont = | 263 String falseCont = |
264 indentBlock(() => visit(node.falseContinuation.definition)); | 264 indentBlock(() => visit(node.falseContinuation)); |
265 String strict = node.isStrictCheck ? 'Strict' : 'NonStrict'; | 265 String strict = node.isStrictCheck ? 'Strict' : 'NonStrict'; |
266 return '$indentation(Branch $strict $condition\n$trueCont\n$falseCont)'; | 266 return '$indentation(Branch $strict $condition\n$trueCont\n$falseCont)'; |
267 } | 267 } |
268 | 268 |
269 String visitUnreachable(Unreachable node) { | 269 String visitUnreachable(Unreachable node) { |
270 return '$indentation(Unreachable)'; | 270 return '$indentation(Unreachable)'; |
271 } | 271 } |
272 | 272 |
273 String visitConstant(Constant node) { | 273 String visitConstant(Constant node) { |
274 String value = node.value.accept(new ConstantStringifier(), null); | 274 String value = node.value.accept(new ConstantStringifier(), null); |
(...skipping 13 matching lines...) Expand all Loading... |
288 // the unstringifier_test produces [LetConts] with dummy arguments on | 288 // the unstringifier_test produces [LetConts] with dummy arguments on |
289 // them. | 289 // them. |
290 String parameters = node.parameters | 290 String parameters = node.parameters |
291 .map((p) => '${decorator(p, newValueName(p))}') | 291 .map((p) => '${decorator(p, newValueName(p))}') |
292 .join(' '); | 292 .join(' '); |
293 String body = indentBlock(() => indentBlock(() => visit(node.body))); | 293 String body = indentBlock(() => indentBlock(() => visit(node.body))); |
294 return '($name ($parameters)\n$body)'; | 294 return '($name ($parameters)\n$body)'; |
295 } | 295 } |
296 | 296 |
297 String visitGetMutable(GetMutable node) { | 297 String visitGetMutable(GetMutable node) { |
298 return '(GetMutable ${access(node.variable)})'; | 298 return '(GetMutable ${access(node.variableRef)})'; |
299 } | 299 } |
300 | 300 |
301 String visitSetMutable(SetMutable node) { | 301 String visitSetMutable(SetMutable node) { |
302 String value = access(node.value); | 302 String value = access(node.valueRef); |
303 return '(SetMutable ${access(node.variable)} $value)'; | 303 return '(SetMutable ${access(node.variableRef)} $value)'; |
304 } | 304 } |
305 | 305 |
306 String visitTypeCast(TypeCast node) { | 306 String visitTypeCast(TypeCast node) { |
307 String value = access(node.value); | 307 String value = access(node.valueRef); |
308 String typeArguments = node.typeArguments.map(access).join(' '); | 308 String typeArguments = node.typeArgumentRefs.map(access).join(' '); |
309 return '(TypeCast $value ${node.dartType} ($typeArguments))'; | 309 return '(TypeCast $value ${node.dartType} ($typeArguments))'; |
310 } | 310 } |
311 | 311 |
312 String visitTypeTest(TypeTest node) { | 312 String visitTypeTest(TypeTest node) { |
313 String value = access(node.value); | 313 String value = access(node.valueRef); |
314 String typeArguments = node.typeArguments.map(access).join(' '); | 314 String typeArguments = node.typeArgumentRefs.map(access).join(' '); |
315 return '(TypeTest $value ${node.dartType} ($typeArguments))'; | 315 return '(TypeTest $value ${node.dartType} ($typeArguments))'; |
316 } | 316 } |
317 | 317 |
318 String visitTypeTestViaFlag(TypeTestViaFlag node) { | 318 String visitTypeTestViaFlag(TypeTestViaFlag node) { |
319 String interceptor = access(node.interceptor); | 319 String interceptor = access(node.interceptorRef); |
320 return '(TypeTestViaFlag $interceptor ${node.dartType})'; | 320 return '(TypeTestViaFlag $interceptor ${node.dartType})'; |
321 } | 321 } |
322 | 322 |
323 String visitLiteralList(LiteralList node) { | 323 String visitLiteralList(LiteralList node) { |
324 String values = node.values.map(access).join(' '); | 324 String values = node.valueRefs.map(access).join(' '); |
325 return '(LiteralList ($values))'; | 325 return '(LiteralList ($values))'; |
326 } | 326 } |
327 | 327 |
328 String visitSetField(SetField node) { | 328 String visitSetField(SetField node) { |
329 String object = access(node.object); | 329 String object = access(node.objectRef); |
330 String field = node.field.name; | 330 String field = node.field.name; |
331 String value = access(node.value); | 331 String value = access(node.valueRef); |
332 return '(SetField $object $field $value)'; | 332 return '(SetField $object $field $value)'; |
333 } | 333 } |
334 | 334 |
335 String visitGetField(GetField node) { | 335 String visitGetField(GetField node) { |
336 String object = access(node.object); | 336 String object = access(node.objectRef); |
337 String field = node.field.name; | 337 String field = node.field.name; |
338 return '(GetField $object $field)'; | 338 return '(GetField $object $field)'; |
339 } | 339 } |
340 | 340 |
341 String visitGetStatic(GetStatic node) { | 341 String visitGetStatic(GetStatic node) { |
342 String element = node.element.name; | 342 String element = node.element.name; |
343 return '(GetStatic $element)'; | 343 return '(GetStatic $element)'; |
344 } | 344 } |
345 | 345 |
346 String visitSetStatic(SetStatic node) { | 346 String visitSetStatic(SetStatic node) { |
347 String element = node.element.name; | 347 String element = node.element.name; |
348 String value = access(node.value); | 348 String value = access(node.valueRef); |
349 return '(SetStatic $element $value)'; | 349 return '(SetStatic $element $value)'; |
350 } | 350 } |
351 | 351 |
352 String visitGetLazyStatic(GetLazyStatic node) { | 352 String visitGetLazyStatic(GetLazyStatic node) { |
353 String element = node.element.name; | 353 String element = node.element.name; |
354 return '(GetLazyStatic $element)'; | 354 return '(GetLazyStatic $element)'; |
355 } | 355 } |
356 | 356 |
357 String visitCreateBox(CreateBox node) { | 357 String visitCreateBox(CreateBox node) { |
358 return '(CreateBox)'; | 358 return '(CreateBox)'; |
359 } | 359 } |
360 | 360 |
361 String visitCreateInstance(CreateInstance node) { | 361 String visitCreateInstance(CreateInstance node) { |
362 String className = node.classElement.name; | 362 String className = node.classElement.name; |
363 String arguments = node.arguments.map(access).join(' '); | 363 String arguments = node.argumentRefs.map(access).join(' '); |
364 String typeInformation = optionalAccess(node.typeInformation); | 364 String typeInformation = optionalAccess(node.typeInformationRef); |
365 return '(CreateInstance $className ($arguments) ($typeInformation))'; | 365 return '(CreateInstance $className ($arguments) ($typeInformation))'; |
366 } | 366 } |
367 | 367 |
368 String visitInterceptor(Interceptor node) { | 368 String visitInterceptor(Interceptor node) { |
369 return '(Interceptor ${access(node.input)})'; | 369 return '(Interceptor ${access(node.inputRef)})'; |
370 } | 370 } |
371 | 371 |
372 String visitReifyRuntimeType(ReifyRuntimeType node) { | 372 String visitReifyRuntimeType(ReifyRuntimeType node) { |
373 return '(ReifyRuntimeType ${access(node.value)})'; | 373 return '(ReifyRuntimeType ${access(node.valueRef)})'; |
374 } | 374 } |
375 | 375 |
376 String visitReadTypeVariable(ReadTypeVariable node) { | 376 String visitReadTypeVariable(ReadTypeVariable node) { |
377 return '(ReadTypeVariable ${access(node.target)}.${node.variable})'; | 377 return '(ReadTypeVariable ${access(node.targetRef)}.${node.variable})'; |
378 } | 378 } |
379 | 379 |
380 String visitTypeExpression(TypeExpression node) { | 380 String visitTypeExpression(TypeExpression node) { |
381 String args = node.arguments.map(access).join(' '); | 381 String args = node.argumentRefs.map(access).join(' '); |
382 return '(TypeExpression ${node.kindAsString} ${node.dartType} ($args))'; | 382 return '(TypeExpression ${node.kindAsString} ${node.dartType} ($args))'; |
383 } | 383 } |
384 | 384 |
385 String visitCreateInvocationMirror(CreateInvocationMirror node) { | 385 String visitCreateInvocationMirror(CreateInvocationMirror node) { |
386 String selector = node.selector.name; | 386 String selector = node.selector.name; |
387 String args = node.arguments.map(access).join(' '); | 387 String args = node.argumentRefs.map(access).join(' '); |
388 return '(CreateInvocationMirror $selector ($args))'; | 388 return '(CreateInvocationMirror $selector ($args))'; |
389 } | 389 } |
390 | 390 |
391 String visitApplyBuiltinOperator(ApplyBuiltinOperator node) { | 391 String visitApplyBuiltinOperator(ApplyBuiltinOperator node) { |
392 String operator = node.operator.toString(); | 392 String operator = node.operator.toString(); |
393 String args = node.arguments.map(access).join(' '); | 393 String args = node.argumentRefs.map(access).join(' '); |
394 return '(ApplyBuiltinOperator $operator ($args))'; | 394 return '(ApplyBuiltinOperator $operator ($args))'; |
395 } | 395 } |
396 | 396 |
397 String visitApplyBuiltinMethod(ApplyBuiltinMethod node) { | 397 String visitApplyBuiltinMethod(ApplyBuiltinMethod node) { |
398 String method = node.method.toString(); | 398 String method = node.method.toString(); |
399 String receiver = access(node.receiver); | 399 String receiver = access(node.receiverRef); |
400 String args = node.arguments.map(access).join(' '); | 400 String args = node.argumentRefs.map(access).join(' '); |
401 return '(ApplyBuiltinMethod $method $receiver ($args))'; | 401 return '(ApplyBuiltinMethod $method $receiver ($args))'; |
402 } | 402 } |
403 | 403 |
404 String visitForeignCode(ForeignCode node) { | 404 String visitForeignCode(ForeignCode node) { |
405 String arguments = node.arguments.map(access).join(' '); | 405 String arguments = node.argumentRefs.map(access).join(' '); |
406 return '(JS "${node.codeTemplate.source}" ($arguments))'; | 406 return '(JS "${node.codeTemplate.source}" ($arguments))'; |
407 } | 407 } |
408 | 408 |
409 String visitGetLength(GetLength node) { | 409 String visitGetLength(GetLength node) { |
410 String object = access(node.object); | 410 String object = access(node.objectRef); |
411 return '(GetLength $object)'; | 411 return '(GetLength $object)'; |
412 } | 412 } |
413 | 413 |
414 String visitGetIndex(GetIndex node) { | 414 String visitGetIndex(GetIndex node) { |
415 String object = access(node.object); | 415 String object = access(node.objectRef); |
416 String index = access(node.index); | 416 String index = access(node.indexRef); |
417 return '(GetIndex $object $index)'; | 417 return '(GetIndex $object $index)'; |
418 } | 418 } |
419 | 419 |
420 String visitSetIndex(SetIndex node) { | 420 String visitSetIndex(SetIndex node) { |
421 String object = access(node.object); | 421 String object = access(node.objectRef); |
422 String index = access(node.index); | 422 String index = access(node.indexRef); |
423 String value = access(node.value); | 423 String value = access(node.valueRef); |
424 return '(SetIndex $object $index $value)'; | 424 return '(SetIndex $object $index $value)'; |
425 } | 425 } |
426 | 426 |
427 @override | 427 @override |
428 String visitAwait(Await node) { | 428 String visitAwait(Await node) { |
429 String value = access(node.input); | 429 String value = access(node.inputRef); |
430 return '(Await $value)'; | 430 return '(Await $value)'; |
431 } | 431 } |
432 | 432 |
433 @override | 433 @override |
434 String visitYield(Yield node) { | 434 String visitYield(Yield node) { |
435 String value = access(node.input); | 435 String value = access(node.inputRef); |
436 return '(Yield $value)'; | 436 return '(Yield $value)'; |
437 } | 437 } |
438 | 438 |
439 String visitRefinement(Refinement node) { | 439 String visitRefinement(Refinement node) { |
440 String value = access(node.value); | 440 String value = access(node.value); |
441 return '(Refinement $value ${node.type})'; | 441 return '(Refinement $value ${node.type})'; |
442 } | 442 } |
443 | 443 |
444 String visitBoundsCheck(BoundsCheck node) { | 444 String visitBoundsCheck(BoundsCheck node) { |
445 String object = access(node.object); | 445 String object = access(node.objectRef); |
446 String index = optionalAccess(node.index); | 446 String index = optionalAccess(node.indexRef); |
447 String length = optionalAccess(node.length); | 447 String length = optionalAccess(node.lengthRef); |
448 return '(BoundsCheck $object $index $length ${node.checkString})'; | 448 return '(BoundsCheck $object $index $length ${node.checkString})'; |
449 } | 449 } |
450 | 450 |
451 String visitReceiverCheck(ReceiverCheck node) { | 451 String visitReceiverCheck(ReceiverCheck node) { |
452 String value = access(node.value); | 452 String value = access(node.valueRef); |
453 String condition = optionalAccess(node.condition); | 453 String condition = optionalAccess(node.conditionRef); |
454 return '(ReceiverCheck $value ${node.selector} $condition ' | 454 return '(ReceiverCheck $value ${node.selector} $condition ' |
455 '${node.flagString}))'; | 455 '${node.flagString}))'; |
456 } | 456 } |
457 } | 457 } |
458 | 458 |
459 class ConstantStringifier extends ConstantValueVisitor<String, Null> { | 459 class ConstantStringifier extends ConstantValueVisitor<String, Null> { |
460 // Some of these methods are unimplemented because we haven't had a need | 460 // Some of these methods are unimplemented because we haven't had a need |
461 // to print such constants. When printing is implemented, the corresponding | 461 // to print such constants. When printing is implemented, the corresponding |
462 // parsing support should be added to SExpressionUnstringifier.parseConstant | 462 // parsing support should be added to SExpressionUnstringifier.parseConstant |
463 // in the dart2js tests (currently in the file | 463 // in the dart2js tests (currently in the file |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 void setReturnContinuation(Continuation node) { | 561 void setReturnContinuation(Continuation node) { |
562 assert(!_names.containsKey(node) || _names[node] == 'return'); | 562 assert(!_names.containsKey(node) || _names[node] == 'return'); |
563 _names[node] = 'return'; | 563 _names[node] = 'return'; |
564 } | 564 } |
565 | 565 |
566 String getName(Node node) { | 566 String getName(Node node) { |
567 if (!_names.containsKey(node)) return 'MISSING_NAME'; | 567 if (!_names.containsKey(node)) return 'MISSING_NAME'; |
568 return _names[node]; | 568 return _names[node]; |
569 } | 569 } |
570 } | 570 } |
OLD | NEW |