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

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

Issue 12837007: Revise duplicate interface check (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 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/parser.h ('k') | tests/language/class_cycle_test.dart » ('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 "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/class_finalizer.h" 9 #include "vm/class_finalizer.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 3248 matching lines...) Expand 10 before | Expand all | Expand 10 after
3259 super_type = ParseMixins(super_type); 3259 super_type = ParseMixins(super_type);
3260 } 3260 }
3261 } else { 3261 } else {
3262 // No extends clause: implicitly extend Object. 3262 // No extends clause: implicitly extend Object.
3263 super_type = Type::ObjectType(); 3263 super_type = Type::ObjectType();
3264 } 3264 }
3265 ASSERT(!super_type.IsNull()); 3265 ASSERT(!super_type.IsNull());
3266 cls.set_super_type(super_type); 3266 cls.set_super_type(super_type);
3267 3267
3268 if (CurrentToken() == Token::kIMPLEMENTS) { 3268 if (CurrentToken() == Token::kIMPLEMENTS) {
3269 Array& interfaces = Array::Handle(); 3269 ParseInterfaceList(cls);
3270 const intptr_t interfaces_pos = TokenPos();
3271 interfaces = ParseInterfaceList(super_type);
3272 AddInterfaces(interfaces_pos, cls, interfaces);
3273 } 3270 }
3274 3271
3275 ExpectToken(Token::kLBRACE); 3272 ExpectToken(Token::kLBRACE);
3276 ClassDesc members(cls, class_name, false, class_pos); 3273 ClassDesc members(cls, class_name, false, class_pos);
3277 while (CurrentToken() != Token::kRBRACE) { 3274 while (CurrentToken() != Token::kRBRACE) {
3278 SkipMetadata(); 3275 SkipMetadata();
3279 ParseClassMemberDefinition(&members); 3276 ParseClassMemberDefinition(&members);
3280 } 3277 }
3281 ExpectToken(Token::kRBRACE); 3278 ExpectToken(Token::kRBRACE);
3282 3279
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
3435 ErrorMsg("mixin application 'with Type' expected"); 3432 ErrorMsg("mixin application 'with Type' expected");
3436 } 3433 }
3437 type = ParseMixins(type); 3434 type = ParseMixins(type);
3438 3435
3439 // TODO(hausner): treat the mixin application as an alias, not as a base 3436 // TODO(hausner): treat the mixin application as an alias, not as a base
3440 // class whose super class is the mixin application! 3437 // class whose super class is the mixin application!
3441 mixin_application.set_super_type(type); 3438 mixin_application.set_super_type(type);
3442 3439
3443 AddImplicitConstructor(mixin_application); 3440 AddImplicitConstructor(mixin_application);
3444 if (CurrentToken() == Token::kIMPLEMENTS) { 3441 if (CurrentToken() == Token::kIMPLEMENTS) {
3445 Array& interfaces = Array::Handle(); 3442 ParseInterfaceList(mixin_application);
3446 const intptr_t interfaces_pos = TokenPos();
3447 interfaces = ParseInterfaceList(type);
3448 AddInterfaces(interfaces_pos, mixin_application, interfaces);
3449 } 3443 }
3450 ExpectSemicolon(); 3444 ExpectSemicolon();
3451 pending_classes.Add(mixin_application, Heap::kOld); 3445 pending_classes.Add(mixin_application, Heap::kOld);
3452 } 3446 }
3453 3447
3454 3448
3455 // Look ahead to detect if we are seeing ident [ TypeParameters ] "(". 3449 // Look ahead to detect if we are seeing ident [ TypeParameters ] "(".
3456 // We need this lookahead to distinguish between the optional return type 3450 // We need this lookahead to distinguish between the optional return type
3457 // and the alias name of a function type alias. 3451 // and the alias name of a function type alias.
3458 // Token position remains unchanged. 3452 // Token position remains unchanged.
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
3772 ErrorMsg("right angle bracket expected"); 3766 ErrorMsg("right angle bracket expected");
3773 } 3767 }
3774 if (finalization != ClassFinalizer::kIgnore) { 3768 if (finalization != ClassFinalizer::kIgnore) {
3775 return NewTypeArguments(types); 3769 return NewTypeArguments(types);
3776 } 3770 }
3777 } 3771 }
3778 return TypeArguments::null(); 3772 return TypeArguments::null();
3779 } 3773 }
3780 3774
3781 3775
3782 // Parse and return an array of interface types. 3776 // Parse interface list and add to class cls.
3783 RawArray* Parser::ParseInterfaceList(const AbstractType& super_type) { 3777 void Parser::ParseInterfaceList(const Class& cls) {
3784 TRACE_PARSER("ParseInterfaceList"); 3778 TRACE_PARSER("ParseInterfaceList");
3785 ASSERT(CurrentToken() == Token::kIMPLEMENTS); 3779 ASSERT(CurrentToken() == Token::kIMPLEMENTS);
3786 const GrowableObjectArray& interfaces = 3780 const GrowableObjectArray& all_interfaces =
3787 GrowableObjectArray::Handle(GrowableObjectArray::New()); 3781 GrowableObjectArray::Handle(GrowableObjectArray::New());
3788 String& interface_name = String::Handle();
3789 AbstractType& interface = AbstractType::Handle(); 3782 AbstractType& interface = AbstractType::Handle();
3790 String& other_name = String::Handle(); 3783 // First get all the interfaces already implemented by class.
3791 AbstractType& other_interface = AbstractType::Handle(); 3784 Array& cls_interfaces = Array::Handle(cls.interfaces());
3792 const String& super_type_name = String::Handle(super_type.Name()); 3785 for (intptr_t i = 0; i < cls_interfaces.Length(); i++) {
3786 interface ^= cls_interfaces.At(i);
3787 all_interfaces.Add(interface);
3788 }
3789 // Now parse and add the new interfaces.
3793 do { 3790 do {
3794 ConsumeToken(); 3791 ConsumeToken();
3795 intptr_t interface_pos = TokenPos(); 3792 intptr_t interface_pos = TokenPos();
3796 interface = ParseType(ClassFinalizer::kTryResolve); 3793 interface = ParseType(ClassFinalizer::kTryResolve);
3797 interface_name = interface.UserVisibleName(); 3794 if (interface.IsTypeParameter()) {
3798 if (interface_name.Equals(super_type_name)) { 3795 ErrorMsg(interface_pos,
3799 // TODO(hausner): I think this check is not necessary. There is 3796 "type parameter '%s' may not be used in interface list",
3800 // no such restriction. If the check is removed, the 'super_type' 3797 String::Handle(interface.UserVisibleName()).ToCString());
3801 // parameter to this function can be eliminated.
3802 ErrorMsg(interface_pos, "class may not extend and implement '%s'",
3803 interface_name.ToCString());
3804 } 3798 }
3805 for (int i = 0; i < interfaces.Length(); i++) { 3799 all_interfaces.Add(interface);
3806 other_interface ^= interfaces.At(i);
3807 other_name = other_interface.Name();
3808 if (interface_name.Equals(other_name)) {
3809 ErrorMsg(interface_pos, "duplicate interface '%s'",
3810 interface_name.ToCString());
3811 }
3812 }
3813 interfaces.Add(interface);
3814 } while (CurrentToken() == Token::kCOMMA); 3800 } while (CurrentToken() == Token::kCOMMA);
3815 return Array::MakeArray(interfaces); 3801 cls_interfaces = Array::MakeArray(all_interfaces);
3802 cls.set_interfaces(cls_interfaces);
3816 } 3803 }
3817 3804
3818 3805
3819 RawAbstractType* Parser::ParseMixins(const AbstractType& super_type) { 3806 RawAbstractType* Parser::ParseMixins(const AbstractType& super_type) {
3820 TRACE_PARSER("ParseMixins"); 3807 TRACE_PARSER("ParseMixins");
3821 ASSERT(CurrentToken() == Token::kWITH); 3808 ASSERT(CurrentToken() == Token::kWITH);
3822 3809
3823 const GrowableObjectArray& mixin_apps = 3810 const GrowableObjectArray& mixin_apps =
3824 GrowableObjectArray::Handle(GrowableObjectArray::New()); 3811 GrowableObjectArray::Handle(GrowableObjectArray::New());
3825 AbstractType& mixin_type = AbstractType::Handle(); 3812 AbstractType& mixin_type = AbstractType::Handle();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3873 mixin_type_arguments, 3860 mixin_type_arguments,
3874 mixin_pos); 3861 mixin_pos);
3875 mixin_super_type = mixin_application_type.raw(); 3862 mixin_super_type = mixin_application_type.raw();
3876 mixin_apps.Add(mixin_application_type); 3863 mixin_apps.Add(mixin_application_type);
3877 } while (CurrentToken() == Token::kCOMMA); 3864 } while (CurrentToken() == Token::kCOMMA);
3878 return MixinAppType::New(super_type, 3865 return MixinAppType::New(super_type,
3879 Array::Handle(Array::MakeArray(mixin_apps))); 3866 Array::Handle(Array::MakeArray(mixin_apps)));
3880 } 3867 }
3881 3868
3882 3869
3883 // Add 'interface' to 'interface_list' if it is not already in the list.
3884 // An error is reported if the interface conflicts with an interface already in
3885 // the list with the same class and same type arguments.
3886 void Parser::AddInterfaceIfUnique(intptr_t interfaces_pos,
3887 const GrowableObjectArray& interface_list,
3888 const AbstractType& interface) {
3889 String& interface_name = String::Handle(interface.Name());
3890 String& existing_interface_name = String::Handle();
3891 AbstractType& other_interface = AbstractType::Handle();
3892 for (intptr_t i = 0; i < interface_list.Length(); i++) {
3893 other_interface ^= interface_list.At(i);
3894 existing_interface_name = other_interface.Name();
3895 if (interface_name.Equals(existing_interface_name)) {
3896 return;
3897 }
3898 }
3899 interface_list.Add(interface);
3900 }
3901
3902
3903 void Parser::AddInterfaces(intptr_t interfaces_pos,
3904 const Class& cls,
3905 const Array& interfaces) {
3906 const GrowableObjectArray& all_interfaces =
3907 GrowableObjectArray::Handle(GrowableObjectArray::New());
3908 AbstractType& interface = AbstractType::Handle();
3909 // First get all the interfaces already implemented by class.
3910 Array& cls_interfaces = Array::Handle(cls.interfaces());
3911 for (intptr_t i = 0; i < cls_interfaces.Length(); i++) {
3912 interface ^= cls_interfaces.At(i);
3913 all_interfaces.Add(interface);
3914 }
3915 // Now add the new interfaces.
3916 for (intptr_t i = 0; i < interfaces.Length(); i++) {
3917 AbstractType& interface = AbstractType::ZoneHandle();
3918 interface ^= interfaces.At(i);
3919 if (interface.IsTypeParameter()) {
3920 ErrorMsg(interfaces_pos,
3921 "class '%s' may not implement type parameter '%s'",
3922 String::Handle(cls.Name()).ToCString(),
3923 String::Handle(interface.UserVisibleName()).ToCString());
3924 }
3925 AddInterfaceIfUnique(interfaces_pos, all_interfaces, interface);
3926 }
3927 cls_interfaces = Array::MakeArray(all_interfaces);
3928 cls.set_interfaces(cls_interfaces);
3929 }
3930
3931
3932 void Parser::ParseTopLevelVariable(TopLevel* top_level) { 3870 void Parser::ParseTopLevelVariable(TopLevel* top_level) {
3933 TRACE_PARSER("ParseTopLevelVariable"); 3871 TRACE_PARSER("ParseTopLevelVariable");
3934 const bool is_const = (CurrentToken() == Token::kCONST); 3872 const bool is_const = (CurrentToken() == Token::kCONST);
3935 // Const fields are implicitly final. 3873 // Const fields are implicitly final.
3936 const bool is_final = is_const || (CurrentToken() == Token::kFINAL); 3874 const bool is_final = is_const || (CurrentToken() == Token::kFINAL);
3937 const bool is_static = true; 3875 const bool is_static = true;
3938 const AbstractType& type = 3876 const AbstractType& type =
3939 AbstractType::ZoneHandle(ParseConstFinalVarOrType( 3877 AbstractType::ZoneHandle(ParseConstFinalVarOrType(
3940 FLAG_enable_type_checks ? ClassFinalizer::kTryResolve : 3878 FLAG_enable_type_checks ? ClassFinalizer::kTryResolve :
3941 ClassFinalizer::kIgnore)); 3879 ClassFinalizer::kIgnore));
(...skipping 6097 matching lines...) Expand 10 before | Expand all | Expand 10 after
10039 void Parser::SkipQualIdent() { 9977 void Parser::SkipQualIdent() {
10040 ASSERT(IsIdentifier()); 9978 ASSERT(IsIdentifier());
10041 ConsumeToken(); 9979 ConsumeToken();
10042 if (CurrentToken() == Token::kPERIOD) { 9980 if (CurrentToken() == Token::kPERIOD) {
10043 ConsumeToken(); // Consume the kPERIOD token. 9981 ConsumeToken(); // Consume the kPERIOD token.
10044 ExpectIdentifier("identifier expected after '.'"); 9982 ExpectIdentifier("identifier expected after '.'");
10045 } 9983 }
10046 } 9984 }
10047 9985
10048 } // namespace dart 9986 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/class_cycle_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698