Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 class TypeCheckerTask extends CompilerTask { | 5 class TypeCheckerTask extends CompilerTask { |
| 6 TypeCheckerTask(Compiler compiler) : super(compiler); | 6 TypeCheckerTask(Compiler compiler) : super(compiler); |
| 7 String get name() => "Type checker"; | 7 String get name() => "Type checker"; |
| 8 | 8 |
| 9 static final bool LOG_FAILURES = false; | 9 static final bool LOG_FAILURES = false; |
| 10 | 10 |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 | 360 |
| 361 Link<Type> analyzeArguments(Link<Node> arguments) { | 361 Link<Type> analyzeArguments(Link<Node> arguments) { |
| 362 LinkBuilder<Type> builder = new LinkBuilder<Type>(); | 362 LinkBuilder<Type> builder = new LinkBuilder<Type>(); |
| 363 while(!arguments.isEmpty()) { | 363 while(!arguments.isEmpty()) { |
| 364 builder.addLast(analyze(arguments.head)); | 364 builder.addLast(analyze(arguments.head)); |
| 365 arguments = arguments.tail; | 365 arguments = arguments.tail; |
| 366 } | 366 } |
| 367 return builder.toLink(); | 367 return builder.toLink(); |
| 368 } | 368 } |
| 369 | 369 |
| 370 /** | |
| 371 * Checks that [parameterTypes] matches [argumentTypes], reports type | |
| 372 * warnings otherwise. Preconditions: | |
| 373 * [: argumentNodes == sendOrNew.arguments :] | |
| 374 * [: argumentTypes == analyzeArguments(argumentNodes) :] | |
| 375 */ | |
| 376 void checkArgumentTypes(Node sendOrNew, Link<Node> argumentNodes, | |
|
ahe
2012/03/22 14:46:23
Change this to:
checkArgumentTypes(Send send, Fun
polux
2012/03/22 15:08:26
I could as well merge the loops of checkArgumentTy
polux
2012/03/22 15:36:47
Done.
| |
| 377 Link<Type> parameterTypes, Link<Type> argumentTypes) { | |
| 378 while (!argumentTypes.isEmpty() && !parameterTypes.isEmpty()) { | |
| 379 checkAssignable(argumentNodes.head, parameterTypes.head, | |
| 380 argumentTypes.head); | |
| 381 argumentTypes = argumentTypes.tail; | |
| 382 parameterTypes = parameterTypes.tail; | |
| 383 argumentNodes = argumentNodes.tail; | |
| 384 } | |
| 385 if (!argumentTypes.isEmpty()) { | |
| 386 reportTypeWarning(argumentNodes.head, MessageKind.ADDITIONAL_ARGUMENT); | |
| 387 } else if (!parameterTypes.isEmpty()) { | |
| 388 reportTypeWarning(sendOrNew, MessageKind.MISSING_ARGUMENT, | |
| 389 [parameterTypes.head]); | |
| 390 } | |
| 391 } | |
| 392 | |
| 370 Type visitSend(Send node) { | 393 Type visitSend(Send node) { |
| 371 if (Elements.isClosureSend(node, elements)) { | 394 if (Elements.isClosureSend(node, elements)) { |
| 372 // TODO(karlklose): Finish implementation. | 395 // TODO(karlklose): Finish implementation. |
| 373 return types.dynamicType; | 396 return types.dynamicType; |
| 374 } | 397 } |
| 375 | 398 |
| 376 Identifier selector = node.selector.asIdentifier(); | 399 Identifier selector = node.selector.asIdentifier(); |
| 377 String name = selector.source.stringValue; | 400 String name = selector.source.stringValue; |
| 378 | 401 |
| 379 if (node.isOperator && name === 'is') { | 402 if (node.isOperator && name === 'is') { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 409 } else if (node.isPropertyAccess) { | 432 } else if (node.isPropertyAccess) { |
| 410 if (node.receiver !== null) fail(node, 'cannot handle fields'); | 433 if (node.receiver !== null) fail(node, 'cannot handle fields'); |
| 411 Element element = elements[node]; | 434 Element element = elements[node]; |
| 412 if (element === null) fail(node.selector, 'unresolved property'); | 435 if (element === null) fail(node.selector, 'unresolved property'); |
| 413 return computeType(element); | 436 return computeType(element); |
| 414 | 437 |
| 415 } else if (node.isFunctionObjectInvocation) { | 438 } else if (node.isFunctionObjectInvocation) { |
| 416 fail(node.receiver, 'function object invocation unimplemented'); | 439 fail(node.receiver, 'function object invocation unimplemented'); |
| 417 | 440 |
| 418 } else { | 441 } else { |
| 419 Link<Type> argumentTypes = analyzeArguments(node.arguments); | 442 Link<Type> argumentTypes = analyzeArguments(node.arguments); |
|
ahe
2012/03/22 14:46:23
Move this check to line 473.
| |
| 420 FunctionType funType; | 443 FunctionType funType; |
| 421 if (node.receiver !== null) { | 444 if (node.receiver !== null) { |
| 422 Type receiverType = analyze(node.receiver); | 445 Type receiverType = analyze(node.receiver); |
| 423 if (receiverType === types.dynamicType) return types.dynamicType; | 446 if (receiverType === types.dynamicType) return types.dynamicType; |
|
ahe
2012/03/22 14:46:23
Don't return here, but skip the rest.
| |
| 424 if (receiverType === null) { | 447 if (receiverType === null) { |
| 425 fail(node.receiver, 'receivertype is null'); | 448 fail(node.receiver, 'receivertype is null'); |
| 426 } | 449 } |
| 427 if (receiverType.element.kind !== ElementKind.CLASS) { | 450 if (receiverType.element.kind !== ElementKind.CLASS) { |
| 428 fail(node.receiver, 'receivertype is not a class'); | 451 fail(node.receiver, 'receivertype is not a class'); |
| 429 } | 452 } |
| 430 ClassElement classElement = receiverType.element; | 453 ClassElement classElement = receiverType.element; |
| 431 // TODO(karlklose): substitute type arguments. | 454 // TODO(karlklose): substitute type arguments. |
| 432 Type memberType = | 455 Type memberType = |
| 433 lookupMethodType(selector, classElement, selector.source); | 456 lookupMethodType(selector, classElement, selector.source); |
| 434 if (memberType === types.dynamicType) return types.dynamicType; | 457 if (memberType === types.dynamicType) return types.dynamicType; |
|
ahe
2012/03/22 14:46:23
Don't return here.
| |
| 435 if (memberType is !FunctionType) { | 458 if (memberType is !FunctionType) { |
| 436 fail(node, 'can only handle function types'); | 459 fail(node, 'can only handle function types'); |
| 437 } | 460 } |
| 438 funType = memberType; | 461 funType = memberType; |
| 439 } else { | 462 } else { |
| 440 Element element = elements[node]; | 463 Element element = elements[node]; |
| 441 if (element === null) { | 464 if (element === null) { |
| 442 fail(node, 'unresolved ${node.selector}'); | 465 fail(node, 'unresolved ${node.selector}'); |
| 443 } else if (element.kind === ElementKind.FUNCTION) { | 466 } else if (element.kind === ElementKind.FUNCTION) { |
| 444 funType = computeType(element); | 467 funType = computeType(element); |
| 445 } else if (element.kind === ElementKind.FOREIGN) { | 468 } else if (element.kind === ElementKind.FOREIGN) { |
| 446 return types.dynamicType; | 469 return types.dynamicType; |
| 447 } else { | 470 } else { |
| 448 fail(node, 'unexpected element kind ${element.kind}'); | 471 fail(node, 'unexpected element kind ${element.kind}'); |
| 449 } | 472 } |
| 450 } | 473 } |
| 451 Link<Type> parameterTypes = funType.parameterTypes; | 474 checkArgumentTypes(node, node.arguments, funType.parameterTypes, argumentT ypes); |
|
ahe
2012/03/22 14:46:23
Change this to:
checkArgumentTypes(node, funType)
polux
2012/03/22 15:36:47
Done.
| |
| 452 Link<Node> argumentNodes = node.arguments; | |
| 453 while (!argumentTypes.isEmpty() && !parameterTypes.isEmpty()) { | |
| 454 checkAssignable(argumentNodes.head, parameterTypes.head, | |
| 455 argumentTypes.head); | |
| 456 argumentTypes = argumentTypes.tail; | |
| 457 parameterTypes = parameterTypes.tail; | |
| 458 argumentNodes = argumentNodes.tail; | |
| 459 } | |
| 460 if (!argumentTypes.isEmpty()) { | |
| 461 reportTypeWarning(argumentNodes.head, MessageKind.ADDITIONAL_ARGUMENT); | |
| 462 } else if (!parameterTypes.isEmpty()) { | |
| 463 reportTypeWarning(node, MessageKind.MISSING_ARGUMENT, | |
| 464 [parameterTypes.head]); | |
| 465 } | |
| 466 return funType.returnType; | 475 return funType.returnType; |
| 467 } | 476 } |
| 468 } | 477 } |
| 469 | 478 |
| 470 visitSendSet(SendSet node) { | 479 visitSendSet(SendSet node) { |
| 471 Identifier selector = node.selector; | 480 Identifier selector = node.selector; |
| 472 final name = node.assignmentOperator.source.stringValue; | 481 final name = node.assignmentOperator.source.stringValue; |
| 473 if (name === '++' || name === '--') { | 482 if (name === '++' || name === '--') { |
| 474 final Element element = elements[node.selector]; | 483 final Element element = elements[node.selector]; |
| 475 final Type receiverType = computeType(element); | 484 final Type receiverType = computeType(element); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 503 analyze(node.first); | 512 analyze(node.first); |
| 504 analyze(node.second); | 513 analyze(node.second); |
| 505 return stringType; | 514 return stringType; |
| 506 } | 515 } |
| 507 | 516 |
| 508 Type visitLiteralNull(LiteralNull node) { | 517 Type visitLiteralNull(LiteralNull node) { |
| 509 return types.dynamicType; | 518 return types.dynamicType; |
| 510 } | 519 } |
| 511 | 520 |
| 512 Type visitNewExpression(NewExpression node) { | 521 Type visitNewExpression(NewExpression node) { |
| 522 Link<Type> argumentTypes = analyzeArguments(node.send.arguments); | |
| 523 Link<Type> parameterTypes = new EmptyLink(); | |
| 524 Element element = elements[node.send]; | |
| 525 FunctionType funtype = computeType(element); | |
|
ahe
2012/03/22 14:46:23
Calling computeType resolves the element on-demand
polux
2012/03/22 15:36:47
Done.
| |
| 526 checkArgumentTypes(node, node.send.arguments, funtype.parameterTypes, argume ntTypes); | |
|
ahe
2012/03/22 14:46:23
Change this to:
checkArgumentTypes(node.send, fun
polux
2012/03/22 15:36:47
Done.
| |
| 513 return analyze(node.send.selector); | 527 return analyze(node.send.selector); |
| 514 } | 528 } |
| 515 | 529 |
| 516 Type visitLiteralList(LiteralList node) { | 530 Type visitLiteralList(LiteralList node) { |
| 517 return listType; | 531 return listType; |
| 518 } | 532 } |
| 519 | 533 |
| 520 Type visitNodeList(NodeList node) { | 534 Type visitNodeList(NodeList node) { |
| 521 Type type = StatementType.NOT_RETURNING; | 535 Type type = StatementType.NOT_RETURNING; |
| 522 bool reportedDeadCode = false; | 536 bool reportedDeadCode = false; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 707 } | 721 } |
| 708 | 722 |
| 709 visitCatchBlock(CatchBlock node) { | 723 visitCatchBlock(CatchBlock node) { |
| 710 fail(node); | 724 fail(node); |
| 711 } | 725 } |
| 712 | 726 |
| 713 visitTypedef(Typedef node) { | 727 visitTypedef(Typedef node) { |
| 714 fail(node); | 728 fail(node); |
| 715 } | 729 } |
| 716 } | 730 } |
| OLD | NEW |