| OLD | NEW |
| 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 "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
| 9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 2418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2429 | 2429 |
| 2430 // Parse expressions of instance fields that have an explicit | 2430 // Parse expressions of instance fields that have an explicit |
| 2431 // initializer expression. | 2431 // initializer expression. |
| 2432 // The receiver must not be visible to field initializer expressions. | 2432 // The receiver must not be visible to field initializer expressions. |
| 2433 receiver->set_invisible(true); | 2433 receiver->set_invisible(true); |
| 2434 GrowableArray<Field*> initialized_fields; | 2434 GrowableArray<Field*> initialized_fields; |
| 2435 ParseInitializedInstanceFields( | 2435 ParseInitializedInstanceFields( |
| 2436 current_class(), receiver, &initialized_fields); | 2436 current_class(), receiver, &initialized_fields); |
| 2437 receiver->set_invisible(false); | 2437 receiver->set_invisible(false); |
| 2438 | 2438 |
| 2439 // If the class of this implicit constructor is a mixin typedef class, | 2439 // If the class of this implicit constructor is a mixin application alias, |
| 2440 // it is a forwarding constructor of the aliased mixin application class. | 2440 // it is a forwarding constructor of the aliased mixin application class. |
| 2441 // If the class of this implicit constructor is a mixin application class, | 2441 // If the class of this implicit constructor is a mixin application class, |
| 2442 // it is a forwarding constructor of the mixin. The forwarding | 2442 // it is a forwarding constructor of the mixin. The forwarding |
| 2443 // constructor initializes the instance fields that have initializer | 2443 // constructor initializes the instance fields that have initializer |
| 2444 // expressions and then calls the respective super constructor with | 2444 // expressions and then calls the respective super constructor with |
| 2445 // the same name and number of parameters. | 2445 // the same name and number of parameters. |
| 2446 ArgumentListNode* forwarding_args = NULL; | 2446 ArgumentListNode* forwarding_args = NULL; |
| 2447 if (current_class().is_mixin_typedef() || | 2447 if (current_class().is_mixin_app_alias() || |
| 2448 current_class().IsMixinApplication()) { | 2448 current_class().IsMixinApplication()) { |
| 2449 // At this point we don't support forwarding constructors | 2449 // At this point we don't support forwarding constructors |
| 2450 // that have optional parameters because we don't know the default | 2450 // that have optional parameters because we don't know the default |
| 2451 // values of the optional parameters. We would have to compile the super | 2451 // values of the optional parameters. We would have to compile the super |
| 2452 // constructor to get the default values. Also, the spec is not clear | 2452 // constructor to get the default values. Also, the spec is not clear |
| 2453 // whether optional parameters are even allowed in this situation. | 2453 // whether optional parameters are even allowed in this situation. |
| 2454 // TODO(hausner): Remove this limitation if the language spec indeed | 2454 // TODO(hausner): Remove this limitation if the language spec indeed |
| 2455 // allows optional parameters. | 2455 // allows optional parameters. |
| 2456 if (func.HasOptionalParameters()) { | 2456 if (func.HasOptionalParameters()) { |
| 2457 ErrorMsg(ctor_pos, | 2457 ErrorMsg(ctor_pos, |
| (...skipping 1435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3893 ErrorMsg(type_pos, | 3893 ErrorMsg(type_pos, |
| 3894 "class '%s' may not extend type parameter '%s'", | 3894 "class '%s' may not extend type parameter '%s'", |
| 3895 class_name.ToCString(), | 3895 class_name.ToCString(), |
| 3896 String::Handle(super_type.UserVisibleName()).ToCString()); | 3896 String::Handle(super_type.UserVisibleName()).ToCString()); |
| 3897 } | 3897 } |
| 3898 // The class finalizer will check whether the super type is malbounded. | 3898 // The class finalizer will check whether the super type is malbounded. |
| 3899 if (CurrentToken() == Token::kWITH) { | 3899 if (CurrentToken() == Token::kWITH) { |
| 3900 super_type = ParseMixins(super_type); | 3900 super_type = ParseMixins(super_type); |
| 3901 } | 3901 } |
| 3902 if (is_mixin_declaration) { | 3902 if (is_mixin_declaration) { |
| 3903 cls.set_is_mixin_typedef(); | 3903 cls.set_is_mixin_app_alias(); |
| 3904 cls.set_is_synthesized_class(); | 3904 cls.set_is_synthesized_class(); |
| 3905 } | 3905 } |
| 3906 } else { | 3906 } else { |
| 3907 // No extends clause: implicitly extend Object, unless Object itself. | 3907 // No extends clause: implicitly extend Object, unless Object itself. |
| 3908 if (!cls.IsObjectClass()) { | 3908 if (!cls.IsObjectClass()) { |
| 3909 super_type = Type::ObjectType(); | 3909 super_type = Type::ObjectType(); |
| 3910 } | 3910 } |
| 3911 } | 3911 } |
| 3912 ASSERT(!super_type.IsNull() || cls.IsObjectClass()); | 3912 ASSERT(!super_type.IsNull() || cls.IsObjectClass()); |
| 3913 cls.set_super_type(super_type); | 3913 cls.set_super_type(super_type); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4050 // which the current one redirects, we ignore the unresolved | 4050 // which the current one redirects, we ignore the unresolved |
| 4051 // reference. We'll catch it later when the constructor gets | 4051 // reference. We'll catch it later when the constructor gets |
| 4052 // compiled. | 4052 // compiled. |
| 4053 ctors.Add(member); | 4053 ctors.Add(member); |
| 4054 member = class_desc->LookupMember(*member->redirect_name); | 4054 member = class_desc->LookupMember(*member->redirect_name); |
| 4055 } | 4055 } |
| 4056 } | 4056 } |
| 4057 } | 4057 } |
| 4058 | 4058 |
| 4059 | 4059 |
| 4060 void Parser::ParseMixinTypedef(const GrowableObjectArray& pending_classes, | 4060 void Parser::ParseMixinAppAlias( |
| 4061 intptr_t metadata_pos) { | 4061 const GrowableObjectArray& pending_classes, |
| 4062 TRACE_PARSER("ParseMixinTypedef"); | 4062 intptr_t metadata_pos) { |
| 4063 TRACE_PARSER("ParseMixinAppAlias"); |
| 4063 const intptr_t classname_pos = TokenPos(); | 4064 const intptr_t classname_pos = TokenPos(); |
| 4064 String& class_name = *ExpectUserDefinedTypeIdentifier("class name expected"); | 4065 String& class_name = *ExpectUserDefinedTypeIdentifier("class name expected"); |
| 4065 if (FLAG_trace_parser) { | 4066 if (FLAG_trace_parser) { |
| 4066 OS::Print("toplevel parsing typedef class '%s'\n", class_name.ToCString()); | 4067 OS::Print("toplevel parsing mixin application alias class '%s'\n", |
| 4068 class_name.ToCString()); |
| 4067 } | 4069 } |
| 4068 const Object& obj = Object::Handle(library_.LookupLocalObject(class_name)); | 4070 const Object& obj = Object::Handle(library_.LookupLocalObject(class_name)); |
| 4069 if (!obj.IsNull()) { | 4071 if (!obj.IsNull()) { |
| 4070 ErrorMsg(classname_pos, "'%s' is already defined", | 4072 ErrorMsg(classname_pos, "'%s' is already defined", |
| 4071 class_name.ToCString()); | 4073 class_name.ToCString()); |
| 4072 } | 4074 } |
| 4073 const Class& mixin_application = | 4075 const Class& mixin_application = |
| 4074 Class::Handle(Class::New(class_name, script_, classname_pos)); | 4076 Class::Handle(Class::New(class_name, script_, classname_pos)); |
| 4075 mixin_application.set_is_mixin_typedef(); | 4077 mixin_application.set_is_mixin_app_alias(); |
| 4076 library_.AddClass(mixin_application); | 4078 library_.AddClass(mixin_application); |
| 4077 set_current_class(mixin_application); | 4079 set_current_class(mixin_application); |
| 4078 ParseTypeParameters(mixin_application); | 4080 ParseTypeParameters(mixin_application); |
| 4079 | 4081 |
| 4080 ExpectToken(Token::kASSIGN); | 4082 ExpectToken(Token::kASSIGN); |
| 4081 | 4083 |
| 4082 if (CurrentToken() == Token::kABSTRACT) { | 4084 if (CurrentToken() == Token::kABSTRACT) { |
| 4083 mixin_application.set_is_abstract(); | 4085 mixin_application.set_is_abstract(); |
| 4084 ConsumeToken(); | 4086 ConsumeToken(); |
| 4085 } | 4087 } |
| 4086 | 4088 |
| 4087 const intptr_t type_pos = TokenPos(); | 4089 const intptr_t type_pos = TokenPos(); |
| 4088 AbstractType& type = | 4090 AbstractType& type = |
| 4089 AbstractType::Handle(ParseType(ClassFinalizer::kResolveTypeParameters)); | 4091 AbstractType::Handle(ParseType(ClassFinalizer::kResolveTypeParameters)); |
| 4090 if (type.IsTypeParameter()) { | 4092 if (type.IsTypeParameter()) { |
| 4091 ErrorMsg(type_pos, | 4093 ErrorMsg(type_pos, |
| 4092 "class '%s' may not extend type parameter '%s'", | 4094 "class '%s' may not extend type parameter '%s'", |
| 4093 class_name.ToCString(), | 4095 class_name.ToCString(), |
| 4094 String::Handle(type.UserVisibleName()).ToCString()); | 4096 String::Handle(type.UserVisibleName()).ToCString()); |
| 4095 } | 4097 } |
| 4096 | 4098 |
| 4097 CheckToken(Token::kWITH, "mixin application 'with Type' expected"); | 4099 CheckToken(Token::kWITH, "mixin application 'with Type' expected"); |
| 4098 type = ParseMixins(type); | 4100 type = ParseMixins(type); |
| 4099 | 4101 |
| 4100 mixin_application.set_super_type(type); | 4102 mixin_application.set_super_type(type); |
| 4101 mixin_application.set_is_synthesized_class(); | 4103 mixin_application.set_is_synthesized_class(); |
| 4102 | 4104 |
| 4103 // This mixin application typedef needs an implicit constructor, but it is | 4105 // This mixin application alias needs an implicit constructor, but it is |
| 4104 // too early to call 'AddImplicitConstructor(mixin_application)' here, | 4106 // too early to call 'AddImplicitConstructor(mixin_application)' here, |
| 4105 // because this class should be lazily compiled. | 4107 // because this class should be lazily compiled. |
| 4106 if (CurrentToken() == Token::kIMPLEMENTS) { | 4108 if (CurrentToken() == Token::kIMPLEMENTS) { |
| 4107 ParseInterfaceList(mixin_application); | 4109 ParseInterfaceList(mixin_application); |
| 4108 } | 4110 } |
| 4109 ExpectSemicolon(); | 4111 ExpectSemicolon(); |
| 4110 pending_classes.Add(mixin_application, Heap::kOld); | 4112 pending_classes.Add(mixin_application, Heap::kOld); |
| 4111 if (metadata_pos >= 0) { | 4113 if (metadata_pos >= 0) { |
| 4112 library_.AddClassMetadata(mixin_application, metadata_pos); | 4114 library_.AddClassMetadata(mixin_application, metadata_pos); |
| 4113 } | 4115 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4130 is_alias_name = true; | 4132 is_alias_name = true; |
| 4131 } | 4133 } |
| 4132 } | 4134 } |
| 4133 SetPosition(saved_pos); | 4135 SetPosition(saved_pos); |
| 4134 return is_alias_name; | 4136 return is_alias_name; |
| 4135 } | 4137 } |
| 4136 | 4138 |
| 4137 | 4139 |
| 4138 // Look ahead to detect if we are seeing ident [ TypeParameters ] "=". | 4140 // Look ahead to detect if we are seeing ident [ TypeParameters ] "=". |
| 4139 // Token position remains unchanged. | 4141 // Token position remains unchanged. |
| 4140 bool Parser::IsMixinTypedef() { | 4142 bool Parser::IsMixinAppAlias() { |
| 4141 if (IsIdentifier() && (LookaheadToken(1) == Token::kASSIGN)) { | 4143 if (IsIdentifier() && (LookaheadToken(1) == Token::kASSIGN)) { |
| 4142 return true; | 4144 return true; |
| 4143 } | 4145 } |
| 4144 const intptr_t saved_pos = TokenPos(); | 4146 const intptr_t saved_pos = TokenPos(); |
| 4145 bool is_mixin_def = false; | 4147 bool is_mixin_def = false; |
| 4146 if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) { | 4148 if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) { |
| 4147 ConsumeToken(); | 4149 ConsumeToken(); |
| 4148 if (TryParseTypeParameters() && (CurrentToken() == Token::kASSIGN)) { | 4150 if (TryParseTypeParameters() && (CurrentToken() == Token::kASSIGN)) { |
| 4149 is_mixin_def = true; | 4151 is_mixin_def = true; |
| 4150 } | 4152 } |
| 4151 } | 4153 } |
| 4152 SetPosition(saved_pos); | 4154 SetPosition(saved_pos); |
| 4153 return is_mixin_def; | 4155 return is_mixin_def; |
| 4154 } | 4156 } |
| 4155 | 4157 |
| 4156 | 4158 |
| 4157 void Parser::ParseTypedef(const GrowableObjectArray& pending_classes, | 4159 void Parser::ParseTypedef(const GrowableObjectArray& pending_classes, |
| 4158 intptr_t metadata_pos) { | 4160 intptr_t metadata_pos) { |
| 4159 TRACE_PARSER("ParseTypedef"); | 4161 TRACE_PARSER("ParseTypedef"); |
| 4160 ExpectToken(Token::kTYPEDEF); | 4162 ExpectToken(Token::kTYPEDEF); |
| 4161 | 4163 |
| 4162 if (IsMixinTypedef()) { | 4164 if (IsMixinAppAlias()) { |
| 4163 if (FLAG_warn_mixin_typedef) { | 4165 if (FLAG_warn_mixin_typedef) { |
| 4164 Warning("deprecated mixin typedef"); | 4166 Warning("deprecated mixin application typedef"); |
| 4165 } | 4167 } |
| 4166 ParseMixinTypedef(pending_classes, metadata_pos); | 4168 ParseMixinAppAlias(pending_classes, metadata_pos); |
| 4167 return; | 4169 return; |
| 4168 } | 4170 } |
| 4169 | 4171 |
| 4170 // Parse the result type of the function type. | 4172 // Parse the result type of the function type. |
| 4171 AbstractType& result_type = Type::Handle(Type::DynamicType()); | 4173 AbstractType& result_type = Type::Handle(Type::DynamicType()); |
| 4172 if (CurrentToken() == Token::kVOID) { | 4174 if (CurrentToken() == Token::kVOID) { |
| 4173 ConsumeToken(); | 4175 ConsumeToken(); |
| 4174 result_type = Type::VoidType(); | 4176 result_type = Type::VoidType(); |
| 4175 } else if (!IsFunctionTypeAliasName()) { | 4177 } else if (!IsFunctionTypeAliasName()) { |
| 4176 // Type annotations in typedef are never ignored, even in unchecked mode. | 4178 // Type annotations in typedef are never ignored, even in production mode. |
| 4177 // Wait until we have an owner class before resolving the result type. | 4179 // Wait until we have an owner class before resolving the result type. |
| 4178 result_type = ParseType(ClassFinalizer::kDoNotResolve); | 4180 result_type = ParseType(ClassFinalizer::kDoNotResolve); |
| 4179 } | 4181 } |
| 4180 | 4182 |
| 4181 const intptr_t alias_name_pos = TokenPos(); | 4183 const intptr_t alias_name_pos = TokenPos(); |
| 4182 const String* alias_name = | 4184 const String* alias_name = |
| 4183 ExpectUserDefinedTypeIdentifier("function alias name expected"); | 4185 ExpectUserDefinedTypeIdentifier("function alias name expected"); |
| 4184 | 4186 |
| 4185 // Lookup alias name and report an error if it is already defined in | 4187 // Lookup alias name and report an error if it is already defined in |
| 4186 // the library scope. | 4188 // the library scope. |
| (...skipping 6602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10789 void Parser::SkipQualIdent() { | 10791 void Parser::SkipQualIdent() { |
| 10790 ASSERT(IsIdentifier()); | 10792 ASSERT(IsIdentifier()); |
| 10791 ConsumeToken(); | 10793 ConsumeToken(); |
| 10792 if (CurrentToken() == Token::kPERIOD) { | 10794 if (CurrentToken() == Token::kPERIOD) { |
| 10793 ConsumeToken(); // Consume the kPERIOD token. | 10795 ConsumeToken(); // Consume the kPERIOD token. |
| 10794 ExpectIdentifier("identifier expected after '.'"); | 10796 ExpectIdentifier("identifier expected after '.'"); |
| 10795 } | 10797 } |
| 10796 } | 10798 } |
| 10797 | 10799 |
| 10798 } // namespace dart | 10800 } // namespace dart |
| OLD | NEW |