Chromium Code Reviews| Index: frog/leg/typechecker.dart |
| diff --git a/frog/leg/typechecker.dart b/frog/leg/typechecker.dart |
| index ef555b2a420e88e1cba9224a75c35fbeffce3301..fa54cdc70f350bc6e3045bc0389b02e515560bdb 100644 |
| --- a/frog/leg/typechecker.dart |
| +++ b/frog/leg/typechecker.dart |
| @@ -358,13 +358,28 @@ class TypeCheckerVisitor implements Visitor<Type> { |
| return types.dynamicType; |
| } |
| - Link<Type> analyzeArguments(Link<Node> arguments) { |
| - LinkBuilder<Type> builder = new LinkBuilder<Type>(); |
| - while(!arguments.isEmpty()) { |
| - builder.addLast(analyze(arguments.head)); |
| - arguments = arguments.tail; |
| + void analyzeArguments(Send send, FunctionType funType) { |
| + Link<Node> arguments = send.arguments; |
| + if (funType === null) { |
| + while(!arguments.isEmpty()) { |
| + analyze(arguments.head); |
| + arguments = arguments.tail; |
| + } |
| + } else { |
| + Link<Type> parameterTypes = funType.parameterTypes; |
| + while (!arguments.isEmpty() && !parameterTypes.isEmpty()) { |
| + checkAssignable(arguments.head, parameterTypes.head, |
| + analyze(arguments.head)); |
| + arguments = arguments.tail; |
| + parameterTypes = parameterTypes.tail; |
| + } |
| + if (!arguments.isEmpty()) { |
| + reportTypeWarning(arguments.head, MessageKind.ADDITIONAL_ARGUMENT); |
| + } else if (!parameterTypes.isEmpty()) { |
| + reportTypeWarning(send, MessageKind.MISSING_ARGUMENT, |
| + [parameterTypes.head]); |
| + } |
| } |
| - return builder.toLink(); |
| } |
| Type visitSend(Send node) { |
| @@ -416,54 +431,41 @@ class TypeCheckerVisitor implements Visitor<Type> { |
| fail(node.receiver, 'function object invocation unimplemented'); |
| } else { |
| - Link<Type> argumentTypes = analyzeArguments(node.arguments); |
| - FunctionType funType; |
| - if (node.receiver !== null) { |
| - Type receiverType = analyze(node.receiver); |
| - if (receiverType === types.dynamicType) return types.dynamicType; |
| - if (receiverType === null) { |
| - fail(node.receiver, 'receivertype is null'); |
| - } |
| - if (receiverType.element.kind !== ElementKind.CLASS) { |
| - fail(node.receiver, 'receivertype is not a class'); |
| - } |
| - ClassElement classElement = receiverType.element; |
| - // TODO(karlklose): substitute type arguments. |
| - Type memberType = |
| - lookupMethodType(selector, classElement, selector.source); |
| - if (memberType === types.dynamicType) return types.dynamicType; |
| - if (memberType is !FunctionType) { |
| - fail(node, 'can only handle function types'); |
| - } |
| - funType = memberType; |
| - } else { |
| - Element element = elements[node]; |
| - if (element === null) { |
| - fail(node, 'unresolved ${node.selector}'); |
| - } else if (element.kind === ElementKind.FUNCTION) { |
| - funType = computeType(element); |
| - } else if (element.kind === ElementKind.FOREIGN) { |
| - return types.dynamicType; |
| + FunctionType computeFunType() { |
| + if (node.receiver !== null) { |
| + Type receiverType = analyze(node.receiver); |
| + if (receiverType === types.dynamicType) return null; |
| + if (receiverType === null) { |
| + fail(node.receiver, 'receivertype is null'); |
| + } |
| + if (receiverType.element.kind !== ElementKind.CLASS) { |
| + fail(node.receiver, 'receivertype is not a class'); |
| + } |
| + ClassElement classElement = receiverType.element; |
| + // TODO(karlklose): substitute type arguments. |
| + Type memberType = |
| + lookupMethodType(selector, classElement, selector.source); |
| + if (memberType === types.dynamicType) return null; |
| + if (memberType is !FunctionType) { |
|
ahe
2012/03/22 17:52:16
Then you can remove this check.
|
| + fail(node, 'can only handle function types'); |
|
ahe
2012/03/22 16:31:01
return null;
polux
2012/03/22 18:44:16
Done. Also fixed lookupMethodType as discussed.
O
|
| + } |
| + return memberType; |
| } else { |
| - fail(node, 'unexpected element kind ${element.kind}'); |
| + Element element = elements[node]; |
| + if (element === null) { |
| + fail(node, 'unresolved ${node.selector}'); |
| + } else if (element.kind === ElementKind.FUNCTION) { |
| + return computeType(element); |
| + } else if (element.kind === ElementKind.FOREIGN) { |
| + return null; |
| + } else { |
| + fail(node, 'unexpected element kind ${element.kind}'); |
| + } |
| } |
| } |
| - Link<Type> parameterTypes = funType.parameterTypes; |
| - Link<Node> argumentNodes = node.arguments; |
| - while (!argumentTypes.isEmpty() && !parameterTypes.isEmpty()) { |
| - checkAssignable(argumentNodes.head, parameterTypes.head, |
| - argumentTypes.head); |
| - argumentTypes = argumentTypes.tail; |
| - parameterTypes = parameterTypes.tail; |
| - argumentNodes = argumentNodes.tail; |
| - } |
| - if (!argumentTypes.isEmpty()) { |
| - reportTypeWarning(argumentNodes.head, MessageKind.ADDITIONAL_ARGUMENT); |
| - } else if (!parameterTypes.isEmpty()) { |
| - reportTypeWarning(node, MessageKind.MISSING_ARGUMENT, |
| - [parameterTypes.head]); |
| - } |
| - return funType.returnType; |
| + FunctionType funType = computeFunType(); |
| + analyzeArguments(node, funType); |
| + return (funType !== null) ? funType.returnType : types.dynamicType; |
| } |
| } |
| @@ -510,6 +512,8 @@ class TypeCheckerVisitor implements Visitor<Type> { |
| } |
| Type visitNewExpression(NewExpression node) { |
| + Element element = elements[node.send]; |
| + analyzeArguments(node.send, computeType(element)); |
| return analyze(node.send.selector); |
| } |