| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
| 8 #include "vm/class_finalizer.h" | 8 #include "vm/class_finalizer.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/compiler_stats.h" | 10 #include "vm/compiler_stats.h" |
| 11 #include "vm/dart_api_impl.h" | 11 #include "vm/dart_api_impl.h" |
| 12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
| 13 #include "vm/flags.h" | 13 #include "vm/flags.h" |
| 14 #include "vm/growable_array.h" | 14 #include "vm/growable_array.h" |
| 15 #include "vm/longjump.h" | 15 #include "vm/longjump.h" |
| 16 #include "vm/native_entry.h" | 16 #include "vm/native_entry.h" |
| 17 #include "vm/object.h" | 17 #include "vm/object.h" |
| 18 #include "vm/object_store.h" | 18 #include "vm/object_store.h" |
| 19 #include "vm/resolver.h" | 19 #include "vm/resolver.h" |
| 20 #include "vm/scopes.h" | 20 #include "vm/scopes.h" |
| 21 | 21 |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements."); | 24 DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements."); |
| 25 DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks."); | 25 DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks."); |
| 26 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); | 26 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); |
| 27 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); | 27 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); |
| 28 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); | 28 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); |
| 29 DECLARE_FLAG(bool, expose_core_impl); |
| 29 | 30 |
| 30 // All references to Dart names are listed here. | 31 // All references to Dart names are listed here. |
| 31 static const char* kAssertionErrorName = "AssertionError"; | 32 static const char* kAssertionErrorName = "AssertionError"; |
| 32 static const char* kFallThroughErrorName = "FallThroughError"; | 33 static const char* kFallThroughErrorName = "FallThroughError"; |
| 33 static const char* kThrowNewName = "_throwNew"; | 34 static const char* kThrowNewName = "_throwNew"; |
| 34 static const char* kGrowableObjectArrayFromArrayName = | 35 static const char* kGrowableObjectArrayFromArrayName = |
| 35 "GrowableObjectArray._usingArray"; | 36 "GrowableObjectArray._usingArray"; |
| 36 static const char* kGrowableObjectArrayName = "GrowableObjectArray"; | 37 static const char* kGrowableObjectArrayName = "GrowableObjectArray"; |
| 37 static const char* kMutableMapName = "MutableMap"; | 38 static const char* kLiteralMapFactoryName = "_LiteralMapFactory"; |
| 38 static const char* kMutableMapFromLiteralName = "fromLiteral"; | 39 static const char* kLiteralMapFactoryFromLiteralName = "Map.fromLiteral"; |
| 39 static const char* kImmutableMapName = "ImmutableMap"; | 40 static const char* kImmutableMapName = "ImmutableMap"; |
| 40 static const char* kImmutableMapConstructorName = "ImmutableMap."; | 41 static const char* kImmutableMapConstructorName = "ImmutableMap."; |
| 41 static const char* kStringClassName = "StringBase"; | 42 static const char* kStringClassName = "StringBase"; |
| 42 static const char* kInterpolateName = "_interpolate"; | 43 static const char* kInterpolateName = "_interpolate"; |
| 43 static const char* kThisName = "this"; | 44 static const char* kThisName = "this"; |
| 44 static const char* kPhaseParameterName = ":phase"; | 45 static const char* kPhaseParameterName = ":phase"; |
| 45 static const char* kGetIteratorName = "iterator"; | 46 static const char* kGetIteratorName = "iterator"; |
| 46 | 47 |
| 47 #if defined(DEBUG) | 48 #if defined(DEBUG) |
| 48 | 49 |
| (...skipping 4370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4419 } | 4420 } |
| 4420 | 4421 |
| 4421 | 4422 |
| 4422 // Lookup class in the corelib implementation which contains various VM | 4423 // Lookup class in the corelib implementation which contains various VM |
| 4423 // helper methods and classes. | 4424 // helper methods and classes. |
| 4424 static RawClass* LookupImplClass(const String& class_name) { | 4425 static RawClass* LookupImplClass(const String& class_name) { |
| 4425 return Library::Handle(Library::CoreImplLibrary()).LookupClass(class_name); | 4426 return Library::Handle(Library::CoreImplLibrary()).LookupClass(class_name); |
| 4426 } | 4427 } |
| 4427 | 4428 |
| 4428 | 4429 |
| 4430 // Lookup class in the corelib which also contains various VM |
| 4431 // helper methods and classes. Allow look up of private classes. |
| 4432 static RawClass* LookupCoreClass(const String& class_name) { |
| 4433 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 4434 String& name = String::Handle(class_name.raw()); |
| 4435 if ((class_name.CharAt(0) == Scanner::kPrivateIdentifierStart) && |
| 4436 !FLAG_expose_core_impl) { |
| 4437 // Private identifiers are mangled on a per script basis. |
| 4438 name = String::Concat(name, String::Handle(core_lib.private_key())); |
| 4439 name = String::NewSymbol(name); |
| 4440 } |
| 4441 return core_lib.LookupClass(name); |
| 4442 } |
| 4443 |
| 4444 |
| 4429 RawClass* Parser::LookupClass(const String& class_name) { | 4445 RawClass* Parser::LookupClass(const String& class_name) { |
| 4430 return library_.LookupClass(class_name); | 4446 return library_.LookupClass(class_name); |
| 4431 } | 4447 } |
| 4432 | 4448 |
| 4433 | 4449 |
| 4434 // Calling VM-internal helpers, uses implementation core library. | 4450 // Calling VM-internal helpers, uses implementation core library. |
| 4435 AstNode* Parser::MakeStaticCall(const char* class_name, | 4451 AstNode* Parser::MakeStaticCall(const char* class_name, |
| 4436 const char* function_name, | 4452 const char* function_name, |
| 4437 ArgumentListNode* arguments) { | 4453 ArgumentListNode* arguments) { |
| 4438 const String& cls_name = | 4454 const String& cls_name = |
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5103 va_start(args, format); | 5119 va_start(args, format); |
| 5104 FormatMessage(script_, token_index_, "Error", | 5120 FormatMessage(script_, token_index_, "Error", |
| 5105 message_buffer, kMessageBufferSize, | 5121 message_buffer, kMessageBufferSize, |
| 5106 format, args); | 5122 format, args); |
| 5107 va_end(args); | 5123 va_end(args); |
| 5108 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); | 5124 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); |
| 5109 UNREACHABLE(); | 5125 UNREACHABLE(); |
| 5110 } | 5126 } |
| 5111 | 5127 |
| 5112 | 5128 |
| 5129 void Parser::Warning(intptr_t token_index, const char* format, ...) { |
| 5130 const intptr_t kMessageBufferSize = 512; |
| 5131 char message_buffer[kMessageBufferSize]; |
| 5132 if (FLAG_silent_warnings) return; |
| 5133 va_list args; |
| 5134 va_start(args, format); |
| 5135 FormatMessage(script_, token_index, "Warning", |
| 5136 message_buffer, kMessageBufferSize, |
| 5137 format, args); |
| 5138 va_end(args); |
| 5139 if (FLAG_warning_as_error) { |
| 5140 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); |
| 5141 UNREACHABLE(); |
| 5142 } else { |
| 5143 OS::Print(message_buffer); |
| 5144 } |
| 5145 } |
| 5146 |
| 5147 |
| 5113 void Parser::Warning(const char* format, ...) { | 5148 void Parser::Warning(const char* format, ...) { |
| 5114 const intptr_t kMessageBufferSize = 512; | 5149 const intptr_t kMessageBufferSize = 512; |
| 5115 char message_buffer[kMessageBufferSize]; | 5150 char message_buffer[kMessageBufferSize]; |
| 5116 if (FLAG_silent_warnings) return; | 5151 if (FLAG_silent_warnings) return; |
| 5117 va_list args; | 5152 va_list args; |
| 5118 va_start(args, format); | 5153 va_start(args, format); |
| 5119 FormatMessage(script_, token_index_, "Warning", | 5154 FormatMessage(script_, token_index_, "Warning", |
| 5120 message_buffer, kMessageBufferSize, | 5155 message_buffer, kMessageBufferSize, |
| 5121 format, args); | 5156 format, args); |
| 5122 va_end(args); | 5157 va_end(args); |
| (...skipping 1530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6653 } | 6688 } |
| 6654 pairs->AddElement(key); | 6689 pairs->AddElement(key); |
| 6655 pairs->AddElement(value); | 6690 pairs->AddElement(value); |
| 6656 } | 6691 } |
| 6657 | 6692 |
| 6658 | 6693 |
| 6659 AstNode* Parser::ParseMapLiteral(intptr_t type_pos, | 6694 AstNode* Parser::ParseMapLiteral(intptr_t type_pos, |
| 6660 bool is_const, | 6695 bool is_const, |
| 6661 const TypeArguments& type_arguments) { | 6696 const TypeArguments& type_arguments) { |
| 6662 TRACE_PARSER("ParseMapLiteral"); | 6697 TRACE_PARSER("ParseMapLiteral"); |
| 6698 ASSERT(type_pos >= 0); |
| 6663 ASSERT(CurrentToken() == Token::kLBRACE); | 6699 ASSERT(CurrentToken() == Token::kLBRACE); |
| 6664 const intptr_t literal_pos = token_index_; | 6700 const intptr_t literal_pos = token_index_; |
| 6665 ConsumeToken(); | 6701 ConsumeToken(); |
| 6666 | 6702 |
| 6667 String& map_class_name = String::Handle( | 6703 Type& value_type_argument = Type::Handle(Type::DynamicType()); |
| 6668 String::NewSymbol(is_const ? kImmutableMapName : kMutableMapName)); | |
| 6669 const Class& map_class = Class::Handle(LookupImplClass(map_class_name)); | |
| 6670 ASSERT(!map_class.IsNull()); | |
| 6671 | |
| 6672 TypeArguments& map_type_arguments = | 6704 TypeArguments& map_type_arguments = |
| 6673 TypeArguments::ZoneHandle(type_arguments.raw()); | 6705 TypeArguments::ZoneHandle(type_arguments.raw()); |
| 6674 // If no type arguments are provided, leave them as null, which is equivalent | 6706 // If no type argument is provided, leave it as null, which is equivalent |
| 6675 // to using Map<Dynamic, Dynamic>. See issue 4966724. | 6707 // to using Dynamic as the type argument for the value type. |
| 6676 if (!map_type_arguments.IsNull()) { | 6708 if (!map_type_arguments.IsNull()) { |
| 6677 // For now, only check the number of type arguments. See issue 4975876. | 6709 // Map literals only take one type argument. |
| 6678 if (map_type_arguments.Length() != 2) { | 6710 value_type_argument = map_type_arguments.TypeAt(0); |
| 6679 ASSERT(type_pos >= 0); | 6711 if (map_type_arguments.Length() > 1) { |
| 6680 ErrorMsg(type_pos, "wrong number of type arguments for Map literal"); | 6712 // We temporarily accept two type arguments, as long as the first one is |
| 6713 // type String. |
| 6714 if (map_type_arguments.Length() != 2) { |
| 6715 ErrorMsg(type_pos, |
| 6716 "a map literal takes one type argument specifying " |
| 6717 "the value type"); |
| 6718 } |
| 6719 if (!value_type_argument.IsStringInterface()) { |
| 6720 ErrorMsg(type_pos, |
| 6721 "the key type of a map literal is implicitly 'String'"); |
| 6722 } |
| 6723 Warning(type_pos, |
| 6724 "a map literal takes one type argument specifying " |
| 6725 "the value type"); |
| 6726 value_type_argument = map_type_arguments.TypeAt(1); |
| 6727 } else { |
| 6728 TypeArray& type_array = TypeArray::Handle(TypeArray::New(2)); |
| 6729 type_array.SetTypeAt(0, Type::Handle(Type::StringInterface())); |
| 6730 type_array.SetTypeAt(1, value_type_argument); |
| 6731 map_type_arguments = type_array.raw(); |
| 6732 } |
| 6733 if (is_const && !value_type_argument.IsInstantiated()) { |
| 6734 ErrorMsg(type_pos, |
| 6735 "the type argument of a constant map literal cannot include " |
| 6736 "a type variable"); |
| 6681 } | 6737 } |
| 6682 } | 6738 } |
| 6739 ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2)); |
| 6683 | 6740 |
| 6684 // Parse the map entries. Note: there may be an optional extra | 6741 // Parse the map entries. Note: there may be an optional extra |
| 6685 // comma after the last entry. | 6742 // comma after the last entry. |
| 6686 ArrayNode* kv_pairs = | 6743 ArrayNode* kv_pairs = |
| 6687 new ArrayNode(token_index_, TypeArguments::ZoneHandle()); | 6744 new ArrayNode(token_index_, TypeArguments::ZoneHandle()); |
| 6688 while (CurrentToken() != Token::kRBRACE) { | 6745 while (CurrentToken() != Token::kRBRACE) { |
| 6689 AstNode* key = NULL; | 6746 AstNode* key = NULL; |
| 6690 if (CurrentToken() == Token::kSTRING) { | 6747 if (CurrentToken() == Token::kSTRING) { |
| 6691 key = ParseStringLiteral(); | 6748 key = ParseStringLiteral(); |
| 6692 } | 6749 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 6716 // the immutable map object with it. This all happens at compile time. | 6773 // the immutable map object with it. This all happens at compile time. |
| 6717 // The resulting immutable map object is returned as a literal. | 6774 // The resulting immutable map object is returned as a literal. |
| 6718 | 6775 |
| 6719 // First, create the canonicalized key-value pair array. | 6776 // First, create the canonicalized key-value pair array. |
| 6720 Array& key_value_array = | 6777 Array& key_value_array = |
| 6721 Array::ZoneHandle(Array::New(kv_pairs->length(), Heap::kOld)); | 6778 Array::ZoneHandle(Array::New(kv_pairs->length(), Heap::kOld)); |
| 6722 for (int i = 0; i < kv_pairs->length(); i++) { | 6779 for (int i = 0; i < kv_pairs->length(); i++) { |
| 6723 AstNode* arg = kv_pairs->ElementAt(i); | 6780 AstNode* arg = kv_pairs->ElementAt(i); |
| 6724 // Arguments have been evaluated to a literal value already. | 6781 // Arguments have been evaluated to a literal value already. |
| 6725 ASSERT(arg->IsLiteralNode()); | 6782 ASSERT(arg->IsLiteralNode()); |
| 6783 if (((i % 2) == 1) && // Check values only, not keys. |
| 6784 !value_type_argument.IsDynamicType() && |
| 6785 !arg->AsLiteralNode()->literal().Is(value_type_argument)) { |
| 6786 ErrorMsg(arg->AsLiteralNode()->token_index(), |
| 6787 "map literal entry value must be a constant of type '%s'", |
| 6788 String::Handle(value_type_argument.Name()).ToCString()); |
| 6789 } |
| 6726 key_value_array.SetAt(i, arg->AsLiteralNode()->literal()); | 6790 key_value_array.SetAt(i, arg->AsLiteralNode()->literal()); |
| 6727 } | 6791 } |
| 6728 key_value_array ^= key_value_array.Canonicalize(); | 6792 key_value_array ^= key_value_array.Canonicalize(); |
| 6729 key_value_array.MakeImmutable(); | 6793 key_value_array.MakeImmutable(); |
| 6730 | 6794 |
| 6731 // Construct the map object. | 6795 // Construct the map object. |
| 6796 const String& immutable_map_class_name = |
| 6797 String::Handle(String::NewSymbol(kImmutableMapName)); |
| 6798 const Class& immutable_map_class = |
| 6799 Class::Handle(LookupImplClass(immutable_map_class_name)); |
| 6800 ASSERT(!immutable_map_class.IsNull()); |
| 6732 ArgumentListNode* constr_args = new ArgumentListNode(token_index_); | 6801 ArgumentListNode* constr_args = new ArgumentListNode(token_index_); |
| 6733 constr_args->Add(new LiteralNode(literal_pos, key_value_array)); | 6802 constr_args->Add(new LiteralNode(literal_pos, key_value_array)); |
| 6734 const String& constr_name = | 6803 const String& constr_name = |
| 6735 String::Handle(String::NewSymbol(kImmutableMapConstructorName)); | 6804 String::Handle(String::NewSymbol(kImmutableMapConstructorName)); |
| 6736 const Function& map_constr = Function::ZoneHandle( | 6805 const Function& map_constr = Function::ZoneHandle( |
| 6737 map_class.LookupConstructor(constr_name)); | 6806 immutable_map_class.LookupConstructor(constr_name)); |
| 6738 ASSERT(!map_constr.IsNull()); | 6807 ASSERT(!map_constr.IsNull()); |
| 6739 const Instance& const_instance = Instance::ZoneHandle( | 6808 const Instance& const_instance = Instance::ZoneHandle( |
| 6740 EvaluateConstConstructorCall(map_class, | 6809 EvaluateConstConstructorCall(immutable_map_class, |
| 6741 map_type_arguments, | 6810 map_type_arguments, |
| 6742 map_constr, | 6811 map_constr, |
| 6743 constr_args)); | 6812 constr_args)); |
| 6744 if (const_instance.IsUnhandledException()) { | 6813 if (const_instance.IsUnhandledException()) { |
| 6745 return CreateEvalConstConstructorThrow(literal_pos, const_instance); | 6814 return CreateEvalConstConstructorThrow(literal_pos, const_instance); |
| 6746 } else { | 6815 } else { |
| 6747 return new LiteralNode(literal_pos, const_instance); | 6816 return new LiteralNode(literal_pos, const_instance); |
| 6748 } | 6817 } |
| 6749 } else { | 6818 } else { |
| 6750 // Static call at runtime. | 6819 // Factory call at runtime. |
| 6751 const String& static_factory_name = | 6820 String& literal_map_factory_class_name = String::Handle( |
| 6752 String::Handle(String::NewSymbol(kMutableMapFromLiteralName)); | 6821 String::NewSymbol(kLiteralMapFactoryName)); |
| 6753 const Function& static_factory = Function::ZoneHandle( | 6822 const Class& literal_map_factory_class = |
| 6754 map_class.LookupStaticFunction(static_factory_name)); | 6823 Class::Handle(LookupCoreClass(literal_map_factory_class_name)); |
| 6755 ASSERT(!static_factory.IsNull()); | 6824 ASSERT(!literal_map_factory_class.IsNull()); |
| 6825 const String& literal_map_factory_name = |
| 6826 String::Handle(String::NewSymbol(kLiteralMapFactoryFromLiteralName)); |
| 6827 const Function& literal_map_factory = Function::ZoneHandle( |
| 6828 literal_map_factory_class.LookupFactory(literal_map_factory_name)); |
| 6829 ASSERT(!literal_map_factory.IsNull()); |
| 6756 if (!map_type_arguments.IsNull() && | 6830 if (!map_type_arguments.IsNull() && |
| 6757 !map_type_arguments.IsInstantiated() && | 6831 !map_type_arguments.IsInstantiated() && |
| 6758 (current_block_->scope->function_level() > 0)) { | 6832 (current_block_->scope->function_level() > 0)) { |
| 6759 // Make sure that the instantiator is captured. | 6833 // Make sure that the instantiator is captured. |
| 6760 CaptureReceiver(); | 6834 CaptureReceiver(); |
| 6761 } | 6835 } |
| 6762 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); | 6836 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); |
| 6837 factory_param->Add( |
| 6838 new LiteralNode(literal_pos, Smi::ZoneHandle(Smi::New(literal_pos)))); |
| 6839 factory_param->Add( |
| 6840 new LiteralNode(literal_pos, |
| 6841 String::ZoneHandle(value_type_argument.Name()))); |
| 6763 factory_param->Add(kv_pairs); | 6842 factory_param->Add(kv_pairs); |
| 6764 return new StaticCallNode( | 6843 return new ConstructorCallNode( |
| 6765 literal_pos, static_factory, factory_param); | 6844 literal_pos, map_type_arguments, literal_map_factory, factory_param); |
| 6766 } | 6845 } |
| 6767 } | 6846 } |
| 6768 | 6847 |
| 6769 | 6848 |
| 6770 AstNode* Parser::ParseCompoundLiteral() { | 6849 AstNode* Parser::ParseCompoundLiteral() { |
| 6771 bool is_const = false; | 6850 bool is_const = false; |
| 6772 if (CurrentToken() == Token::kCONST) { | 6851 if (CurrentToken() == Token::kCONST) { |
| 6773 is_const = true; | 6852 is_const = true; |
| 6774 ConsumeToken(); | 6853 ConsumeToken(); |
| 6775 } | 6854 } |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7432 } | 7511 } |
| 7433 | 7512 |
| 7434 | 7513 |
| 7435 void Parser::SkipNestedExpr() { | 7514 void Parser::SkipNestedExpr() { |
| 7436 const bool saved_mode = SetAllowFunctionLiterals(true); | 7515 const bool saved_mode = SetAllowFunctionLiterals(true); |
| 7437 SkipExpr(); | 7516 SkipExpr(); |
| 7438 SetAllowFunctionLiterals(saved_mode); | 7517 SetAllowFunctionLiterals(saved_mode); |
| 7439 } | 7518 } |
| 7440 | 7519 |
| 7441 } // namespace dart | 7520 } // namespace dart |
| OLD | NEW |