Chromium Code Reviews| 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); | |
|
srdjan
2011/11/23 03:43:44
Future CL: Since we are using this flag only for d
regis
2011/11/23 15:51:32
Will do.
| |
| 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 4374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4423 } | 4424 } |
| 4424 | 4425 |
| 4425 | 4426 |
| 4426 // Lookup class in the corelib implementation which contains various VM | 4427 // Lookup class in the corelib implementation which contains various VM |
| 4427 // helper methods and classes. | 4428 // helper methods and classes. |
| 4428 static RawClass* LookupImplClass(const String& class_name) { | 4429 static RawClass* LookupImplClass(const String& class_name) { |
| 4429 return Library::Handle(Library::CoreImplLibrary()).LookupClass(class_name); | 4430 return Library::Handle(Library::CoreImplLibrary()).LookupClass(class_name); |
| 4430 } | 4431 } |
| 4431 | 4432 |
| 4432 | 4433 |
| 4434 // Lookup class in the corelib which also contains various VM | |
| 4435 // helper methods and classes. Allow look up of private classes. | |
| 4436 static RawClass* LookupCoreClass(const String& class_name) { | |
| 4437 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | |
| 4438 String& name = String::Handle(class_name.raw()); | |
| 4439 if ((class_name.CharAt(0) == Scanner::kPrivateIdentifierStart) && | |
| 4440 !FLAG_expose_core_impl) { | |
| 4441 // Private identifiers are mangled on a per script basis. | |
| 4442 name = String::Concat(name, String::Handle(core_lib.private_key())); | |
| 4443 name = String::NewSymbol(name); | |
| 4444 } | |
| 4445 return core_lib.LookupClass(name); | |
| 4446 } | |
| 4447 | |
| 4448 | |
| 4433 RawClass* Parser::LookupClass(const String& class_name) { | 4449 RawClass* Parser::LookupClass(const String& class_name) { |
| 4434 return library_.LookupClass(class_name); | 4450 return library_.LookupClass(class_name); |
| 4435 } | 4451 } |
| 4436 | 4452 |
| 4437 | 4453 |
| 4438 // Calling VM-internal helpers, uses implementation core library. | 4454 // Calling VM-internal helpers, uses implementation core library. |
| 4439 AstNode* Parser::MakeStaticCall(const char* class_name, | 4455 AstNode* Parser::MakeStaticCall(const char* class_name, |
| 4440 const char* function_name, | 4456 const char* function_name, |
| 4441 ArgumentListNode* arguments) { | 4457 ArgumentListNode* arguments) { |
| 4442 const String& cls_name = | 4458 const String& cls_name = |
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5107 va_start(args, format); | 5123 va_start(args, format); |
| 5108 FormatMessage(script_, token_index_, "Error", | 5124 FormatMessage(script_, token_index_, "Error", |
| 5109 message_buffer, kMessageBufferSize, | 5125 message_buffer, kMessageBufferSize, |
| 5110 format, args); | 5126 format, args); |
| 5111 va_end(args); | 5127 va_end(args); |
| 5112 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); | 5128 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); |
| 5113 UNREACHABLE(); | 5129 UNREACHABLE(); |
| 5114 } | 5130 } |
| 5115 | 5131 |
| 5116 | 5132 |
| 5133 void Parser::Warning(intptr_t token_index, const char* format, ...) { | |
| 5134 const intptr_t kMessageBufferSize = 512; | |
| 5135 char message_buffer[kMessageBufferSize]; | |
| 5136 if (FLAG_silent_warnings) return; | |
| 5137 va_list args; | |
| 5138 va_start(args, format); | |
| 5139 FormatMessage(script_, token_index, "Warning", | |
| 5140 message_buffer, kMessageBufferSize, | |
| 5141 format, args); | |
| 5142 va_end(args); | |
| 5143 if (FLAG_warning_as_error) { | |
| 5144 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); | |
| 5145 UNREACHABLE(); | |
| 5146 } else { | |
| 5147 OS::Print(message_buffer); | |
| 5148 } | |
| 5149 } | |
| 5150 | |
| 5151 | |
| 5117 void Parser::Warning(const char* format, ...) { | 5152 void Parser::Warning(const char* format, ...) { |
| 5118 const intptr_t kMessageBufferSize = 512; | 5153 const intptr_t kMessageBufferSize = 512; |
| 5119 char message_buffer[kMessageBufferSize]; | 5154 char message_buffer[kMessageBufferSize]; |
| 5120 if (FLAG_silent_warnings) return; | 5155 if (FLAG_silent_warnings) return; |
| 5121 va_list args; | 5156 va_list args; |
| 5122 va_start(args, format); | 5157 va_start(args, format); |
| 5123 FormatMessage(script_, token_index_, "Warning", | 5158 FormatMessage(script_, token_index_, "Warning", |
| 5124 message_buffer, kMessageBufferSize, | 5159 message_buffer, kMessageBufferSize, |
| 5125 format, args); | 5160 format, args); |
| 5126 va_end(args); | 5161 va_end(args); |
| (...skipping 1530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6657 } | 6692 } |
| 6658 pairs->AddElement(key); | 6693 pairs->AddElement(key); |
| 6659 pairs->AddElement(value); | 6694 pairs->AddElement(value); |
| 6660 } | 6695 } |
| 6661 | 6696 |
| 6662 | 6697 |
| 6663 AstNode* Parser::ParseMapLiteral(intptr_t type_pos, | 6698 AstNode* Parser::ParseMapLiteral(intptr_t type_pos, |
| 6664 bool is_const, | 6699 bool is_const, |
| 6665 const TypeArguments& type_arguments) { | 6700 const TypeArguments& type_arguments) { |
| 6666 TRACE_PARSER("ParseMapLiteral"); | 6701 TRACE_PARSER("ParseMapLiteral"); |
| 6702 ASSERT(type_pos >= 0); | |
| 6667 ASSERT(CurrentToken() == Token::kLBRACE); | 6703 ASSERT(CurrentToken() == Token::kLBRACE); |
| 6668 const intptr_t literal_pos = token_index_; | 6704 const intptr_t literal_pos = token_index_; |
| 6669 ConsumeToken(); | 6705 ConsumeToken(); |
| 6670 | 6706 |
| 6671 String& map_class_name = String::Handle( | 6707 Type& value_type_argument = Type::Handle(Type::DynamicType()); |
| 6672 String::NewSymbol(is_const ? kImmutableMapName : kMutableMapName)); | |
| 6673 const Class& map_class = Class::Handle(LookupImplClass(map_class_name)); | |
| 6674 ASSERT(!map_class.IsNull()); | |
| 6675 | |
| 6676 TypeArguments& map_type_arguments = | 6708 TypeArguments& map_type_arguments = |
| 6677 TypeArguments::ZoneHandle(type_arguments.raw()); | 6709 TypeArguments::ZoneHandle(type_arguments.raw()); |
| 6678 // If no type arguments are provided, leave them as null, which is equivalent | 6710 // If no type argument is provided, leave it as null, which is equivalent |
| 6679 // to using Map<Dynamic, Dynamic>. See issue 4966724. | 6711 // to using Dynamic as the type argument for the value type. |
| 6680 if (!map_type_arguments.IsNull()) { | 6712 if (!map_type_arguments.IsNull()) { |
| 6681 // For now, only check the number of type arguments. See issue 4975876. | 6713 // Map literals only take one type argument. |
| 6682 if (map_type_arguments.Length() != 2) { | 6714 value_type_argument = map_type_arguments.TypeAt(0); |
| 6683 ASSERT(type_pos >= 0); | 6715 if (map_type_arguments.Length() > 1) { |
| 6684 ErrorMsg(type_pos, "wrong number of type arguments for Map literal"); | 6716 // We temporarily accept two type arguments, as long as the first one is |
| 6717 // type String. | |
| 6718 if (map_type_arguments.Length() != 2) { | |
| 6719 ErrorMsg(type_pos, | |
| 6720 "a map literal takes one type argument specifying " | |
| 6721 "the value type"); | |
| 6722 } | |
| 6723 if (!value_type_argument.IsStringInterface()) { | |
| 6724 ErrorMsg(type_pos, | |
| 6725 "the key type of a map literal is implicitly 'String'"); | |
| 6726 } | |
| 6727 Warning(type_pos, | |
| 6728 "a map literal takes one type argument specifying " | |
| 6729 "the value type"); | |
| 6730 value_type_argument = map_type_arguments.TypeAt(1); | |
| 6731 } else { | |
| 6732 TypeArray& type_array = TypeArray::Handle(TypeArray::New(2)); | |
| 6733 type_array.SetTypeAt(0, Type::Handle(Type::StringInterface())); | |
| 6734 type_array.SetTypeAt(1, value_type_argument); | |
| 6735 map_type_arguments = type_array.raw(); | |
| 6736 } | |
| 6737 if (is_const && !value_type_argument.IsInstantiated()) { | |
| 6738 ErrorMsg(type_pos, | |
| 6739 "the type argument of a constant map literal cannot include " | |
| 6740 "a type variable"); | |
| 6685 } | 6741 } |
| 6686 } | 6742 } |
| 6743 ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2)); | |
| 6687 | 6744 |
| 6688 // Parse the map entries. Note: there may be an optional extra | 6745 // Parse the map entries. Note: there may be an optional extra |
| 6689 // comma after the last entry. | 6746 // comma after the last entry. |
| 6690 ArrayNode* kv_pairs = | 6747 ArrayNode* kv_pairs = |
| 6691 new ArrayNode(token_index_, TypeArguments::ZoneHandle()); | 6748 new ArrayNode(token_index_, TypeArguments::ZoneHandle()); |
| 6692 while (CurrentToken() != Token::kRBRACE) { | 6749 while (CurrentToken() != Token::kRBRACE) { |
| 6693 AstNode* key = NULL; | 6750 AstNode* key = NULL; |
| 6694 if (CurrentToken() == Token::kSTRING) { | 6751 if (CurrentToken() == Token::kSTRING) { |
| 6695 key = ParseStringLiteral(); | 6752 key = ParseStringLiteral(); |
| 6696 } | 6753 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 6720 // the immutable map object with it. This all happens at compile time. | 6777 // the immutable map object with it. This all happens at compile time. |
| 6721 // The resulting immutable map object is returned as a literal. | 6778 // The resulting immutable map object is returned as a literal. |
| 6722 | 6779 |
| 6723 // First, create the canonicalized key-value pair array. | 6780 // First, create the canonicalized key-value pair array. |
| 6724 Array& key_value_array = | 6781 Array& key_value_array = |
| 6725 Array::ZoneHandle(Array::New(kv_pairs->length(), Heap::kOld)); | 6782 Array::ZoneHandle(Array::New(kv_pairs->length(), Heap::kOld)); |
| 6726 for (int i = 0; i < kv_pairs->length(); i++) { | 6783 for (int i = 0; i < kv_pairs->length(); i++) { |
| 6727 AstNode* arg = kv_pairs->ElementAt(i); | 6784 AstNode* arg = kv_pairs->ElementAt(i); |
| 6728 // Arguments have been evaluated to a literal value already. | 6785 // Arguments have been evaluated to a literal value already. |
| 6729 ASSERT(arg->IsLiteralNode()); | 6786 ASSERT(arg->IsLiteralNode()); |
| 6787 if (((i % 2) == 1) && // Check values only, not keys. | |
| 6788 !value_type_argument.IsDynamicType() && | |
| 6789 !arg->AsLiteralNode()->literal().Is(value_type_argument)) { | |
| 6790 ErrorMsg(arg->AsLiteralNode()->token_index(), | |
| 6791 "map literal entry value must be a constant of type '%s'", | |
| 6792 String::Handle(value_type_argument.Name()).ToCString()); | |
| 6793 } | |
| 6730 key_value_array.SetAt(i, arg->AsLiteralNode()->literal()); | 6794 key_value_array.SetAt(i, arg->AsLiteralNode()->literal()); |
| 6731 } | 6795 } |
| 6732 key_value_array ^= key_value_array.Canonicalize(); | 6796 key_value_array ^= key_value_array.Canonicalize(); |
| 6733 key_value_array.MakeImmutable(); | 6797 key_value_array.MakeImmutable(); |
| 6734 | 6798 |
| 6735 // Construct the map object. | 6799 // Construct the map object. |
| 6800 const String& immutable_map_class_name = | |
| 6801 String::Handle(String::NewSymbol(kImmutableMapName)); | |
| 6802 const Class& immutable_map_class = | |
| 6803 Class::Handle(LookupImplClass(immutable_map_class_name)); | |
| 6804 ASSERT(!immutable_map_class.IsNull()); | |
| 6736 ArgumentListNode* constr_args = new ArgumentListNode(token_index_); | 6805 ArgumentListNode* constr_args = new ArgumentListNode(token_index_); |
| 6737 constr_args->Add(new LiteralNode(literal_pos, key_value_array)); | 6806 constr_args->Add(new LiteralNode(literal_pos, key_value_array)); |
| 6738 const String& constr_name = | 6807 const String& constr_name = |
| 6739 String::Handle(String::NewSymbol(kImmutableMapConstructorName)); | 6808 String::Handle(String::NewSymbol(kImmutableMapConstructorName)); |
| 6740 const Function& map_constr = Function::ZoneHandle( | 6809 const Function& map_constr = Function::ZoneHandle( |
| 6741 map_class.LookupConstructor(constr_name)); | 6810 immutable_map_class.LookupConstructor(constr_name)); |
| 6742 ASSERT(!map_constr.IsNull()); | 6811 ASSERT(!map_constr.IsNull()); |
| 6743 const Instance& const_instance = Instance::ZoneHandle( | 6812 const Instance& const_instance = Instance::ZoneHandle( |
| 6744 EvaluateConstConstructorCall(map_class, | 6813 EvaluateConstConstructorCall(immutable_map_class, |
| 6745 map_type_arguments, | 6814 map_type_arguments, |
| 6746 map_constr, | 6815 map_constr, |
| 6747 constr_args)); | 6816 constr_args)); |
| 6748 if (const_instance.IsUnhandledException()) { | 6817 if (const_instance.IsUnhandledException()) { |
| 6749 return CreateEvalConstConstructorThrow(literal_pos, const_instance); | 6818 return CreateEvalConstConstructorThrow(literal_pos, const_instance); |
| 6750 } else { | 6819 } else { |
| 6751 return new LiteralNode(literal_pos, const_instance); | 6820 return new LiteralNode(literal_pos, const_instance); |
| 6752 } | 6821 } |
| 6753 } else { | 6822 } else { |
| 6754 // Static call at runtime. | 6823 // Factory call at runtime. |
| 6755 const String& static_factory_name = | 6824 String& literal_map_factory_class_name = String::Handle( |
| 6756 String::Handle(String::NewSymbol(kMutableMapFromLiteralName)); | 6825 String::NewSymbol(kLiteralMapFactoryName)); |
| 6757 const Function& static_factory = Function::ZoneHandle( | 6826 const Class& literal_map_factory_class = |
| 6758 map_class.LookupStaticFunction(static_factory_name)); | 6827 Class::Handle(LookupCoreClass(literal_map_factory_class_name)); |
| 6759 ASSERT(!static_factory.IsNull()); | 6828 ASSERT(!literal_map_factory_class.IsNull()); |
| 6829 const String& literal_map_factory_name = | |
| 6830 String::Handle(String::NewSymbol(kLiteralMapFactoryFromLiteralName)); | |
| 6831 const Function& literal_map_factory = Function::ZoneHandle( | |
| 6832 literal_map_factory_class.LookupFactory(literal_map_factory_name)); | |
| 6833 ASSERT(!literal_map_factory.IsNull()); | |
| 6760 if (!map_type_arguments.IsNull() && | 6834 if (!map_type_arguments.IsNull() && |
| 6761 !map_type_arguments.IsInstantiated() && | 6835 !map_type_arguments.IsInstantiated() && |
| 6762 (current_block_->scope->function_level() > 0)) { | 6836 (current_block_->scope->function_level() > 0)) { |
| 6763 // Make sure that the instantiator is captured. | 6837 // Make sure that the instantiator is captured. |
| 6764 CaptureReceiver(); | 6838 CaptureReceiver(); |
| 6765 } | 6839 } |
| 6766 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); | 6840 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); |
| 6841 factory_param->Add( | |
| 6842 new LiteralNode(literal_pos, Smi::ZoneHandle(Smi::New(literal_pos)))); | |
| 6843 factory_param->Add( | |
| 6844 new LiteralNode(literal_pos, | |
| 6845 String::ZoneHandle(value_type_argument.Name()))); | |
| 6767 factory_param->Add(kv_pairs); | 6846 factory_param->Add(kv_pairs); |
| 6768 return new StaticCallNode( | 6847 return new ConstructorCallNode( |
| 6769 literal_pos, static_factory, factory_param); | 6848 literal_pos, map_type_arguments, literal_map_factory, factory_param); |
| 6770 } | 6849 } |
| 6771 } | 6850 } |
| 6772 | 6851 |
| 6773 | 6852 |
| 6774 AstNode* Parser::ParseCompoundLiteral() { | 6853 AstNode* Parser::ParseCompoundLiteral() { |
| 6775 bool is_const = false; | 6854 bool is_const = false; |
| 6776 if (CurrentToken() == Token::kCONST) { | 6855 if (CurrentToken() == Token::kCONST) { |
| 6777 is_const = true; | 6856 is_const = true; |
| 6778 ConsumeToken(); | 6857 ConsumeToken(); |
| 6779 } | 6858 } |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7436 } | 7515 } |
| 7437 | 7516 |
| 7438 | 7517 |
| 7439 void Parser::SkipNestedExpr() { | 7518 void Parser::SkipNestedExpr() { |
| 7440 const bool saved_mode = SetAllowFunctionLiterals(true); | 7519 const bool saved_mode = SetAllowFunctionLiterals(true); |
| 7441 SkipExpr(); | 7520 SkipExpr(); |
| 7442 SetAllowFunctionLiterals(saved_mode); | 7521 SetAllowFunctionLiterals(saved_mode); |
| 7443 } | 7522 } |
| 7444 | 7523 |
| 7445 } // namespace dart | 7524 } // namespace dart |
| OLD | NEW |