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 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 351 } | 351 } |
| 352 } | 352 } |
| 353 if (member !== null && member.kind == ElementKind.FUNCTION) { | 353 if (member !== null && member.kind == ElementKind.FUNCTION) { |
| 354 return computeType(member); | 354 return computeType(member); |
| 355 } | 355 } |
| 356 reportTypeWarning(node, MessageKind.METHOD_NOT_FOUND, | 356 reportTypeWarning(node, MessageKind.METHOD_NOT_FOUND, |
| 357 [classElement.name, name]); | 357 [classElement.name, name]); |
| 358 return types.dynamicType; | 358 return types.dynamicType; |
| 359 } | 359 } |
| 360 | 360 |
| 361 Link<Type> analyzeArguments(Link<Node> arguments) { | 361 void analyzeArguments(Send send, FunctionType funType) { |
| 362 LinkBuilder<Type> builder = new LinkBuilder<Type>(); | 362 Link<Node> arguments = send.arguments; |
| 363 while(!arguments.isEmpty()) { | 363 if (funType === null) { |
| 364 builder.addLast(analyze(arguments.head)); | 364 while(!arguments.isEmpty()) { |
| 365 arguments = arguments.tail; | 365 analyze(arguments.head); |
| 366 arguments = arguments.tail; | |
| 367 } | |
| 368 } else { | |
| 369 Link<Type> parameterTypes = funType.parameterTypes; | |
| 370 while (!arguments.isEmpty() && !parameterTypes.isEmpty()) { | |
| 371 checkAssignable(arguments.head, parameterTypes.head, | |
| 372 analyze(arguments.head)); | |
| 373 arguments = arguments.tail; | |
| 374 parameterTypes = parameterTypes.tail; | |
| 375 } | |
| 376 if (!arguments.isEmpty()) { | |
| 377 reportTypeWarning(arguments.head, MessageKind.ADDITIONAL_ARGUMENT); | |
| 378 } else if (!parameterTypes.isEmpty()) { | |
| 379 reportTypeWarning(send, MessageKind.MISSING_ARGUMENT, | |
| 380 [parameterTypes.head]); | |
| 381 } | |
| 366 } | 382 } |
| 367 return builder.toLink(); | |
| 368 } | 383 } |
| 369 | 384 |
| 370 Type visitSend(Send node) { | 385 Type visitSend(Send node) { |
| 371 if (Elements.isClosureSend(node, elements)) { | 386 if (Elements.isClosureSend(node, elements)) { |
| 372 // TODO(karlklose): Finish implementation. | 387 // TODO(karlklose): Finish implementation. |
| 373 return types.dynamicType; | 388 return types.dynamicType; |
| 374 } | 389 } |
| 375 | 390 |
| 376 Identifier selector = node.selector.asIdentifier(); | 391 Identifier selector = node.selector.asIdentifier(); |
| 377 String name = selector.source.stringValue; | 392 String name = selector.source.stringValue; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 409 } else if (node.isPropertyAccess) { | 424 } else if (node.isPropertyAccess) { |
| 410 if (node.receiver !== null) fail(node, 'cannot handle fields'); | 425 if (node.receiver !== null) fail(node, 'cannot handle fields'); |
| 411 Element element = elements[node]; | 426 Element element = elements[node]; |
| 412 if (element === null) fail(node.selector, 'unresolved property'); | 427 if (element === null) fail(node.selector, 'unresolved property'); |
| 413 return computeType(element); | 428 return computeType(element); |
| 414 | 429 |
| 415 } else if (node.isFunctionObjectInvocation) { | 430 } else if (node.isFunctionObjectInvocation) { |
| 416 fail(node.receiver, 'function object invocation unimplemented'); | 431 fail(node.receiver, 'function object invocation unimplemented'); |
| 417 | 432 |
| 418 } else { | 433 } else { |
| 419 Link<Type> argumentTypes = analyzeArguments(node.arguments); | |
| 420 FunctionType funType; | 434 FunctionType funType; |
| 421 if (node.receiver !== null) { | 435 if (node.receiver !== null) { |
| 422 Type receiverType = analyze(node.receiver); | 436 Type receiverType = analyze(node.receiver); |
| 423 if (receiverType === types.dynamicType) return types.dynamicType; | 437 if (receiverType === types.dynamicType) return types.dynamicType; |
|
ahe
2012/03/22 15:48:03
Don't return.
polux
2012/03/22 16:25:40
Done.
| |
| 424 if (receiverType === null) { | 438 if (receiverType === null) { |
| 425 fail(node.receiver, 'receivertype is null'); | 439 fail(node.receiver, 'receivertype is null'); |
| 426 } | 440 } |
| 427 if (receiverType.element.kind !== ElementKind.CLASS) { | 441 if (receiverType.element.kind !== ElementKind.CLASS) { |
| 428 fail(node.receiver, 'receivertype is not a class'); | 442 fail(node.receiver, 'receivertype is not a class'); |
| 429 } | 443 } |
| 430 ClassElement classElement = receiverType.element; | 444 ClassElement classElement = receiverType.element; |
| 431 // TODO(karlklose): substitute type arguments. | 445 // TODO(karlklose): substitute type arguments. |
| 432 Type memberType = | 446 Type memberType = |
| 433 lookupMethodType(selector, classElement, selector.source); | 447 lookupMethodType(selector, classElement, selector.source); |
| 434 if (memberType === types.dynamicType) return types.dynamicType; | 448 if (memberType === types.dynamicType) return types.dynamicType; |
|
ahe
2012/03/22 15:48:03
Don't return.
polux
2012/03/22 16:25:40
Done.
| |
| 435 if (memberType is !FunctionType) { | 449 if (memberType is !FunctionType) { |
| 436 fail(node, 'can only handle function types'); | 450 fail(node, 'can only handle function types'); |
| 437 } | 451 } |
| 438 funType = memberType; | 452 funType = memberType; |
| 439 } else { | 453 } else { |
| 440 Element element = elements[node]; | 454 Element element = elements[node]; |
| 441 if (element === null) { | 455 if (element === null) { |
| 442 fail(node, 'unresolved ${node.selector}'); | 456 fail(node, 'unresolved ${node.selector}'); |
| 443 } else if (element.kind === ElementKind.FUNCTION) { | 457 } else if (element.kind === ElementKind.FUNCTION) { |
| 444 funType = computeType(element); | 458 funType = computeType(element); |
| 445 } else if (element.kind === ElementKind.FOREIGN) { | 459 } else if (element.kind === ElementKind.FOREIGN) { |
| 446 return types.dynamicType; | 460 return types.dynamicType; |
| 447 } else { | 461 } else { |
| 448 fail(node, 'unexpected element kind ${element.kind}'); | 462 fail(node, 'unexpected element kind ${element.kind}'); |
| 449 } | 463 } |
| 450 } | 464 } |
| 451 Link<Type> parameterTypes = funType.parameterTypes; | 465 analyzeArguments(node, funType); |
| 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; | 466 return funType.returnType; |
| 467 } | 467 } |
| 468 } | 468 } |
| 469 | 469 |
| 470 visitSendSet(SendSet node) { | 470 visitSendSet(SendSet node) { |
| 471 Identifier selector = node.selector; | 471 Identifier selector = node.selector; |
| 472 final name = node.assignmentOperator.source.stringValue; | 472 final name = node.assignmentOperator.source.stringValue; |
| 473 if (name === '++' || name === '--') { | 473 if (name === '++' || name === '--') { |
| 474 final Element element = elements[node.selector]; | 474 final Element element = elements[node.selector]; |
| 475 final Type receiverType = computeType(element); | 475 final Type receiverType = computeType(element); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 503 analyze(node.first); | 503 analyze(node.first); |
| 504 analyze(node.second); | 504 analyze(node.second); |
| 505 return stringType; | 505 return stringType; |
| 506 } | 506 } |
| 507 | 507 |
| 508 Type visitLiteralNull(LiteralNull node) { | 508 Type visitLiteralNull(LiteralNull node) { |
| 509 return types.dynamicType; | 509 return types.dynamicType; |
| 510 } | 510 } |
| 511 | 511 |
| 512 Type visitNewExpression(NewExpression node) { | 512 Type visitNewExpression(NewExpression node) { |
| 513 Element element = elements[node.send]; | |
| 514 analyzeArguments(node.send, computeType(element)); | |
| 513 return analyze(node.send.selector); | 515 return analyze(node.send.selector); |
| 514 } | 516 } |
| 515 | 517 |
| 516 Type visitLiteralList(LiteralList node) { | 518 Type visitLiteralList(LiteralList node) { |
| 517 return listType; | 519 return listType; |
| 518 } | 520 } |
| 519 | 521 |
| 520 Type visitNodeList(NodeList node) { | 522 Type visitNodeList(NodeList node) { |
| 521 Type type = StatementType.NOT_RETURNING; | 523 Type type = StatementType.NOT_RETURNING; |
| 522 bool reportedDeadCode = false; | 524 bool reportedDeadCode = false; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 707 } | 709 } |
| 708 | 710 |
| 709 visitCatchBlock(CatchBlock node) { | 711 visitCatchBlock(CatchBlock node) { |
| 710 fail(node); | 712 fail(node); |
| 711 } | 713 } |
| 712 | 714 |
| 713 visitTypedef(Typedef node) { | 715 visitTypedef(Typedef node) { |
| 714 fail(node); | 716 fail(node); |
| 715 } | 717 } |
| 716 } | 718 } |
| OLD | NEW |