| 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 "vm/bigint_operations.h" | 8 #include "vm/bigint_operations.h" |
| 9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "vm/stack_frame.h" | 23 #include "vm/stack_frame.h" |
| 24 #include "vm/symbols.h" | 24 #include "vm/symbols.h" |
| 25 | 25 |
| 26 namespace dart { | 26 namespace dart { |
| 27 | 27 |
| 28 DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements."); | 28 DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements."); |
| 29 DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks."); | 29 DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks."); |
| 30 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); | 30 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); |
| 31 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); | 31 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); |
| 32 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); | 32 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); |
| 33 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef"); |
| 33 DECLARE_FLAG(bool, error_on_bad_type); | 34 DECLARE_FLAG(bool, error_on_bad_type); |
| 34 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); | 35 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| 35 | 36 |
| 36 static void CheckedModeHandler(bool value) { | 37 static void CheckedModeHandler(bool value) { |
| 37 FLAG_enable_asserts = value; | 38 FLAG_enable_asserts = value; |
| 38 FLAG_enable_type_checks = value; | 39 FLAG_enable_type_checks = value; |
| 39 } | 40 } |
| 40 | 41 |
| 41 // --enable-checked-mode and --checked both enable checked mode which is | 42 // --enable-checked-mode and --checked both enable checked mode which is |
| 42 // equivalent to setting --enable-asserts and --enable-type-checks. | 43 // equivalent to setting --enable-asserts and --enable-type-checks. |
| (...skipping 3729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3772 "original type parameter '%s'", | 3773 "original type parameter '%s'", |
| 3773 new_name.ToCString(), | 3774 new_name.ToCString(), |
| 3774 class_name.ToCString(), | 3775 class_name.ToCString(), |
| 3775 orig_name.ToCString()); | 3776 orig_name.ToCString()); |
| 3776 } | 3777 } |
| 3777 // We do not check that the bounds are repeated. We use the original ones. | 3778 // We do not check that the bounds are repeated. We use the original ones. |
| 3778 // TODO(regis): Should we check? | 3779 // TODO(regis): Should we check? |
| 3779 } | 3780 } |
| 3780 cls.set_type_parameters(orig_type_parameters); | 3781 cls.set_type_parameters(orig_type_parameters); |
| 3781 } | 3782 } |
| 3783 |
| 3784 if (is_abstract) { |
| 3785 cls.set_is_abstract(); |
| 3786 } |
| 3787 if (metadata_pos >= 0) { |
| 3788 library_.AddClassMetadata(cls, metadata_pos); |
| 3789 } |
| 3790 |
| 3791 const bool is_mixin_declaration = (CurrentToken() == Token::kASSIGN); |
| 3792 if (is_mixin_declaration && is_patch) { |
| 3793 ErrorMsg(classname_pos, |
| 3794 "mixin application '%s' may not be a patch class", |
| 3795 class_name.ToCString()); |
| 3796 } |
| 3797 |
| 3782 AbstractType& super_type = Type::Handle(); | 3798 AbstractType& super_type = Type::Handle(); |
| 3783 if (CurrentToken() == Token::kEXTENDS) { | 3799 if ((CurrentToken() == Token::kEXTENDS) || is_mixin_declaration) { |
| 3784 ConsumeToken(); | 3800 ConsumeToken(); // extends or = |
| 3785 const intptr_t type_pos = TokenPos(); | 3801 const intptr_t type_pos = TokenPos(); |
| 3786 super_type = ParseType(ClassFinalizer::kResolveTypeParameters); | 3802 super_type = ParseType(ClassFinalizer::kResolveTypeParameters); |
| 3787 if (super_type.IsDynamicType()) { | 3803 if (super_type.IsDynamicType()) { |
| 3788 // The string 'dynamic' is not resolved yet at this point, but a malformed | 3804 // The string 'dynamic' is not resolved yet at this point, but a malformed |
| 3789 // type mapped to dynamic can be encountered here. | 3805 // type mapped to dynamic can be encountered here. |
| 3790 ErrorMsg(type_pos, | 3806 ErrorMsg(type_pos, |
| 3791 "class '%s' may not extend a malformed type", | 3807 "class '%s' may not extend a malformed type", |
| 3792 class_name.ToCString()); | 3808 class_name.ToCString()); |
| 3793 } | 3809 } |
| 3794 if (super_type.IsTypeParameter()) { | 3810 if (super_type.IsTypeParameter()) { |
| 3795 ErrorMsg(type_pos, | 3811 ErrorMsg(type_pos, |
| 3796 "class '%s' may not extend type parameter '%s'", | 3812 "class '%s' may not extend type parameter '%s'", |
| 3797 class_name.ToCString(), | 3813 class_name.ToCString(), |
| 3798 String::Handle(super_type.UserVisibleName()).ToCString()); | 3814 String::Handle(super_type.UserVisibleName()).ToCString()); |
| 3799 } | 3815 } |
| 3800 if (CurrentToken() == Token::kWITH) { | 3816 if (CurrentToken() == Token::kWITH) { |
| 3801 super_type = ParseMixins(pending_classes, super_type); | 3817 super_type = ParseMixins(pending_classes, super_type); |
| 3802 } | 3818 } |
| 3819 if (is_mixin_declaration) { |
| 3820 cls.set_is_mixin_typedef(); |
| 3821 cls.set_is_synthesized_class(); |
| 3822 } |
| 3803 } else { | 3823 } else { |
| 3804 // No extends clause: implicitly extend Object, unless Object itself. | 3824 // No extends clause: implicitly extend Object, unless Object itself. |
| 3805 if (!cls.IsObjectClass()) { | 3825 if (!cls.IsObjectClass()) { |
| 3806 super_type = Type::ObjectType(); | 3826 super_type = Type::ObjectType(); |
| 3807 } | 3827 } |
| 3808 } | 3828 } |
| 3809 ASSERT(!super_type.IsNull() || cls.IsObjectClass()); | 3829 ASSERT(!super_type.IsNull() || cls.IsObjectClass()); |
| 3810 cls.set_super_type(super_type); | 3830 cls.set_super_type(super_type); |
| 3811 | 3831 |
| 3812 if (CurrentToken() == Token::kIMPLEMENTS) { | 3832 if (CurrentToken() == Token::kIMPLEMENTS) { |
| 3813 ParseInterfaceList(cls); | 3833 ParseInterfaceList(cls); |
| 3814 } | 3834 } |
| 3815 | 3835 |
| 3816 if (is_abstract) { | |
| 3817 cls.set_is_abstract(); | |
| 3818 } | |
| 3819 if (is_patch) { | 3836 if (is_patch) { |
| 3820 // Apply the changes to the patched class looked up above. | 3837 // Apply the changes to the patched class looked up above. |
| 3821 ASSERT(obj.raw() == library_.LookupLocalObject(class_name)); | 3838 ASSERT(obj.raw() == library_.LookupLocalObject(class_name)); |
| 3822 // The patched class must not be finalized yet. | 3839 // The patched class must not be finalized yet. |
| 3823 const Class& orig_class = Class::Cast(obj); | 3840 const Class& orig_class = Class::Cast(obj); |
| 3824 ASSERT(!orig_class.is_finalized()); | 3841 ASSERT(!orig_class.is_finalized()); |
| 3825 orig_class.set_patch_class(cls); | 3842 orig_class.set_patch_class(cls); |
| 3826 cls.set_is_patch(); | 3843 cls.set_is_patch(); |
| 3827 } | 3844 } |
| 3828 pending_classes.Add(cls, Heap::kOld); | 3845 pending_classes.Add(cls, Heap::kOld); |
| 3829 if (metadata_pos >= 0) { | 3846 |
| 3830 library_.AddClassMetadata(cls, metadata_pos); | 3847 if (is_mixin_declaration) { |
| 3848 ExpectSemicolon(); |
| 3849 } else { |
| 3850 if (CurrentToken() != Token::kLBRACE) { |
| 3851 ErrorMsg("{ expected"); |
| 3852 } |
| 3853 SkipBlock(); |
| 3854 ExpectToken(Token::kRBRACE); |
| 3831 } | 3855 } |
| 3832 | |
| 3833 if (CurrentToken() != Token::kLBRACE) { | |
| 3834 ErrorMsg("{ expected"); | |
| 3835 } | |
| 3836 SkipBlock(); | |
| 3837 ExpectToken(Token::kRBRACE); | |
| 3838 } | 3856 } |
| 3839 | 3857 |
| 3840 | 3858 |
| 3841 void Parser::ParseClassDefinition(const Class& cls) { | 3859 void Parser::ParseClassDefinition(const Class& cls) { |
| 3842 TRACE_PARSER("ParseClassDefinition"); | 3860 TRACE_PARSER("ParseClassDefinition"); |
| 3843 set_current_class(cls); | 3861 set_current_class(cls); |
| 3844 is_top_level_ = true; | 3862 is_top_level_ = true; |
| 3845 String& class_name = String::Handle(cls.Name()); | 3863 String& class_name = String::Handle(cls.Name()); |
| 3846 const intptr_t class_pos = TokenPos(); | 3864 const intptr_t class_pos = TokenPos(); |
| 3847 ClassDesc members(cls, class_name, false, class_pos); | 3865 ClassDesc members(cls, class_name, false, class_pos); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4003 "class '%s' may not extend type parameter '%s'", | 4021 "class '%s' may not extend type parameter '%s'", |
| 4004 class_name.ToCString(), | 4022 class_name.ToCString(), |
| 4005 String::Handle(type.UserVisibleName()).ToCString()); | 4023 String::Handle(type.UserVisibleName()).ToCString()); |
| 4006 } | 4024 } |
| 4007 | 4025 |
| 4008 if (CurrentToken() != Token::kWITH) { | 4026 if (CurrentToken() != Token::kWITH) { |
| 4009 ErrorMsg("mixin application 'with Type' expected"); | 4027 ErrorMsg("mixin application 'with Type' expected"); |
| 4010 } | 4028 } |
| 4011 type = ParseMixins(pending_classes, type); | 4029 type = ParseMixins(pending_classes, type); |
| 4012 | 4030 |
| 4013 // TODO(12773): Treat the mixin application as an alias, not as a base | |
| 4014 // class whose super class is the mixin application! This is difficult because | |
| 4015 // of issues involving subsitution of type parameters | |
| 4016 mixin_application.set_super_type(type); | 4031 mixin_application.set_super_type(type); |
| 4017 mixin_application.set_is_synthesized_class(); | 4032 mixin_application.set_is_synthesized_class(); |
| 4018 | 4033 |
| 4019 // This mixin application typedef needs an implicit constructor, but it is | 4034 // This mixin application typedef needs an implicit constructor, but it is |
| 4020 // too early to call 'AddImplicitConstructor(mixin_application)' here, | 4035 // too early to call 'AddImplicitConstructor(mixin_application)' here, |
| 4021 // because this class should be lazily compiled. | 4036 // because this class should be lazily compiled. |
| 4022 if (CurrentToken() == Token::kIMPLEMENTS) { | 4037 if (CurrentToken() == Token::kIMPLEMENTS) { |
| 4023 // At this point, the mixin_application alias already has an interface, but | |
| 4024 // ParseInterfaceList will add to the list and not lose the one already | |
| 4025 // there. | |
| 4026 ParseInterfaceList(mixin_application); | 4038 ParseInterfaceList(mixin_application); |
| 4027 } | 4039 } |
| 4028 ExpectSemicolon(); | 4040 ExpectSemicolon(); |
| 4029 pending_classes.Add(mixin_application, Heap::kOld); | 4041 pending_classes.Add(mixin_application, Heap::kOld); |
| 4030 if (metadata_pos >= 0) { | 4042 if (metadata_pos >= 0) { |
| 4031 library_.AddClassMetadata(mixin_application, metadata_pos); | 4043 library_.AddClassMetadata(mixin_application, metadata_pos); |
| 4032 } | 4044 } |
| 4033 } | 4045 } |
| 4034 | 4046 |
| 4035 | 4047 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4072 return is_mixin_def; | 4084 return is_mixin_def; |
| 4073 } | 4085 } |
| 4074 | 4086 |
| 4075 | 4087 |
| 4076 void Parser::ParseTypedef(const GrowableObjectArray& pending_classes, | 4088 void Parser::ParseTypedef(const GrowableObjectArray& pending_classes, |
| 4077 intptr_t metadata_pos) { | 4089 intptr_t metadata_pos) { |
| 4078 TRACE_PARSER("ParseTypedef"); | 4090 TRACE_PARSER("ParseTypedef"); |
| 4079 ExpectToken(Token::kTYPEDEF); | 4091 ExpectToken(Token::kTYPEDEF); |
| 4080 | 4092 |
| 4081 if (IsMixinTypedef()) { | 4093 if (IsMixinTypedef()) { |
| 4094 if (FLAG_warn_mixin_typedef) { |
| 4095 Warning("deprecated mixin typedef"); |
| 4096 } |
| 4082 ParseMixinTypedef(pending_classes, metadata_pos); | 4097 ParseMixinTypedef(pending_classes, metadata_pos); |
| 4083 return; | 4098 return; |
| 4084 } | 4099 } |
| 4085 | 4100 |
| 4086 // Parse the result type of the function type. | 4101 // Parse the result type of the function type. |
| 4087 AbstractType& result_type = Type::Handle(Type::DynamicType()); | 4102 AbstractType& result_type = Type::Handle(Type::DynamicType()); |
| 4088 if (CurrentToken() == Token::kVOID) { | 4103 if (CurrentToken() == Token::kVOID) { |
| 4089 ConsumeToken(); | 4104 ConsumeToken(); |
| 4090 result_type = Type::VoidType(); | 4105 result_type = Type::VoidType(); |
| 4091 } else if (!IsFunctionTypeAliasName()) { | 4106 } else if (!IsFunctionTypeAliasName()) { |
| (...skipping 6519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10611 void Parser::SkipQualIdent() { | 10626 void Parser::SkipQualIdent() { |
| 10612 ASSERT(IsIdentifier()); | 10627 ASSERT(IsIdentifier()); |
| 10613 ConsumeToken(); | 10628 ConsumeToken(); |
| 10614 if (CurrentToken() == Token::kPERIOD) { | 10629 if (CurrentToken() == Token::kPERIOD) { |
| 10615 ConsumeToken(); // Consume the kPERIOD token. | 10630 ConsumeToken(); // Consume the kPERIOD token. |
| 10616 ExpectIdentifier("identifier expected after '.'"); | 10631 ExpectIdentifier("identifier expected after '.'"); |
| 10617 } | 10632 } |
| 10618 } | 10633 } |
| 10619 | 10634 |
| 10620 } // namespace dart | 10635 } // namespace dart |
| OLD | NEW |