Index: runtime/vm/parser.cc |
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
index 5964c1104ab946c366a9e9f78dafbc4f9ee79bdf..eb3454bf37a250629a3ce25037cf655e02bcd29f 100644 |
--- a/runtime/vm/parser.cc |
+++ b/runtime/vm/parser.cc |
@@ -44,7 +44,10 @@ namespace dart { |
DEFINE_FLAG(bool, enable_debug_break, false, "Allow use of break \"message\"."); |
DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); |
-DEFINE_FLAG(bool, warn_new_tearoff_syntax, true, "Warning on new tear off."); |
+DEFINE_FLAG(bool, |
+ support_new_tearoff_syntax, |
+ false, |
+ "Support new tear off syntax."); |
// TODO(floitsch): remove the conditional-directive flag, once we publicly |
// committed to the current version. |
DEFINE_FLAG(bool, |
@@ -11704,148 +11707,151 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) { |
// Closurization e#m of getter, setter, method or operator. |
AstNode* Parser::ParseClosurization(AstNode* primary) { |
- if (FLAG_warn_new_tearoff_syntax) { |
- ReportWarning( |
- "Tear-offs using the x#id syntax is a deprecated feature," |
- "it will not be supported in the next release"); |
- } |
- ExpectToken(Token::kHASH); |
- TokenPosition property_pos = TokenPos(); |
- bool is_setter_name = false; |
+ if (!FLAG_support_new_tearoff_syntax) { |
+ ReportError("Tear-offs using the x#id syntax is a deprecated feature"); |
regis
2016/12/29 18:24:07
I have not followed the discussions about this tea
siva
2016/12/29 20:59:56
Good point, I renamed the flag to --deprecated_tea
|
+ return NULL; |
+ } else { |
regis
2016/12/29 18:24:07
I would not use an else here and leave the rest of
siva
2016/12/29 20:59:56
Done.
|
+ ExpectToken(Token::kHASH); |
+ TokenPosition property_pos = TokenPos(); |
+ bool is_setter_name = false; |
- String& extractor_name = String::ZoneHandle(Z); |
- if (IsIdentifier()) { |
- extractor_name = CurrentLiteral()->raw(); |
- ConsumeToken(); |
- if (CurrentToken() == Token::kASSIGN) { |
+ String& extractor_name = String::ZoneHandle(Z); |
+ if (IsIdentifier()) { |
+ extractor_name = CurrentLiteral()->raw(); |
ConsumeToken(); |
- is_setter_name = true; |
+ if (CurrentToken() == Token::kASSIGN) { |
+ ConsumeToken(); |
+ is_setter_name = true; |
+ } |
+ } else if (Token::CanBeOverloaded(CurrentToken())) { |
+ extractor_name = Symbols::Token(CurrentToken()).raw(); |
+ ConsumeToken(); |
+ } else { |
+ ReportError("identifier or operator expected"); |
} |
- } else if (Token::CanBeOverloaded(CurrentToken())) { |
- extractor_name = Symbols::Token(CurrentToken()).raw(); |
- ConsumeToken(); |
- } else { |
- ReportError("identifier or operator expected"); |
- } |
- |
- if (primary->IsPrimaryNode() && primary->AsPrimaryNode()->IsSuper()) { |
- // TODO(hausner): implement super#m |
- ReportError("closurization of super method not yet supported"); |
- } |
- |
- // Handle closurization of top-level names from library prefixes, P#m |
- if (primary->IsLiteralNode() && |
- primary->AsLiteralNode()->literal().IsLibraryPrefix()) { |
- const LibraryPrefix& prefix = |
- LibraryPrefix::Cast(primary->AsLiteralNode()->literal()); |
- Object& obj = Object::Handle(Z); |
- const bool is_private_name = |
- (extractor_name.CharAt(0) == Library::kPrivateIdentifierStart); |
- if (!is_private_name) { |
- // Private names are not exported by libraries. The name mangling |
- // of private names with a library-specific suffix usually ensures |
- // that _x in library A is not found when looked up from library B. |
- // In the pathological case where a library imports itself with |
- // a prefix, the name mangling does not help in hiding the private |
- // name, so we explicitly prevent lookup of private names here. |
- if (is_setter_name) { |
- String& setter_name = |
- String::Handle(Z, Field::SetterName(extractor_name)); |
- obj = prefix.LookupObject(setter_name); |
+ |
+ if (primary->IsPrimaryNode() && primary->AsPrimaryNode()->IsSuper()) { |
+ // TODO(hausner): implement super#m |
+ ReportError("closurization of super method not yet supported"); |
+ } |
+ |
+ // Handle closurization of top-level names from library prefixes, P#m |
+ if (primary->IsLiteralNode() && |
+ primary->AsLiteralNode()->literal().IsLibraryPrefix()) { |
+ const LibraryPrefix& prefix = |
+ LibraryPrefix::Cast(primary->AsLiteralNode()->literal()); |
+ Object& obj = Object::Handle(Z); |
+ const bool is_private_name = |
+ (extractor_name.CharAt(0) == Library::kPrivateIdentifierStart); |
+ if (!is_private_name) { |
+ // Private names are not exported by libraries. The name mangling |
+ // of private names with a library-specific suffix usually ensures |
+ // that _x in library A is not found when looked up from library B. |
+ // In the pathological case where a library imports itself with |
+ // a prefix, the name mangling does not help in hiding the private |
+ // name, so we explicitly prevent lookup of private names here. |
+ if (is_setter_name) { |
+ String& setter_name = |
+ String::Handle(Z, Field::SetterName(extractor_name)); |
+ obj = prefix.LookupObject(setter_name); |
+ } |
+ if (obj.IsNull()) { |
+ obj = prefix.LookupObject(extractor_name); |
+ } |
} |
- if (obj.IsNull()) { |
- obj = prefix.LookupObject(extractor_name); |
+ if (!prefix.is_loaded() && (parsed_function() != NULL) && |
+ !FLAG_load_deferred_eagerly) { |
+ // Remember that this function depends on an import prefix of an |
+ // unloaded deferred library. |
+ parsed_function()->AddDeferredPrefix(prefix); |
} |
- } |
- if (!prefix.is_loaded() && (parsed_function() != NULL) && |
- !FLAG_load_deferred_eagerly) { |
- // Remember that this function depends on an import prefix of an |
- // unloaded deferred library. |
- parsed_function()->AddDeferredPrefix(prefix); |
- } |
- if (obj.IsFunction()) { |
- const Function& func = Function::Cast(obj); |
- if (!func.IsSetterFunction() || is_setter_name) { |
- return CreateImplicitClosureNode(func, property_pos, NULL); |
- } |
- } else if (obj.IsField()) { |
- const Field& field = Field::Cast(obj); |
- if (is_setter_name && !field.is_final()) { |
- Instance& setter_closure = Instance::ZoneHandle(field.SetterClosure()); |
- return new (Z) LiteralNode(property_pos, setter_closure); |
- } |
- if (!is_setter_name) { |
- Instance& getter_closure = Instance::ZoneHandle(field.GetterClosure()); |
- return new (Z) LiteralNode(property_pos, getter_closure); |
- } |
- } |
- return ThrowNoSuchMethodError( |
- property_pos, current_class(), extractor_name, |
- NULL, // No arguments. |
- InvocationMirror::kTopLevel, |
- is_setter_name ? InvocationMirror::kSetter : InvocationMirror::kMethod, |
- NULL); // No existing function. |
- } |
- |
- // Handle closurization of static properties of classes, C#n. |
- if (primary->IsPrimaryNode() && |
- primary->AsPrimaryNode()->primary().IsClass()) { |
- const Class& cls = Class::Cast(primary->AsPrimaryNode()->primary()); |
- const Field& field = |
- Field::Handle(Z, cls.LookupStaticField(extractor_name)); |
- if (!field.IsNull()) { |
- if (is_setter_name) { |
- extractor_name = Field::SetterName(extractor_name); |
- if (!field.is_final()) { |
+ if (obj.IsFunction()) { |
+ const Function& func = Function::Cast(obj); |
+ if (!func.IsSetterFunction() || is_setter_name) { |
+ return CreateImplicitClosureNode(func, property_pos, NULL); |
+ } |
+ } else if (obj.IsField()) { |
+ const Field& field = Field::Cast(obj); |
+ if (is_setter_name && !field.is_final()) { |
const Instance& setter_closure = |
- Instance::ZoneHandle(Z, field.SetterClosure()); |
- ASSERT(setter_closure.IsClosure()); |
- // Note: the created closure is cached after it's created |
- // once. If eager compilation is desired, the compiler can |
- // be invoked here. The same applies for getters below. |
+ Instance::ZoneHandle(field.SetterClosure()); |
return new (Z) LiteralNode(property_pos, setter_closure); |
} |
- } else { |
- const Instance& getter_closure = |
- Instance::ZoneHandle(Z, field.GetterClosure()); |
- ASSERT(getter_closure.IsClosure()); |
- return new (Z) LiteralNode(property_pos, getter_closure); |
+ if (!is_setter_name) { |
+ const Instance& getter_closure = |
+ Instance::ZoneHandle(field.GetterClosure()); |
+ return new (Z) LiteralNode(property_pos, getter_closure); |
+ } |
} |
- } else { |
- Function& func = Function::Handle(Z); |
- if (is_setter_name) { |
- extractor_name = Field::SetterName(extractor_name); |
- func = cls.LookupStaticFunction(extractor_name); |
+ return ThrowNoSuchMethodError(property_pos, current_class(), |
+ extractor_name, |
+ NULL, // No arguments. |
+ InvocationMirror::kTopLevel, |
+ is_setter_name ? InvocationMirror::kSetter |
+ : InvocationMirror::kMethod, |
+ NULL); // No existing function. |
+ } |
+ |
+ // Handle closurization of static properties of classes, C#n. |
+ if (primary->IsPrimaryNode() && |
+ primary->AsPrimaryNode()->primary().IsClass()) { |
+ const Class& cls = Class::Cast(primary->AsPrimaryNode()->primary()); |
+ const Field& field = |
+ Field::Handle(Z, cls.LookupStaticField(extractor_name)); |
+ if (!field.IsNull()) { |
+ if (is_setter_name) { |
+ extractor_name = Field::SetterName(extractor_name); |
+ if (!field.is_final()) { |
+ const Instance& setter_closure = |
+ Instance::ZoneHandle(Z, field.SetterClosure()); |
+ ASSERT(setter_closure.IsClosure()); |
+ // Note: the created closure is cached after it's created |
+ // once. If eager compilation is desired, the compiler can |
+ // be invoked here. The same applies for getters below. |
+ return new (Z) LiteralNode(property_pos, setter_closure); |
+ } |
+ } else { |
+ const Instance& getter_closure = |
+ Instance::ZoneHandle(Z, field.GetterClosure()); |
+ ASSERT(getter_closure.IsClosure()); |
+ return new (Z) LiteralNode(property_pos, getter_closure); |
+ } |
} else { |
- func = cls.LookupStaticFunction(extractor_name); |
- if (func.IsNull()) { |
- const String& getter_name = |
- String::Handle(Z, Field::GetterName(extractor_name)); |
- func = cls.LookupStaticFunction(getter_name); |
+ Function& func = Function::Handle(Z); |
+ if (is_setter_name) { |
+ extractor_name = Field::SetterName(extractor_name); |
+ func = cls.LookupStaticFunction(extractor_name); |
+ } else { |
+ func = cls.LookupStaticFunction(extractor_name); |
+ if (func.IsNull()) { |
+ const String& getter_name = |
+ String::Handle(Z, Field::GetterName(extractor_name)); |
+ func = cls.LookupStaticFunction(getter_name); |
+ } |
+ } |
+ if (!func.IsNull()) { |
+ return CreateImplicitClosureNode(func, property_pos, NULL); |
} |
} |
- if (!func.IsNull()) { |
- return CreateImplicitClosureNode(func, property_pos, NULL); |
- } |
+ return ThrowNoSuchMethodError(property_pos, cls, extractor_name, |
+ NULL, // No arguments. |
+ InvocationMirror::kStatic, |
+ is_setter_name ? InvocationMirror::kSetter |
+ : InvocationMirror::kMethod, |
+ NULL); // No existing function. |
} |
- return ThrowNoSuchMethodError( |
- property_pos, cls, extractor_name, |
- NULL, // No arguments. |
- InvocationMirror::kStatic, |
- is_setter_name ? InvocationMirror::kSetter : InvocationMirror::kMethod, |
- NULL); // No existing function. |
- } |
- // Closurization of instance getter, setter, method or operator. |
- GrowableHandlePtrArray<const String> pieces(Z, 3); |
- pieces.Add(Symbols::HashMark()); |
- if (is_setter_name) { |
- pieces.Add(Symbols::SetterPrefix()); |
+ // Closurization of instance getter, setter, method or operator. |
+ GrowableHandlePtrArray<const String> pieces(Z, 3); |
+ pieces.Add(Symbols::HashMark()); |
+ if (is_setter_name) { |
+ pieces.Add(Symbols::SetterPrefix()); |
+ } |
+ pieces.Add(extractor_name); |
+ extractor_name = Symbols::FromConcatAll(T, pieces); |
+ return new (Z) InstanceGetterNode(property_pos, primary, extractor_name); |
} |
- pieces.Add(extractor_name); |
- extractor_name = Symbols::FromConcatAll(T, pieces); |
- return new (Z) InstanceGetterNode(property_pos, primary, extractor_name); |
} |
@@ -13348,41 +13354,40 @@ void Parser::ParseConstructorClosurization(Function* constructor, |
// type that is loaded. |
ASSERT(prefix.IsNull() || prefix.is_loaded()); |
ASSERT(!type.IsMalformed() && !type.IsTypeParameter()); |
- if (FLAG_warn_new_tearoff_syntax) { |
- ReportWarning( |
- "Tear-offs using the x#id syntax is a deprecated feature," |
- "it will not be supported in the next release"); |
- } |
- ExpectToken(Token::kHASH); |
- String* named_constructor = NULL; |
- if (IsIdentifier()) { |
- named_constructor = CurrentLiteral(); |
- ConsumeToken(); |
- } |
- // Resolve the type and optional identifier to a constructor or factory. |
- Class& type_class = Class::Handle(Z, type.type_class()); |
- String& type_class_name = String::Handle(Z, type_class.Name()); |
- *type_arguments = type.arguments(); |
- String& constructor_name = |
- BuildConstructorName(T, type_class_name, named_constructor); |
- *constructor = type_class.LookupConstructor(constructor_name); |
- if (constructor->IsNull()) { |
- *constructor = type_class.LookupFactory(constructor_name); |
- ASSERT(!constructor->IsNull()); |
- if (constructor->IsRedirectingFactory()) { |
- ClassFinalizer::ResolveRedirectingFactory(type_class, *constructor); |
- type = constructor->RedirectionType(); |
- ASSERT(!type.IsMalformedOrMalbounded()); |
- if (!type.IsInstantiated()) { |
- Error& error = Error::Handle(Z); |
- type ^= type.InstantiateFrom(*type_arguments, &error, |
- NULL, // instantiation_trail |
- NULL, // bound_trail |
- Heap::kOld); |
- ASSERT(error.IsNull()); |
+ if (!FLAG_support_new_tearoff_syntax) { |
+ ReportError("Tear-offs using the x#id syntax is a deprecated feature"); |
+ } else { |
regis
2016/12/29 18:24:07
ditto
siva
2016/12/29 20:59:56
Done.
|
+ ExpectToken(Token::kHASH); |
+ String* named_constructor = NULL; |
+ if (IsIdentifier()) { |
+ named_constructor = CurrentLiteral(); |
+ ConsumeToken(); |
+ } |
+ // Resolve the type and optional identifier to a constructor or factory. |
+ Class& type_class = Class::Handle(Z, type.type_class()); |
+ String& type_class_name = String::Handle(Z, type_class.Name()); |
+ *type_arguments = type.arguments(); |
+ String& constructor_name = |
+ BuildConstructorName(T, type_class_name, named_constructor); |
+ *constructor = type_class.LookupConstructor(constructor_name); |
+ if (constructor->IsNull()) { |
+ *constructor = type_class.LookupFactory(constructor_name); |
+ ASSERT(!constructor->IsNull()); |
+ if (constructor->IsRedirectingFactory()) { |
+ ClassFinalizer::ResolveRedirectingFactory(type_class, *constructor); |
+ type = constructor->RedirectionType(); |
+ ASSERT(!type.IsMalformedOrMalbounded()); |
+ if (!type.IsInstantiated()) { |
+ Error& error = Error::Handle(Z); |
+ type ^= type.InstantiateFrom(*type_arguments, &error, |
+ NULL, // instantiation_trail |
+ NULL, // bound_trail |
+ Heap::kOld); |
+ ASSERT(error.IsNull()); |
+ } |
+ *type_arguments = type.arguments(); |
+ *constructor = constructor->RedirectionTarget(); |
} |
- *type_arguments = type.arguments(); |
- *constructor = constructor->RedirectionTarget(); |
} |
} |
} |
@@ -13451,14 +13456,13 @@ AstNode* Parser::ParseNewOperator(Token::Kind op_kind) { |
if (is_const) { |
ReportError("tear-off closure not allowed with const allocation"); |
} |
- if (FLAG_warn_new_tearoff_syntax) { |
- ReportWarning( |
- "Tear-offs using the x#id syntax is a deprecated feature," |
- "and will not be supported in the next release"); |
- } |
- ConsumeToken(); |
- if (IsIdentifier()) { |
- named_constructor = ExpectIdentifier("name of constructor expected"); |
+ if (!FLAG_support_new_tearoff_syntax) { |
+ ReportError("Tear-offs using the x#id syntax is a deprecated feature"); |
+ } else { |
regis
2016/12/29 18:24:07
ditto
siva
2016/12/29 20:59:56
Done.
|
+ ConsumeToken(); |
+ if (IsIdentifier()) { |
+ named_constructor = ExpectIdentifier("name of constructor expected"); |
+ } |
} |
} else if (CurrentToken() == Token::kPERIOD) { |
ConsumeToken(); |
@@ -13893,13 +13897,14 @@ AstNode* Parser::ParsePrimary() { |
const LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(Z, ParsePrefix()); |
if (!prefix.IsNull()) { |
if (CurrentToken() == Token::kHASH) { |
- if (FLAG_warn_new_tearoff_syntax) { |
- ReportWarning( |
- "Tear-offs using the x#id syntax is a deprecated feature," |
- "it will not be supported in the next release"); |
+ if (!FLAG_support_new_tearoff_syntax) { |
+ ReportError( |
+ "Tear-offs using the x#id syntax " |
+ "is a deprecated feature"); |
+ } else { |
regis
2016/12/29 18:24:07
ditto
siva
2016/12/29 20:59:56
Done.
|
+ // Closurization of top-level entity in prefix scope. |
+ return new (Z) LiteralNode(qual_ident_pos, prefix); |
} |
- // Closurization of top-level entity in prefix scope. |
- return new (Z) LiteralNode(qual_ident_pos, prefix); |
} else { |
ExpectToken(Token::kPERIOD); |
} |