Chromium Code Reviews| Index: runtime/vm/parser.cc |
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
| index c8d2aa1a51760d28959424faff94ec01121e017d..7c250ae19bfe476a5993b800a04577af032aa4cd 100644 |
| --- a/runtime/vm/parser.cc |
| +++ b/runtime/vm/parser.cc |
| @@ -10481,7 +10481,7 @@ AstNode* Parser::ThrowNoSuchMethodError(TokenPosition call_pos, |
| ArgumentListNode* arguments = new (Z) ArgumentListNode(call_pos); |
| String& method_name = String::Handle(Z); |
| - if (prefix == NULL) { |
| + if (prefix == NULL || !prefix->is_deferred_load()) { |
| method_name = Library::PrivateCoreLibName(Symbols::ThrowNew()).raw(); |
| } else { |
| arguments->Add(new (Z) LiteralNode(call_pos, *prefix)); |
| @@ -11219,7 +11219,8 @@ ArgumentListNode* Parser::ParseActualParameters( |
| AstNode* Parser::ParseStaticCall(const Class& cls, |
| const String& func_name, |
| - TokenPosition ident_pos) { |
| + TokenPosition ident_pos, |
| + const LibraryPrefix* prefix) { |
| TRACE_PARSER("ParseStaticCall"); |
| const TokenPosition call_pos = TokenPos(); |
| ASSERT(CurrentToken() == Token::kLPAREN); |
| @@ -11255,7 +11256,8 @@ AstNode* Parser::ParseStaticCall(const Class& cls, |
| return ThrowNoSuchMethodError(ident_pos, cls, func_name, arguments, |
| InvocationMirror::kStatic, |
| InvocationMirror::kMethod, |
| - NULL); // No existing function. |
| + NULL, // No existing function. |
| + prefix); |
|
rmacnak
2017/01/05 22:50:11
Please add an assert in ThrowNoSuchMethodError tha
Florian Schneider
2017/01/06 02:12:12
Done.
|
| } else if (cls.IsTopLevel() && (cls.library() == Library::CoreLibrary()) && |
| (func.name() == Symbols::Identical().raw())) { |
| // This is the predefined toplevel function identical(a,b). |
| @@ -11392,8 +11394,15 @@ AstNode* Parser::LoadFieldIfUnresolved(AstNode* node) { |
| // for a field (which may be defined in a subclass.) |
| const String& name = |
| String::Cast(Object::ZoneHandle(primary->primary().raw())); |
| - if (current_function().is_static() || |
| - current_function().IsInFactoryScope()) { |
| + if (primary->is_deferred_reference()) { |
| + StaticGetterNode* getter = new (Z) StaticGetterNode( |
| + primary->token_pos(), |
| + NULL, // No receiver. |
| + Class::ZoneHandle(Z, library_.toplevel_class()), name); |
| + getter->set_is_deferred(primary->is_deferred_reference()); |
| + return getter; |
| + } else if (current_function().is_static() || |
| + current_function().IsInFactoryScope()) { |
| StaticGetterNode* getter = new (Z) |
| StaticGetterNode(primary->token_pos(), |
| NULL, // No receiver. |
| @@ -11506,13 +11515,21 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) { |
| // For now, resolve type arguments and ignore. |
| ParseTypeArguments(ClassFinalizer::kCanonicalize); |
| } |
| - if (left->IsPrimaryNode() && |
| - left->AsPrimaryNode()->primary().IsClass()) { |
| + PrimaryNode* primary_node = left->AsPrimaryNode(); |
| + if ((primary_node != NULL) && primary_node->primary().IsClass()) { |
| // Static method call prefixed with class name. |
| - const Class& cls = Class::Cast(left->AsPrimaryNode()->primary()); |
| - selector = ParseStaticCall(cls, *ident, ident_pos); |
| + const Class& cls = Class::Cast(primary_node->primary()); |
| + selector = |
| + ParseStaticCall(cls, *ident, ident_pos, primary_node->prefix()); |
| } else { |
| - selector = ParseInstanceCall(left, *ident, ident_pos, is_conditional); |
| + if ((primary_node != NULL) && primary_node->is_deferred_reference()) { |
| + const Class& cls = Class::Handle(library_.toplevel_class()); |
| + selector = |
| + ParseStaticCall(cls, *ident, ident_pos, primary_node->prefix()); |
| + } else { |
| + selector = |
| + ParseInstanceCall(left, *ident, ident_pos, is_conditional); |
| + } |
| } |
| } else { |
| // Field access. |
| @@ -11520,11 +11537,13 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) { |
| bool is_deferred = false; |
| if (left->IsPrimaryNode()) { |
| PrimaryNode* primary_node = left->AsPrimaryNode(); |
| + is_deferred = primary_node->is_deferred_reference(); |
| if (primary_node->primary().IsClass()) { |
| // If the primary node referred to a class we are loading a |
| // qualified static field. |
| cls ^= primary_node->primary().raw(); |
| - is_deferred = primary_node->is_deferred_reference(); |
| + } else if (is_deferred) { |
| + cls = library_.toplevel_class(); |
| } |
| } |
| if (cls.IsNull()) { |
| @@ -11616,7 +11635,12 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) { |
| } |
| const String& name = |
| String::Cast(Object::ZoneHandle(primary_node->primary().raw())); |
| - if (current_function().is_static()) { |
| + if (primary_node->is_deferred_reference()) { |
| + // The static call will be converted to throwing a NSM error. |
| + const Class& cls = Class::Handle(library_.toplevel_class()); |
| + selector = |
| + ParseStaticCall(cls, name, primary_pos, primary_node->prefix()); |
| + } else if (current_function().is_static()) { |
| // The static call will be converted to throwing a NSM error. |
| selector = ParseStaticCall(current_class(), name, primary_pos); |
| } else { |
| @@ -12503,7 +12527,9 @@ AstNode* Parser::ResolveIdentInPrefixScope(TokenPosition ident_pos, |
| const Class& cls = Class::Cast(obj); |
| PrimaryNode* primary = |
| new (Z) PrimaryNode(ident_pos, Class::ZoneHandle(Z, cls.raw())); |
| - primary->set_is_deferred(is_deferred); |
| + if (is_deferred) { |
| + primary->set_prefix(&prefix); |
| + } |
| return primary; |
| } else if (obj.IsField()) { |
| const Field& field = Field::Cast(obj); |
| @@ -12532,7 +12558,9 @@ AstNode* Parser::ResolveIdentInPrefixScope(TokenPosition ident_pos, |
| } else { |
| PrimaryNode* primary = |
| new (Z) PrimaryNode(ident_pos, Function::ZoneHandle(Z, func.raw())); |
| - primary->set_is_deferred(is_deferred); |
| + if (is_deferred) { |
| + primary->set_prefix(&prefix); |
| + } |
| return primary; |
| } |
| } |
| @@ -13969,6 +13997,9 @@ AstNode* Parser::ParsePrimary() { |
| const String& qualified_name = |
| String::ZoneHandle(Z, Symbols::FromConcatAll(T, pieces)); |
| primary = new (Z) PrimaryNode(qual_ident_pos, qualified_name); |
| + if (prefix.is_deferred_load()) { |
| + primary->AsPrimaryNode()->set_prefix(&prefix); |
| + } |
| } |
| } else if (FLAG_load_deferred_eagerly && prefix.is_deferred_load()) { |
| // primary != NULL. |