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

Unified Diff: runtime/vm/parser.cc

Issue 11049038: Change compile-time errors into dynamic errors in instance creation expression (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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 13204)
+++ runtime/vm/parser.cc (working copy)
@@ -1513,7 +1513,7 @@
}
return new StaticGetterNode(
- field_pos, implicit_argument, true, super_class, field_name);
+ field_pos, implicit_argument, true, super_class, field_name);
}
@@ -3646,6 +3646,10 @@
// Map a malformed type argument to Dynamic, so that malformed types with
// a resolved type class are handled properly in production mode.
if (type.IsMalformed()) {
+ ASSERT(finalization != ClassFinalizer::kCanonicalizeWellFormed);
+ if (finalization == ClassFinalizer::kCanonicalizeForCreation) {
+ ErrorMsg(*malformed_error);
+ }
type = Type::DynamicType();
}
types.Add(type);
@@ -6676,6 +6680,20 @@
}
+AstNode* Parser::ThrowNoSuchMethodError(intptr_t call_pos, const String& name) {
+ ArgumentListNode* arguments = new ArgumentListNode(call_pos);
+ // Location argument.
+ arguments->Add(new LiteralNode(
+ call_pos, Integer::ZoneHandle(Integer::New(call_pos))));
+ // Function name argument.
+ arguments->Add(new LiteralNode(
+ call_pos, String::ZoneHandle(Symbols::New(name))));
+ const String& cls_name = String::Handle(Symbols::NoSuchMethodError());
+ const String& func_name = String::Handle(Symbols::ThrowNew());
+ return MakeStaticCall(cls_name, func_name, arguments);
+}
+
+
AstNode* Parser::ParseBinaryExpr(int min_preced) {
TRACE_PARSER("ParseBinaryExpr");
ASSERT(min_preced >= 4);
@@ -6944,6 +6962,11 @@
// Ensure that the expression temp is allocated for nodes that may need it.
AstNode* Parser::CreateAssignmentNode(AstNode* original, AstNode* rhs) {
AstNode* result = original->MakeAssignmentNode(rhs);
+ if ((result == NULL) && original->IsStaticGetterNode()) {
+ const String& setter_name = String::ZoneHandle(
+ Field::SetterSymbol(original->AsStaticGetterNode()->field_name()));
+ result = ThrowNoSuchMethodError(original->token_pos(), setter_name);
+ }
if ((result != NULL) &&
(result->IsStoreIndexedNode() ||
result->IsInstanceSetterNode() ||
@@ -7219,22 +7242,8 @@
closure = GenerateStaticFieldLookup(field, call_pos);
return new ClosureCallNode(call_pos, closure, arguments);
}
- // Could not resolve static method: throw an exception if the arguments
- // do not match or compile time error otherwise.
- const Function& test_func = Function::Handle(
- Resolver::ResolveStaticByName(cls, func_name, Resolver::kIsQualified));
- if (test_func.IsNull()) {
- ErrorMsg(ident_pos, "unresolved static method '%s'",
- func_name.ToCString());
- } else {
- ArgumentListNode* arguments = new ArgumentListNode(ident_pos);
- arguments->Add(new LiteralNode(
- TokenPos(), Integer::ZoneHandle(Integer::New(ident_pos))));
- const String& cls_name =
- String::Handle(Symbols::StaticResolutionException());
- const String& func_name = String::Handle(Symbols::ThrowNew());
- return MakeStaticCall(cls_name, func_name, arguments);
- }
+ // Could not resolve static method: throw a NoSuchMethodError.
+ return ThrowNoSuchMethodError(ident_pos, func_name);
}
CheckFunctionIsCallable(call_pos, func);
return new StaticCallNode(call_pos, func, arguments);
@@ -7306,9 +7315,8 @@
kNoArgumentNames,
Resolver::kIsQualified);
if (func.IsNull()) {
- // No field or explicit setter function, this is an error.
- ErrorMsg(ident_pos, "unknown static field '%s'",
- field_name.ToCString());
+ // No field or explicit setter function, throw a NoSuchMethodError.
+ return ThrowNoSuchMethodError(ident_pos, field_name);
}
// Explicit setter function for the field found, field does not exist.
@@ -7348,9 +7356,8 @@
// there is a function of the same name.
func = cls.LookupStaticFunction(field_name);
if (func.IsNull()) {
- // No field or explicit getter function, this is an error.
- ErrorMsg(ident_pos,
- "unknown static field '%s'", field_name.ToCString());
+ // No field or explicit getter function, throw a NoSuchMethodError.
+ return ThrowNoSuchMethodError(ident_pos, field_name);
}
access = CreateImplicitClosureNode(func, call_pos, NULL);
} else {
@@ -7375,15 +7382,14 @@
}
PrimaryNode* primary = node->AsPrimaryNode();
if (primary->primary().IsString()) {
- // In a static method, an unresolved identifier is an error.
+ // In a static method, evaluation of an unresolved identifier causes a
+ // NoSuchMethodError to be thrown.
// In an instance method, we convert this into a getter call
// for a field (which may be defined in a subclass.)
String& name = String::CheckedZoneHandle(primary->primary().raw());
if (current_function().is_static() ||
current_function().IsInFactoryScope()) {
- ErrorMsg(primary->token_pos(),
- "identifier '%s' is not declared in this scope",
- name.ToCString());
+ return ThrowNoSuchMethodError(primary->token_pos(), name);
} else {
AstNode* receiver = LoadReceiver(primary->token_pos());
return CallGetter(node->token_pos(), receiver, name);
@@ -7508,9 +7514,7 @@
// Primary is an unresolved name.
String& name = String::CheckedZoneHandle(primary->primary().raw());
if (current_function().is_static()) {
- ErrorMsg(primary->token_pos(),
- "identifier '%s' is not declared in this scope",
- name.ToCString());
+ selector = ThrowNoSuchMethodError(primary->token_pos(), name);
} else {
// Treat as call to unresolved (instance) method.
AstNode* receiver = LoadReceiver(primary->token_pos());
@@ -8350,12 +8354,12 @@
PrimaryNode* primary = resolved->AsPrimaryNode();
if (primary->primary().IsString()) {
// We got an unresolved name. If we are compiling a static
- // method, this is an error. In an instance method, we convert
+ // method, evaluation of an unresolved identifier causes a
+ // NoSuchMethodError to be thrown. In an instance method, we convert
// the unresolved name to an instance field access, since a
// subclass might define a field with this name.
if (current_function().is_static()) {
- ErrorMsg(ident_pos, "identifier '%s' is not declared in this scope",
- ident.ToCString());
+ resolved = ThrowNoSuchMethodError(ident_pos, ident);
} else {
// Treat as call to unresolved instance field.
resolved = CallGetter(ident_pos, LoadReceiver(ident_pos), ident);
@@ -8864,7 +8868,7 @@
}
intptr_t type_pos = TokenPos();
AbstractType& type = AbstractType::Handle(
- ParseType(ClassFinalizer::kCanonicalizeWellFormed));
+ ParseType(ClassFinalizer::kCanonicalizeForCreation));
// In case the type is malformed, throw a dynamic type error after finishing
// parsing the instance creation expression.
if (type.IsTypeParameter() || type.IsDynamicType()) {
@@ -8895,8 +8899,13 @@
intptr_t call_pos = TokenPos();
ArgumentListNode* arguments = ParseActualParameters(NULL, is_const);
- // Parsing is complete, so we can return a throw in case of a malformed type.
+ // Parsing is complete, so we can return a throw in case of a malformed type
+ // or report a compile-time error if the constructor is const.
if (type.IsMalformed()) {
+ if (is_const) {
+ const Error& error = Error::Handle(type.malformed_error());
+ ErrorMsg(error);
+ }
return ThrowTypeError(type_pos, type);
}
@@ -8927,30 +8936,33 @@
Function& constructor = Function::ZoneHandle(
type_class.LookupConstructor(constructor_name));
if (constructor.IsNull()) {
- // Replace the type with a malformed type and compile a throw.
+ // Replace the type with a malformed type and compile a throw or report
+ // a compile-time error if the constructor is const.
type = ClassFinalizer::NewFinalizedMalformedType(
current_class(),
- type_pos,
+ call_pos,
"interface '%s' has no constructor named '%s'",
type_class_name.ToCString(),
external_constructor_name.ToCString());
- return ThrowTypeError(type_pos, type);
+ if (is_const) {
+ const Error& error = Error::Handle(type.malformed_error());
+ ErrorMsg(error);
+ }
+ return ThrowNoSuchMethodError(call_pos, external_constructor_name);
}
- // TODO(regis): Throw a NoSuchMethodError instead of a TypeError.
String& error_message = String::Handle();
if (!constructor.AreValidArguments(arguments_length,
arguments->names(),
&error_message)) {
- // Replace the type with a malformed type and compile a throw.
- type = ClassFinalizer::NewFinalizedMalformedType(
- current_class(),
- call_pos,
- "invalid arguments passed to constructor '%s' "
- "for interface '%s': %s",
- external_constructor_name.ToCString(),
- type_class_name.ToCString(),
- error_message.ToCString());
- return ThrowTypeError(call_pos, type);
+ if (is_const) {
+ ErrorMsg(call_pos,
+ "invalid arguments passed to constructor '%s' "
+ "for interface '%s': %s",
+ external_constructor_name.ToCString(),
+ type_class_name.ToCString(),
+ error_message.ToCString());
+ }
+ return ThrowNoSuchMethodError(call_pos, external_constructor_name);
}
// TODO(regis): Remove support for obsolete default factory classes.
if (!type_class.HasFactoryClass()) {
@@ -8992,17 +9004,26 @@
if (constructor.IsNull()) {
const String& external_constructor_name =
(named_constructor ? constructor_name : constructor_class_name);
- // Replace the type with a malformed type and compile a throw.
+ // Replace the type with a malformed type and compile a throw or report a
+ // compile-time error if the constructor is const.
type = ClassFinalizer::NewFinalizedMalformedType(
current_class(),
- type_pos,
+ call_pos,
"class '%s' has no constructor or factory named '%s'",
String::Handle(constructor_class.Name()).ToCString(),
external_constructor_name.ToCString());
- return ThrowTypeError(type_pos, type);
+ if (is_const) {
+ const Error& error = Error::Handle(type.malformed_error());
+ ErrorMsg(error);
+ }
+ return ThrowNoSuchMethodError(call_pos, external_constructor_name);
} else if (constructor.IsRedirectingFactory()) {
type = constructor.RedirectionType();
if (type.IsMalformed()) {
+ if (is_const) {
+ const Error& error = Error::Handle(type.malformed_error());
+ ErrorMsg(error);
+ }
return ThrowTypeError(type.token_pos(), type);
}
constructor = constructor.RedirectionTarget();
@@ -9033,22 +9054,21 @@
const String& func_name = String::Handle(Symbols::ThrowNew());
return MakeStaticCall(cls_name, func_name, arguments);
}
- // TODO(regis): Throw a NoSuchMethodError instead of a TypeError.
String& error_message = String::Handle();
if (!constructor.AreValidArguments(arguments_length,
arguments->names(),
&error_message)) {
const String& external_constructor_name =
(named_constructor ? constructor_name : constructor_class_name);
- // Replace the type with a malformed type and compile a throw when called.
- type = ClassFinalizer::NewFinalizedMalformedType(
- current_class(),
- call_pos,
- "invalid arguments passed to constructor '%s' for class '%s': %s",
- external_constructor_name.ToCString(),
- String::Handle(constructor_class.Name()).ToCString(),
- error_message.ToCString());
- return ThrowTypeError(call_pos, type);
+ if (is_const) {
+ ErrorMsg(call_pos,
+ "invalid arguments passed to constructor '%s' "
+ "for class '%s': %s",
+ external_constructor_name.ToCString(),
+ String::Handle(constructor_class.Name()).ToCString(),
+ error_message.ToCString());
+ }
+ return ThrowNoSuchMethodError(call_pos, external_constructor_name);
}
// Now that the constructor to be called is identified, finalize the type
@@ -9093,8 +9113,13 @@
type.set_malformed_error(error);
}
}
+ // Return a throw in case of a malformed type or report a compile-time error
+ // if the constructor is const.
if (type.IsMalformed()) {
- // Return the throw of a dynamic type error if the type is malformed.
+ if (is_const) {
+ const Error& error = Error::Handle(type.malformed_error());
+ ErrorMsg(error);
+ }
return ThrowTypeError(type_pos, type);
}
type_arguments ^= type_arguments.Canonicalize();
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698