Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: runtime/vm/parser.cc

Issue 10979053: Change many instance creation errors from compile-time errors to dynamic errors (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/class_finalizer.cc ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/compiler_stats.h" 10 #include "vm/compiler_stats.h"
(...skipping 2435 matching lines...) Expand 10 before | Expand all | Expand 10 after
2446 } 2446 }
2447 2447
2448 // Parse redirecting factory constructor. 2448 // Parse redirecting factory constructor.
2449 Type& redirection_type = Type::Handle(); 2449 Type& redirection_type = Type::Handle();
2450 String& redirection_identifier = String::Handle(); 2450 String& redirection_identifier = String::Handle();
2451 if (method->IsFactory() && (CurrentToken() == Token::kASSIGN)) { 2451 if (method->IsFactory() && (CurrentToken() == Token::kASSIGN)) {
2452 ConsumeToken(); 2452 ConsumeToken();
2453 const intptr_t type_pos = TokenPos(); 2453 const intptr_t type_pos = TokenPos();
2454 const AbstractType& type = AbstractType::Handle( 2454 const AbstractType& type = AbstractType::Handle(
2455 ParseType(ClassFinalizer::kTryResolve)); 2455 ParseType(ClassFinalizer::kTryResolve));
2456 if (type.IsTypeParameter()) { 2456 if (type.IsTypeParameter() || type.IsDynamicType()) {
2457 // TODO(regis): Spec is not clear. Throw dynamic error or report 2457 // Replace the type with a malformed type and compile a throw when called.
2458 // compile-time error? Same question for new and const operators. 2458 redirection_type = ClassFinalizer::NewFinalizedMalformedType(
2459 ErrorMsg(type_pos, "factory may not redirect via a type parameter"); 2459 current_class(),
2460 type_pos,
2461 "factory '%s' may not redirect to %s'%s'",
2462 method->name->ToCString(),
2463 type.IsTypeParameter() ? "type parameter " : "",
2464 type.IsTypeParameter() ?
2465 String::Handle(type.UserVisibleName()).ToCString() : "dynamic");
2466 } else {
2467 redirection_type ^= type.raw();
2460 } 2468 }
2461 redirection_type ^= type.raw();
2462 if (CurrentToken() == Token::kPERIOD) { 2469 if (CurrentToken() == Token::kPERIOD) {
2463 // Named constructor or factory. 2470 // Named constructor or factory.
2464 ConsumeToken(); 2471 ConsumeToken();
2465 redirection_identifier = ExpectIdentifier("identifier expected")->raw(); 2472 redirection_identifier = ExpectIdentifier("identifier expected")->raw();
2466 } 2473 }
2467 } else if (CurrentToken() == Token::kCOLON) { 2474 } else if (CurrentToken() == Token::kCOLON) {
2468 // Parse initializers. 2475 // Parse initializers.
2469 if (!method->IsConstructor()) { 2476 if (!method->IsConstructor()) {
2470 ErrorMsg("initializers only allowed on constructors"); 2477 ErrorMsg("initializers only allowed on constructors");
2471 } 2478 }
(...skipping 6379 matching lines...) Expand 10 before | Expand all | Expand 10 after
8851 const intptr_t new_pos = TokenPos(); 8858 const intptr_t new_pos = TokenPos();
8852 ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST)); 8859 ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST));
8853 bool is_const = (CurrentToken() == Token::kCONST); 8860 bool is_const = (CurrentToken() == Token::kCONST);
8854 ConsumeToken(); 8861 ConsumeToken();
8855 if (!IsIdentifier()) { 8862 if (!IsIdentifier()) {
8856 ErrorMsg("type name expected"); 8863 ErrorMsg("type name expected");
8857 } 8864 }
8858 intptr_t type_pos = TokenPos(); 8865 intptr_t type_pos = TokenPos();
8859 AbstractType& type = AbstractType::Handle( 8866 AbstractType& type = AbstractType::Handle(
8860 ParseType(ClassFinalizer::kCanonicalizeWellFormed)); 8867 ParseType(ClassFinalizer::kCanonicalizeWellFormed));
8861 // Malformed bounds never result in a compile time error, therefore, the 8868 // In case the type is malformed, throw a dynamic type error after finishing
8862 // parsed type may be malformed although we requested kCanonicalizeWellFormed. 8869 // parsing the instance creation expression.
8863 // In that case, we throw a dynamic type error instead of calling the 8870 if (type.IsTypeParameter() || type.IsDynamicType()) {
8864 // constructor. 8871 // Replace the type with a malformed type.
8865 if (type.IsTypeParameter()) { 8872 type = ClassFinalizer::NewFinalizedMalformedType(
8866 ErrorMsg(type_pos, 8873 current_class(),
8867 "type parameter '%s' cannot be instantiated", 8874 type_pos,
8868 String::Handle(type.UserVisibleName()).ToCString()); 8875 "%s'%s' cannot be instantiated",
8876 type.IsTypeParameter() ? "type parameter " : "",
8877 type.IsTypeParameter() ?
8878 String::Handle(type.UserVisibleName()).ToCString() : "dynamic");
8869 } 8879 }
8870 if (type.IsDynamicType()) {
8871 ErrorMsg(type_pos, "Dynamic cannot be instantiated");
8872 }
8873 Class& type_class = Class::Handle(type.type_class());
8874 const String& type_class_name = String::Handle(type_class.Name());
8875 AbstractTypeArguments& type_arguments =
8876 AbstractTypeArguments::ZoneHandle(type.arguments());
8877
8878 // The constructor class and its name are those of the parsed type, unless the
8879 // parsed type is an interface and a default factory class is specified, in
8880 // which case constructor_class and constructor_class_name are modified below.
8881 Class& constructor_class = Class::ZoneHandle(type_class.raw());
8882 String& constructor_class_name = String::Handle(type_class_name.raw());
8883 8880
8884 // The grammar allows for an optional ('.' identifier)? after the type, which 8881 // The grammar allows for an optional ('.' identifier)? after the type, which
8885 // is a named constructor. Note that ParseType(kMustResolve) above will not 8882 // is a named constructor. Note that ParseType(kMustResolve) above will not
8886 // consume it as part of a misinterpreted qualified identifier, because only a 8883 // consume it as part of a misinterpreted qualified identifier, because only a
8887 // valid library prefix is accepted as qualifier. 8884 // valid library prefix is accepted as qualifier.
8888 String* named_constructor = NULL; 8885 String* named_constructor = NULL;
8889 if (CurrentToken() == Token::kPERIOD) { 8886 if (CurrentToken() == Token::kPERIOD) {
8890 ConsumeToken(); 8887 ConsumeToken();
8891 named_constructor = ExpectIdentifier("name of constructor expected"); 8888 named_constructor = ExpectIdentifier("name of constructor expected");
8892 } 8889 }
8893 8890
8894 // Parse constructor parameters. 8891 // Parse constructor parameters.
8895 if (CurrentToken() != Token::kLPAREN) { 8892 if (CurrentToken() != Token::kLPAREN) {
8896 ErrorMsg("'(' expected"); 8893 ErrorMsg("'(' expected");
8897 } 8894 }
8898 intptr_t call_pos = TokenPos(); 8895 intptr_t call_pos = TokenPos();
8899 ArgumentListNode* arguments = ParseActualParameters(NULL, is_const); 8896 ArgumentListNode* arguments = ParseActualParameters(NULL, is_const);
8900 8897
8898 // Parsing is complete, so we can return a throw in case of a malformed type.
8899 if (type.IsMalformed()) {
8900 return ThrowTypeError(type_pos, type);
8901 }
8902
8903 // Resolve the type and optional identifier to a constructor or factory.
8904 Class& type_class = Class::Handle(type.type_class());
8905 const String& type_class_name = String::Handle(type_class.Name());
8906 AbstractTypeArguments& type_arguments =
8907 AbstractTypeArguments::ZoneHandle(type.arguments());
8908
8909 // The constructor class and its name are those of the parsed type, unless the
8910 // parsed type is an interface and a default factory class is specified, in
8911 // which case constructor_class and constructor_class_name are modified below.
8912 Class& constructor_class = Class::ZoneHandle(type_class.raw());
8913 String& constructor_class_name = String::Handle(type_class_name.raw());
8914
8901 // A constructor has an implicit 'this' parameter (instance to construct) 8915 // A constructor has an implicit 'this' parameter (instance to construct)
8902 // and a factory has an implicit 'this' parameter (type_arguments). 8916 // and a factory has an implicit 'this' parameter (type_arguments).
8903 // A constructor has a second implicit 'phase' parameter. 8917 // A constructor has a second implicit 'phase' parameter.
8904 intptr_t arguments_length = arguments->length() + 2; 8918 intptr_t arguments_length = arguments->length() + 2;
8905 8919
8906 if (type_class.is_interface()) { 8920 if (type_class.is_interface()) {
8907 // We need to make sure that an appropriate constructor is 8921 // We need to make sure that an appropriate constructor is
8908 // declared in the interface. 8922 // declared in the interface.
8909 const String& constructor_name = 8923 const String& constructor_name =
8910 BuildConstructorName(type_class_name, named_constructor); 8924 BuildConstructorName(type_class_name, named_constructor);
8911 const String& external_constructor_name = 8925 const String& external_constructor_name =
8912 (named_constructor ? constructor_name : type_class_name); 8926 (named_constructor ? constructor_name : type_class_name);
8913 Function& constructor = Function::ZoneHandle( 8927 Function& constructor = Function::ZoneHandle(
8914 type_class.LookupConstructor(constructor_name)); 8928 type_class.LookupConstructor(constructor_name));
8915 if (constructor.IsNull()) { 8929 if (constructor.IsNull()) {
8916 ErrorMsg(type_pos, 8930 // Replace the type with a malformed type and compile a throw.
8917 "interface '%s' has no constructor named '%s'", 8931 type = ClassFinalizer::NewFinalizedMalformedType(
8918 type_class_name.ToCString(), 8932 current_class(),
8919 external_constructor_name.ToCString()); 8933 type_pos,
8934 "interface '%s' has no constructor named '%s'",
8935 type_class_name.ToCString(),
8936 external_constructor_name.ToCString());
8937 return ThrowTypeError(type_pos, type);
8920 } 8938 }
8939 // TODO(regis): Throw a NoSuchMethodError instead of a TypeError.
8921 String& error_message = String::Handle(); 8940 String& error_message = String::Handle();
8922 if (!constructor.AreValidArguments(arguments_length, 8941 if (!constructor.AreValidArguments(arguments_length,
8923 arguments->names(), 8942 arguments->names(),
8924 &error_message)) { 8943 &error_message)) {
8925 ErrorMsg(call_pos, 8944 // Replace the type with a malformed type and compile a throw.
8926 "invalid arguments passed to constructor '%s' " 8945 type = ClassFinalizer::NewFinalizedMalformedType(
8927 "for interface '%s': %s", 8946 current_class(),
8928 external_constructor_name.ToCString(), 8947 call_pos,
8929 type_class_name.ToCString(), 8948 "invalid arguments passed to constructor '%s' "
8930 error_message.ToCString()); 8949 "for interface '%s': %s",
8950 external_constructor_name.ToCString(),
8951 type_class_name.ToCString(),
8952 error_message.ToCString());
8953 return ThrowTypeError(call_pos, type);
8931 } 8954 }
8955 // TODO(regis): Remove support for obsolete default factory classes.
8932 if (!type_class.HasFactoryClass()) { 8956 if (!type_class.HasFactoryClass()) {
8933 ErrorMsg(type_pos, 8957 ErrorMsg(type_pos,
8934 "cannot allocate interface '%s' without factory class", 8958 "cannot allocate interface '%s' without factory class",
8935 type_class_name.ToCString()); 8959 type_class_name.ToCString());
8936 } 8960 }
8937 if (!type_class.HasResolvedFactoryClass()) { 8961 if (!type_class.HasResolvedFactoryClass()) {
8938 // This error can occur only with bootstrap classes. 8962 // This error can occur only with bootstrap classes.
8939 const UnresolvedClass& unresolved = 8963 const UnresolvedClass& unresolved =
8940 UnresolvedClass::Handle(type_class.UnresolvedFactoryClass()); 8964 UnresolvedClass::Handle(type_class.UnresolvedFactoryClass());
8941 const String& missing_class_name = String::Handle(unresolved.ident()); 8965 const String& missing_class_name = String::Handle(unresolved.ident());
(...skipping 19 matching lines...) Expand all
8961 // Make sure that an appropriate constructor exists. 8985 // Make sure that an appropriate constructor exists.
8962 const String& constructor_name = 8986 const String& constructor_name =
8963 BuildConstructorName(constructor_class_name, named_constructor); 8987 BuildConstructorName(constructor_class_name, named_constructor);
8964 Function& constructor = Function::ZoneHandle( 8988 Function& constructor = Function::ZoneHandle(
8965 constructor_class.LookupConstructor(constructor_name)); 8989 constructor_class.LookupConstructor(constructor_name));
8966 if (constructor.IsNull()) { 8990 if (constructor.IsNull()) {
8967 constructor = constructor_class.LookupFactory(constructor_name); 8991 constructor = constructor_class.LookupFactory(constructor_name);
8968 if (constructor.IsNull()) { 8992 if (constructor.IsNull()) {
8969 const String& external_constructor_name = 8993 const String& external_constructor_name =
8970 (named_constructor ? constructor_name : constructor_class_name); 8994 (named_constructor ? constructor_name : constructor_class_name);
8971 ErrorMsg(type_pos, 8995 // Replace the type with a malformed type and compile a throw.
8972 "class '%s' has no constructor or factory named '%s'", 8996 type = ClassFinalizer::NewFinalizedMalformedType(
8973 String::Handle(constructor_class.Name()).ToCString(), 8997 current_class(),
8974 external_constructor_name.ToCString()); 8998 type_pos,
8999 "class '%s' has no constructor or factory named '%s'",
9000 String::Handle(constructor_class.Name()).ToCString(),
9001 external_constructor_name.ToCString());
9002 return ThrowTypeError(type_pos, type);
8975 } else if (constructor.IsRedirectingFactory()) { 9003 } else if (constructor.IsRedirectingFactory()) {
8976 type = constructor.RedirectionType(); 9004 type = constructor.RedirectionType();
9005 if (type.IsMalformed()) {
9006 return ThrowTypeError(type.token_pos(), type);
9007 }
8977 constructor = constructor.RedirectionTarget(); 9008 constructor = constructor.RedirectionTarget();
8978 if (constructor.IsNull()) { 9009 ASSERT(!constructor.IsNull());
8979 // TODO(regis): We normally report a compile-time error if the 9010 type_class = type.type_class();
8980 // constructor is not found. See above. However, we should throw a 9011 type_arguments = type.arguments();
8981 // dynamic error instead. We do it here. This is the first step. 9012 constructor_class = constructor.Owner();
8982 ASSERT(type.IsMalformed()); 9013 ASSERT(type_class.raw() == constructor_class.raw());
8983 } else {
8984 type_class = type.type_class();
8985 type_arguments = type.arguments();
8986 constructor_class = constructor.Owner();
8987 ASSERT(type_class.raw() == constructor_class.raw());
8988 }
8989 } 9014 }
8990 if (!constructor.IsNull() && constructor.IsFactory()) { 9015 if (constructor.IsFactory()) {
8991 // A factory does not have the implicit 'phase' parameter. 9016 // A factory does not have the implicit 'phase' parameter.
8992 arguments_length -= 1; 9017 arguments_length -= 1;
8993 } 9018 }
8994 } 9019 }
8995 9020
8996 // It is ok to call a factory method of an abstract class, but it is 9021 // It is ok to call a factory method of an abstract class, but it is
8997 // a dynamic error to instantiate an abstract class. 9022 // a dynamic error to instantiate an abstract class.
8998 if (!constructor.IsNull() && 9023 ASSERT(!constructor.IsNull());
8999 constructor_class.is_abstract() && 9024 if (constructor_class.is_abstract() &&
9000 !constructor.IsFactory()) { 9025 !constructor.IsFactory()) {
9001 ArgumentListNode* arguments = new ArgumentListNode(type_pos); 9026 ArgumentListNode* arguments = new ArgumentListNode(type_pos);
9002 arguments->Add(new LiteralNode( 9027 arguments->Add(new LiteralNode(
9003 TokenPos(), Integer::ZoneHandle(Integer::New(type_pos)))); 9028 TokenPos(), Integer::ZoneHandle(Integer::New(type_pos))));
9004 arguments->Add(new LiteralNode( 9029 arguments->Add(new LiteralNode(
9005 TokenPos(), String::ZoneHandle(constructor_class_name.raw()))); 9030 TokenPos(), String::ZoneHandle(constructor_class_name.raw())));
9006 const String& cls_name = 9031 const String& cls_name =
9007 String::Handle(Symbols::AbstractClassInstantiationError()); 9032 String::Handle(Symbols::AbstractClassInstantiationError());
9008 const String& func_name = String::Handle(Symbols::ThrowNew()); 9033 const String& func_name = String::Handle(Symbols::ThrowNew());
9009 return MakeStaticCall(cls_name, func_name, arguments); 9034 return MakeStaticCall(cls_name, func_name, arguments);
9010 } 9035 }
9011 9036 // TODO(regis): Throw a NoSuchMethodError instead of a TypeError.
9012 String& error_message = String::Handle(); 9037 String& error_message = String::Handle();
9013 if (!constructor.IsNull() && 9038 if (!constructor.AreValidArguments(arguments_length,
9014 !constructor.AreValidArguments(arguments_length,
9015 arguments->names(), 9039 arguments->names(),
9016 &error_message)) { 9040 &error_message)) {
9017 const String& external_constructor_name = 9041 const String& external_constructor_name =
9018 (named_constructor ? constructor_name : constructor_class_name); 9042 (named_constructor ? constructor_name : constructor_class_name);
9019 ErrorMsg(call_pos, 9043 // Replace the type with a malformed type and compile a throw when called.
9020 "invalid arguments passed to constructor '%s' for class '%s': %s", 9044 type = ClassFinalizer::NewFinalizedMalformedType(
9021 external_constructor_name.ToCString(), 9045 current_class(),
9022 String::Handle(constructor_class.Name()).ToCString(), 9046 call_pos,
9023 error_message.ToCString()); 9047 "invalid arguments passed to constructor '%s' for class '%s': %s",
9048 external_constructor_name.ToCString(),
9049 String::Handle(constructor_class.Name()).ToCString(),
9050 error_message.ToCString());
9051 return ThrowTypeError(call_pos, type);
9024 } 9052 }
9025 9053
9026 // Now that the constructor to be called is identified, finalize the type 9054 // Now that the constructor to be called is identified, finalize the type
9027 // argument vector to be passed. 9055 // argument vector to be passed.
9028 // The type argument vector of the parsed type was finalized in ParseType. 9056 // The type argument vector of the parsed type was finalized in ParseType.
9029 // If the constructor class was changed from the interface class to the 9057 // If the constructor class was changed from the interface class to the
9030 // factory class, we need to finalize the type argument vector again, because 9058 // factory class, we need to finalize the type argument vector again, because
9031 // it may be longer due to the factory class extending a class, or/and because 9059 // it may be longer due to the factory class extending a class, or/and because
9032 // the bounds on the factory class may be tighter than on the interface. 9060 // the bounds on the factory class may be tighter than on the interface.
9033 if (!constructor.IsNull() && (constructor_class.raw() != type_class.raw())) { 9061 if (!constructor.IsNull() && (constructor_class.raw() != type_class.raw())) {
(...skipping 25 matching lines...) Expand all
9059 type_arguments = temp_type.arguments(); 9087 type_arguments = temp_type.arguments();
9060 // The type parameter bounds of the factory class may be more specific than 9088 // The type parameter bounds of the factory class may be more specific than
9061 // the type parameter bounds of the interface class. Therefore, although 9089 // the type parameter bounds of the interface class. Therefore, although
9062 // type was not malformed, temp_type may be malformed. 9090 // type was not malformed, temp_type may be malformed.
9063 if (!type.IsMalformed() && temp_type.IsMalformed()) { 9091 if (!type.IsMalformed() && temp_type.IsMalformed()) {
9064 const Error& error = Error::Handle(temp_type.malformed_error()); 9092 const Error& error = Error::Handle(temp_type.malformed_error());
9065 type.set_malformed_error(error); 9093 type.set_malformed_error(error);
9066 } 9094 }
9067 } 9095 }
9068 if (type.IsMalformed()) { 9096 if (type.IsMalformed()) {
9069 // Compile the throw of a dynamic type error due to a bound error or to 9097 // Return the throw of a dynamic type error if the type is malformed.
9070 // a redirection error.
9071 return ThrowTypeError(type_pos, type); 9098 return ThrowTypeError(type_pos, type);
9072 } 9099 }
9073 type_arguments ^= type_arguments.Canonicalize(); 9100 type_arguments ^= type_arguments.Canonicalize();
9074 // Make the constructor call. 9101 // Make the constructor call.
9075 AstNode* new_object = NULL; 9102 AstNode* new_object = NULL;
9076 if (is_const) { 9103 if (is_const) {
9077 if (!constructor.is_const()) { 9104 if (!constructor.is_const()) {
9078 ErrorMsg("'const' requires const constructor: '%s'", 9105 ErrorMsg("'const' requires const constructor: '%s'",
9079 String::Handle(constructor.name()).ToCString()); 9106 String::Handle(constructor.name()).ToCString());
9080 } 9107 }
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after
9694 void Parser::SkipQualIdent() { 9721 void Parser::SkipQualIdent() {
9695 ASSERT(IsIdentifier()); 9722 ASSERT(IsIdentifier());
9696 ConsumeToken(); 9723 ConsumeToken();
9697 if (CurrentToken() == Token::kPERIOD) { 9724 if (CurrentToken() == Token::kPERIOD) {
9698 ConsumeToken(); // Consume the kPERIOD token. 9725 ConsumeToken(); // Consume the kPERIOD token.
9699 ExpectIdentifier("identifier expected after '.'"); 9726 ExpectIdentifier("identifier expected after '.'");
9700 } 9727 }
9701 } 9728 }
9702 9729
9703 } // namespace dart 9730 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.cc ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698