| 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 "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" |
| (...skipping 8576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8587 "a type variable"); | 8587 "a type variable"); |
| 8588 } | 8588 } |
| 8589 } | 8589 } |
| 8590 ASSERT(type_arguments.IsNull() || (type_arguments.Length() == 1)); | 8590 ASSERT(type_arguments.IsNull() || (type_arguments.Length() == 1)); |
| 8591 const Class& array_class = Class::Handle( | 8591 const Class& array_class = Class::Handle( |
| 8592 Isolate::Current()->object_store()->array_class()); | 8592 Isolate::Current()->object_store()->array_class()); |
| 8593 Type& type = Type::ZoneHandle( | 8593 Type& type = Type::ZoneHandle( |
| 8594 Type::New(array_class, type_arguments, type_pos)); | 8594 Type::New(array_class, type_arguments, type_pos)); |
| 8595 type ^= ClassFinalizer::FinalizeType( | 8595 type ^= ClassFinalizer::FinalizeType( |
| 8596 current_class(), type, ClassFinalizer::kCanonicalize); | 8596 current_class(), type, ClassFinalizer::kCanonicalize); |
| 8597 ArrayNode* list = new ArrayNode(TokenPos(), type); | 8597 GrowableArray<AstNode*> element_list; |
| 8598 | |
| 8599 // Parse the list elements. Note: there may be an optional extra | 8598 // Parse the list elements. Note: there may be an optional extra |
| 8600 // comma after the last element. | 8599 // comma after the last element. |
| 8601 if (!is_empty_literal) { | 8600 if (!is_empty_literal) { |
| 8602 const bool saved_mode = SetAllowFunctionLiterals(true); | 8601 const bool saved_mode = SetAllowFunctionLiterals(true); |
| 8603 while (CurrentToken() != Token::kRBRACK) { | 8602 while (CurrentToken() != Token::kRBRACK) { |
| 8604 const intptr_t element_pos = TokenPos(); | 8603 const intptr_t element_pos = TokenPos(); |
| 8605 AstNode* element = ParseExpr(is_const, kConsumeCascades); | 8604 AstNode* element = ParseExpr(is_const, kConsumeCascades); |
| 8606 if (FLAG_enable_type_checks && | 8605 if (FLAG_enable_type_checks && |
| 8607 !is_const && | 8606 !is_const && |
| 8608 !element_type.IsDynamicType()) { | 8607 !element_type.IsDynamicType()) { |
| 8609 element = new AssignableNode(element_pos, | 8608 element = new AssignableNode(element_pos, |
| 8610 element, | 8609 element, |
| 8611 element_type, | 8610 element_type, |
| 8612 Symbols::ListLiteralElement()); | 8611 Symbols::ListLiteralElement()); |
| 8613 } | 8612 } |
| 8614 list->AddElement(element); | 8613 element_list.Add(element); |
| 8615 if (CurrentToken() == Token::kCOMMA) { | 8614 if (CurrentToken() == Token::kCOMMA) { |
| 8616 ConsumeToken(); | 8615 ConsumeToken(); |
| 8617 } else if (CurrentToken() != Token::kRBRACK) { | 8616 } else if (CurrentToken() != Token::kRBRACK) { |
| 8618 ErrorMsg("comma or ']' expected"); | 8617 ErrorMsg("comma or ']' expected"); |
| 8619 } | 8618 } |
| 8620 } | 8619 } |
| 8621 ExpectToken(Token::kRBRACK); | 8620 ExpectToken(Token::kRBRACK); |
| 8622 SetAllowFunctionLiterals(saved_mode); | 8621 SetAllowFunctionLiterals(saved_mode); |
| 8623 } | 8622 } |
| 8624 | 8623 |
| 8625 if (is_const) { | 8624 if (is_const) { |
| 8626 // Allocate and initialize the const list at compile time. | 8625 // Allocate and initialize the const list at compile time. |
| 8627 Array& const_list = | 8626 Array& const_list = |
| 8628 Array::ZoneHandle(Array::New(list->length(), Heap::kOld)); | 8627 Array::ZoneHandle(Array::New(element_list.length(), Heap::kOld)); |
| 8629 const_list.SetTypeArguments( | 8628 const_list.SetTypeArguments( |
| 8630 AbstractTypeArguments::Handle(type_arguments.Canonicalize())); | 8629 AbstractTypeArguments::Handle(type_arguments.Canonicalize())); |
| 8631 Error& malformed_error = Error::Handle(); | 8630 Error& malformed_error = Error::Handle(); |
| 8632 for (int i = 0; i < list->length(); i++) { | 8631 for (int i = 0; i < element_list.length(); i++) { |
| 8633 AstNode* elem = list->ElementAt(i); | 8632 AstNode* elem = element_list[i]; |
| 8634 // Arguments have been evaluated to a literal value already. | 8633 // Arguments have been evaluated to a literal value already. |
| 8635 ASSERT(elem->IsLiteralNode()); | 8634 ASSERT(elem->IsLiteralNode()); |
| 8636 if (FLAG_enable_type_checks && | 8635 if (FLAG_enable_type_checks && |
| 8637 !element_type.IsDynamicType() && | 8636 !element_type.IsDynamicType() && |
| 8638 (!elem->AsLiteralNode()->literal().IsNull() && | 8637 (!elem->AsLiteralNode()->literal().IsNull() && |
| 8639 !elem->AsLiteralNode()->literal().IsInstanceOf( | 8638 !elem->AsLiteralNode()->literal().IsInstanceOf( |
| 8640 element_type, TypeArguments::Handle(), &malformed_error))) { | 8639 element_type, TypeArguments::Handle(), &malformed_error))) { |
| 8641 // If the failure is due to a malformed type error, display it instead. | 8640 // If the failure is due to a malformed type error, display it instead. |
| 8642 if (!malformed_error.IsNull()) { | 8641 if (!malformed_error.IsNull()) { |
| 8643 ErrorMsg(malformed_error); | 8642 ErrorMsg(malformed_error); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8677 ASSERT(factory_type_args.Length() == 1); | 8676 ASSERT(factory_type_args.Length() == 1); |
| 8678 Type& factory_type = Type::Handle(Type::New( | 8677 Type& factory_type = Type::Handle(Type::New( |
| 8679 factory_class, factory_type_args, type_pos, Heap::kNew)); | 8678 factory_class, factory_type_args, type_pos, Heap::kNew)); |
| 8680 factory_type ^= ClassFinalizer::FinalizeType( | 8679 factory_type ^= ClassFinalizer::FinalizeType( |
| 8681 current_class(), factory_type, ClassFinalizer::kFinalize); | 8680 current_class(), factory_type, ClassFinalizer::kFinalize); |
| 8682 factory_type_args = factory_type.arguments(); | 8681 factory_type_args = factory_type.arguments(); |
| 8683 ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments()); | 8682 ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments()); |
| 8684 } | 8683 } |
| 8685 factory_type_args = factory_type_args.Canonicalize(); | 8684 factory_type_args = factory_type_args.Canonicalize(); |
| 8686 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); | 8685 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); |
| 8686 ArrayNode* list = new ArrayNode(TokenPos(), type, element_list); |
| 8687 factory_param->Add(list); | 8687 factory_param->Add(list); |
| 8688 return CreateConstructorCallNode(literal_pos, | 8688 return CreateConstructorCallNode(literal_pos, |
| 8689 factory_type_args, | 8689 factory_type_args, |
| 8690 factory_method, | 8690 factory_method, |
| 8691 factory_param); | 8691 factory_param); |
| 8692 } | 8692 } |
| 8693 } | 8693 } |
| 8694 | 8694 |
| 8695 | 8695 |
| 8696 ConstructorCallNode* Parser::CreateConstructorCallNode( | 8696 ConstructorCallNode* Parser::CreateConstructorCallNode( |
| 8697 intptr_t token_pos, | 8697 intptr_t token_pos, |
| 8698 const AbstractTypeArguments& type_arguments, | 8698 const AbstractTypeArguments& type_arguments, |
| 8699 const Function& constructor, | 8699 const Function& constructor, |
| 8700 ArgumentListNode* arguments) { | 8700 ArgumentListNode* arguments) { |
| 8701 if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) { | 8701 if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) { |
| 8702 EnsureExpressionTemp(); | 8702 EnsureExpressionTemp(); |
| 8703 } | 8703 } |
| 8704 LocalVariable* allocated = | 8704 LocalVariable* allocated = |
| 8705 CreateTempConstVariable(token_pos, "alloc"); | 8705 CreateTempConstVariable(token_pos, "alloc"); |
| 8706 return new ConstructorCallNode(token_pos, | 8706 return new ConstructorCallNode(token_pos, |
| 8707 type_arguments, | 8707 type_arguments, |
| 8708 constructor, | 8708 constructor, |
| 8709 arguments, | 8709 arguments, |
| 8710 allocated); | 8710 allocated); |
| 8711 } | 8711 } |
| 8712 | 8712 |
| 8713 | 8713 |
| 8714 static void AddKeyValuePair(ArrayNode* pairs, | 8714 static void AddKeyValuePair(GrowableArray<AstNode*>* pairs, |
| 8715 bool is_const, | 8715 bool is_const, |
| 8716 AstNode* key, | 8716 AstNode* key, |
| 8717 AstNode* value) { | 8717 AstNode* value) { |
| 8718 if (is_const) { | 8718 if (is_const) { |
| 8719 ASSERT(key->IsLiteralNode()); | 8719 ASSERT(key->IsLiteralNode()); |
| 8720 ASSERT(key->AsLiteralNode()->literal().IsString()); | 8720 ASSERT(key->AsLiteralNode()->literal().IsString()); |
| 8721 const Instance& new_key = key->AsLiteralNode()->literal(); | 8721 const Instance& new_key = key->AsLiteralNode()->literal(); |
| 8722 for (int i = 0; i < pairs->length(); i += 2) { | 8722 for (int i = 0; i < pairs->length(); i += 2) { |
| 8723 const Instance& key_i = | 8723 const Instance& key_i = |
| 8724 pairs->ElementAt(i)->AsLiteralNode()->literal(); | 8724 (*pairs)[i]->AsLiteralNode()->literal(); |
| 8725 ASSERT(key_i.IsString()); | 8725 ASSERT(key_i.IsString()); |
| 8726 if (new_key.Equals(key_i)) { | 8726 if (new_key.Equals(key_i)) { |
| 8727 // Duplicate key found. The new value replaces the previously | 8727 // Duplicate key found. The new value replaces the previously |
| 8728 // defined value. | 8728 // defined value. |
| 8729 pairs->SetElementAt(i + 1, value); | 8729 (*pairs)[i + 1] = value; |
| 8730 return; | 8730 return; |
| 8731 } | 8731 } |
| 8732 } | 8732 } |
| 8733 } | 8733 } |
| 8734 pairs->AddElement(key); | 8734 pairs->Add(key); |
| 8735 pairs->AddElement(value); | 8735 pairs->Add(value); |
| 8736 } | 8736 } |
| 8737 | 8737 |
| 8738 | 8738 |
| 8739 AstNode* Parser::ParseMapLiteral(intptr_t type_pos, | 8739 AstNode* Parser::ParseMapLiteral(intptr_t type_pos, |
| 8740 bool is_const, | 8740 bool is_const, |
| 8741 const AbstractTypeArguments& type_arguments) { | 8741 const AbstractTypeArguments& type_arguments) { |
| 8742 TRACE_PARSER("ParseMapLiteral"); | 8742 TRACE_PARSER("ParseMapLiteral"); |
| 8743 ASSERT(type_pos >= 0); | 8743 ASSERT(type_pos >= 0); |
| 8744 ASSERT(CurrentToken() == Token::kLBRACE); | 8744 ASSERT(CurrentToken() == Token::kLBRACE); |
| 8745 const intptr_t literal_pos = TokenPos(); | 8745 const intptr_t literal_pos = TokenPos(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 8768 ErrorMsg(type_pos, | 8768 ErrorMsg(type_pos, |
| 8769 "the type argument of a constant map literal cannot include " | 8769 "the type argument of a constant map literal cannot include " |
| 8770 "a type variable"); | 8770 "a type variable"); |
| 8771 } | 8771 } |
| 8772 } | 8772 } |
| 8773 ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2)); | 8773 ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2)); |
| 8774 map_type_arguments ^= map_type_arguments.Canonicalize(); | 8774 map_type_arguments ^= map_type_arguments.Canonicalize(); |
| 8775 | 8775 |
| 8776 // The kv_pair array is temporary and of element type dynamic. It is passed | 8776 // The kv_pair array is temporary and of element type dynamic. It is passed |
| 8777 // to the factory to initialize a properly typed map. | 8777 // to the factory to initialize a properly typed map. |
| 8778 ArrayNode* kv_pairs = new ArrayNode( | 8778 GrowableArray<AstNode*> kv_pairs_list; |
| 8779 TokenPos(), Type::ZoneHandle(Type::ArrayType())); | |
| 8780 | |
| 8781 // Parse the map entries. Note: there may be an optional extra | 8779 // Parse the map entries. Note: there may be an optional extra |
| 8782 // comma after the last entry. | 8780 // comma after the last entry. |
| 8783 while (CurrentToken() != Token::kRBRACE) { | 8781 while (CurrentToken() != Token::kRBRACE) { |
| 8784 AstNode* key = NULL; | 8782 AstNode* key = NULL; |
| 8785 if (CurrentToken() == Token::kSTRING) { | 8783 if (CurrentToken() == Token::kSTRING) { |
| 8786 key = ParseStringLiteral(); | 8784 key = ParseStringLiteral(); |
| 8787 } | 8785 } |
| 8788 if (key == NULL) { | 8786 if (key == NULL) { |
| 8789 ErrorMsg("map entry key must be string literal"); | 8787 ErrorMsg("map entry key must be string literal"); |
| 8790 } else if (is_const && !key->IsLiteralNode()) { | 8788 } else if (is_const && !key->IsLiteralNode()) { |
| 8791 ErrorMsg("map entry key must be compile-time constant string"); | 8789 ErrorMsg("map entry key must be compile-time constant string"); |
| 8792 } | 8790 } |
| 8793 ExpectToken(Token::kCOLON); | 8791 ExpectToken(Token::kCOLON); |
| 8794 const bool saved_mode = SetAllowFunctionLiterals(true); | 8792 const bool saved_mode = SetAllowFunctionLiterals(true); |
| 8795 const intptr_t value_pos = TokenPos(); | 8793 const intptr_t value_pos = TokenPos(); |
| 8796 AstNode* value = ParseExpr(is_const, kConsumeCascades); | 8794 AstNode* value = ParseExpr(is_const, kConsumeCascades); |
| 8797 SetAllowFunctionLiterals(saved_mode); | 8795 SetAllowFunctionLiterals(saved_mode); |
| 8798 if (FLAG_enable_type_checks && | 8796 if (FLAG_enable_type_checks && |
| 8799 !is_const && | 8797 !is_const && |
| 8800 !value_type.IsDynamicType()) { | 8798 !value_type.IsDynamicType()) { |
| 8801 value = new AssignableNode(value_pos, | 8799 value = new AssignableNode(value_pos, |
| 8802 value, | 8800 value, |
| 8803 value_type, | 8801 value_type, |
| 8804 Symbols::ListLiteralElement()); | 8802 Symbols::ListLiteralElement()); |
| 8805 } | 8803 } |
| 8806 AddKeyValuePair(kv_pairs, is_const, key, value); | 8804 AddKeyValuePair(&kv_pairs_list, is_const, key, value); |
| 8807 | 8805 |
| 8808 if (CurrentToken() == Token::kCOMMA) { | 8806 if (CurrentToken() == Token::kCOMMA) { |
| 8809 ConsumeToken(); | 8807 ConsumeToken(); |
| 8810 } else if (CurrentToken() != Token::kRBRACE) { | 8808 } else if (CurrentToken() != Token::kRBRACE) { |
| 8811 ErrorMsg("comma or '}' expected"); | 8809 ErrorMsg("comma or '}' expected"); |
| 8812 } | 8810 } |
| 8813 } | 8811 } |
| 8814 ASSERT(kv_pairs->length() % 2 == 0); | 8812 ASSERT(kv_pairs_list.length() % 2 == 0); |
| 8815 ExpectToken(Token::kRBRACE); | 8813 ExpectToken(Token::kRBRACE); |
| 8816 | 8814 |
| 8817 if (is_const) { | 8815 if (is_const) { |
| 8818 // Create the key-value pair array, canonicalize it and then create | 8816 // Create the key-value pair array, canonicalize it and then create |
| 8819 // the immutable map object with it. This all happens at compile time. | 8817 // the immutable map object with it. This all happens at compile time. |
| 8820 // The resulting immutable map object is returned as a literal. | 8818 // The resulting immutable map object is returned as a literal. |
| 8821 | 8819 |
| 8822 // First, create the canonicalized key-value pair array. | 8820 // First, create the canonicalized key-value pair array. |
| 8823 Array& key_value_array = | 8821 Array& key_value_array = |
| 8824 Array::ZoneHandle(Array::New(kv_pairs->length(), Heap::kOld)); | 8822 Array::ZoneHandle(Array::New(kv_pairs_list.length(), Heap::kOld)); |
| 8825 Error& malformed_error = Error::Handle(); | 8823 Error& malformed_error = Error::Handle(); |
| 8826 for (int i = 0; i < kv_pairs->length(); i++) { | 8824 for (int i = 0; i < kv_pairs_list.length(); i++) { |
| 8827 AstNode* arg = kv_pairs->ElementAt(i); | 8825 AstNode* arg = kv_pairs_list[i]; |
| 8828 // Arguments have been evaluated to a literal value already. | 8826 // Arguments have been evaluated to a literal value already. |
| 8829 ASSERT(arg->IsLiteralNode()); | 8827 ASSERT(arg->IsLiteralNode()); |
| 8830 if (FLAG_enable_type_checks && | 8828 if (FLAG_enable_type_checks && |
| 8831 ((i % 2) == 1) && // Check values only, not keys. | 8829 ((i % 2) == 1) && // Check values only, not keys. |
| 8832 !value_type.IsDynamicType() && | 8830 !value_type.IsDynamicType() && |
| 8833 (!arg->AsLiteralNode()->literal().IsNull() && | 8831 (!arg->AsLiteralNode()->literal().IsNull() && |
| 8834 !arg->AsLiteralNode()->literal().IsInstanceOf( | 8832 !arg->AsLiteralNode()->literal().IsInstanceOf( |
| 8835 value_type, TypeArguments::Handle(), &malformed_error))) { | 8833 value_type, TypeArguments::Handle(), &malformed_error))) { |
| 8836 // If the failure is due to a malformed type error, display it instead. | 8834 // If the failure is due to a malformed type error, display it instead. |
| 8837 if (!malformed_error.IsNull()) { | 8835 if (!malformed_error.IsNull()) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8897 ASSERT(factory_type_args.Length() == 2); | 8895 ASSERT(factory_type_args.Length() == 2); |
| 8898 Type& factory_type = Type::Handle(Type::New( | 8896 Type& factory_type = Type::Handle(Type::New( |
| 8899 factory_class, factory_type_args, type_pos, Heap::kNew)); | 8897 factory_class, factory_type_args, type_pos, Heap::kNew)); |
| 8900 factory_type ^= ClassFinalizer::FinalizeType( | 8898 factory_type ^= ClassFinalizer::FinalizeType( |
| 8901 current_class(), factory_type, ClassFinalizer::kFinalize); | 8899 current_class(), factory_type, ClassFinalizer::kFinalize); |
| 8902 factory_type_args = factory_type.arguments(); | 8900 factory_type_args = factory_type.arguments(); |
| 8903 ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments()); | 8901 ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments()); |
| 8904 } | 8902 } |
| 8905 factory_type_args = factory_type_args.Canonicalize(); | 8903 factory_type_args = factory_type_args.Canonicalize(); |
| 8906 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); | 8904 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); |
| 8905 ArrayNode* kv_pairs = new ArrayNode( |
| 8906 TokenPos(), Type::ZoneHandle(Type::ArrayType()), kv_pairs_list); |
| 8907 factory_param->Add(kv_pairs); | 8907 factory_param->Add(kv_pairs); |
| 8908 return CreateConstructorCallNode(literal_pos, | 8908 return CreateConstructorCallNode(literal_pos, |
| 8909 factory_type_args, | 8909 factory_type_args, |
| 8910 factory_method, | 8910 factory_method, |
| 8911 factory_param); | 8911 factory_param); |
| 8912 } | 8912 } |
| 8913 } | 8913 } |
| 8914 | 8914 |
| 8915 | 8915 |
| 8916 AstNode* Parser::ParseCompoundLiteral() { | 8916 AstNode* Parser::ParseCompoundLiteral() { |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9178 if (!type_bound.IsNull()) { | 9178 if (!type_bound.IsNull()) { |
| 9179 new_object = new AssignableNode(new_pos, | 9179 new_object = new AssignableNode(new_pos, |
| 9180 new_object, | 9180 new_object, |
| 9181 type_bound, | 9181 type_bound, |
| 9182 Symbols::FactoryResult()); | 9182 Symbols::FactoryResult()); |
| 9183 } | 9183 } |
| 9184 return new_object; | 9184 return new_object; |
| 9185 } | 9185 } |
| 9186 | 9186 |
| 9187 | 9187 |
| 9188 String& Parser::Interpolate(ArrayNode* values) { | 9188 String& Parser::Interpolate(const GrowableArray<AstNode*>& values) { |
| 9189 const Class& cls = Class::Handle(LookupCoreClass(Symbols::StringBase())); | 9189 const Class& cls = Class::Handle(LookupCoreClass(Symbols::StringBase())); |
| 9190 ASSERT(!cls.IsNull()); | 9190 ASSERT(!cls.IsNull()); |
| 9191 const Function& func = | 9191 const Function& func = |
| 9192 Function::Handle(cls.LookupStaticFunction( | 9192 Function::Handle(cls.LookupStaticFunction( |
| 9193 PrivateCoreLibName(Symbols::Interpolate()))); | 9193 PrivateCoreLibName(Symbols::Interpolate()))); |
| 9194 ASSERT(!func.IsNull()); | 9194 ASSERT(!func.IsNull()); |
| 9195 | 9195 |
| 9196 // Build the array of literal values to interpolate. | 9196 // Build the array of literal values to interpolate. |
| 9197 const Array& value_arr = Array::Handle(Array::New(values->length())); | 9197 const Array& value_arr = Array::Handle(Array::New(values.length())); |
| 9198 for (int i = 0; i < values->length(); i++) { | 9198 for (int i = 0; i < values.length(); i++) { |
| 9199 ASSERT(values->ElementAt(i)->IsLiteralNode()); | 9199 ASSERT(values[i]->IsLiteralNode()); |
| 9200 value_arr.SetAt(i, values->ElementAt(i)->AsLiteralNode()->literal()); | 9200 value_arr.SetAt(i, values[i]->AsLiteralNode()->literal()); |
| 9201 } | 9201 } |
| 9202 | 9202 |
| 9203 // Build argument array to pass to the interpolation function. | 9203 // Build argument array to pass to the interpolation function. |
| 9204 const Array& interpolate_arg = Array::Handle(Array::New(1)); | 9204 const Array& interpolate_arg = Array::Handle(Array::New(1)); |
| 9205 interpolate_arg.SetAt(0, value_arr); | 9205 interpolate_arg.SetAt(0, value_arr); |
| 9206 | 9206 |
| 9207 // Call interpolation function. | 9207 // Call interpolation function. |
| 9208 String& concatenated = String::ZoneHandle(); | 9208 String& concatenated = String::ZoneHandle(); |
| 9209 concatenated ^= DartEntry::InvokeStatic(func, interpolate_arg); | 9209 concatenated ^= DartEntry::InvokeStatic(func, interpolate_arg); |
| 9210 if (concatenated.IsUnhandledException()) { | 9210 if (concatenated.IsUnhandledException()) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 9230 if ((l1_token != Token::kSTRING) && | 9230 if ((l1_token != Token::kSTRING) && |
| 9231 (l1_token != Token::kINTERPOL_VAR) && | 9231 (l1_token != Token::kINTERPOL_VAR) && |
| 9232 (l1_token != Token::kINTERPOL_START)) { | 9232 (l1_token != Token::kINTERPOL_START)) { |
| 9233 // Common case: no interpolation. | 9233 // Common case: no interpolation. |
| 9234 primary = new LiteralNode(literal_start, *CurrentLiteral()); | 9234 primary = new LiteralNode(literal_start, *CurrentLiteral()); |
| 9235 ConsumeToken(); | 9235 ConsumeToken(); |
| 9236 return primary; | 9236 return primary; |
| 9237 } | 9237 } |
| 9238 // String interpolation needed. | 9238 // String interpolation needed. |
| 9239 bool is_compiletime_const = true; | 9239 bool is_compiletime_const = true; |
| 9240 ArrayNode* values = new ArrayNode( | 9240 GrowableArray<AstNode*> values_list; |
| 9241 TokenPos(), Type::ZoneHandle(Type::ArrayType())); | |
| 9242 while (CurrentToken() == Token::kSTRING) { | 9241 while (CurrentToken() == Token::kSTRING) { |
| 9243 values->AddElement(new LiteralNode(TokenPos(), *CurrentLiteral())); | 9242 values_list.Add(new LiteralNode(TokenPos(), *CurrentLiteral())); |
| 9244 ConsumeToken(); | 9243 ConsumeToken(); |
| 9245 while ((CurrentToken() == Token::kINTERPOL_VAR) || | 9244 while ((CurrentToken() == Token::kINTERPOL_VAR) || |
| 9246 (CurrentToken() == Token::kINTERPOL_START)) { | 9245 (CurrentToken() == Token::kINTERPOL_START)) { |
| 9247 AstNode* expr = NULL; | 9246 AstNode* expr = NULL; |
| 9248 const intptr_t expr_pos = TokenPos(); | 9247 const intptr_t expr_pos = TokenPos(); |
| 9249 if (CurrentToken() == Token::kINTERPOL_VAR) { | 9248 if (CurrentToken() == Token::kINTERPOL_VAR) { |
| 9250 expr = ResolveIdent(TokenPos(), *CurrentLiteral(), true); | 9249 expr = ResolveIdent(TokenPos(), *CurrentLiteral(), true); |
| 9251 ConsumeToken(); | 9250 ConsumeToken(); |
| 9252 } else { | 9251 } else { |
| 9253 ASSERT(CurrentToken() == Token::kINTERPOL_START); | 9252 ASSERT(CurrentToken() == Token::kINTERPOL_START); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 9265 (const_expr->IsNumber() || | 9264 (const_expr->IsNumber() || |
| 9266 const_expr->IsString() || | 9265 const_expr->IsString() || |
| 9267 const_expr->IsBool() || | 9266 const_expr->IsBool() || |
| 9268 const_expr->IsNull())) { | 9267 const_expr->IsNull())) { |
| 9269 // Change expr into a literal. | 9268 // Change expr into a literal. |
| 9270 expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr)); | 9269 expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr)); |
| 9271 } else { | 9270 } else { |
| 9272 is_compiletime_const = false; | 9271 is_compiletime_const = false; |
| 9273 } | 9272 } |
| 9274 } | 9273 } |
| 9275 values->AddElement(expr); | 9274 values_list.Add(expr); |
| 9276 } | 9275 } |
| 9277 } | 9276 } |
| 9278 if (is_compiletime_const) { | 9277 if (is_compiletime_const) { |
| 9279 primary = new LiteralNode(literal_start, Interpolate(values)); | 9278 primary = new LiteralNode(literal_start, Interpolate(values_list)); |
| 9280 } else { | 9279 } else { |
| 9281 ArgumentListNode* interpolate_arg = | 9280 ArgumentListNode* interpolate_arg = new ArgumentListNode(TokenPos()); |
| 9282 new ArgumentListNode(values->token_pos()); | 9281 ArrayNode* values = new ArrayNode( |
| 9282 TokenPos(), Type::ZoneHandle(Type::ArrayType()), values_list); |
| 9283 interpolate_arg->Add(values); | 9283 interpolate_arg->Add(values); |
| 9284 primary = MakeStaticCall(Symbols::StringBase(), | 9284 primary = MakeStaticCall(Symbols::StringBase(), |
| 9285 PrivateCoreLibName(Symbols::Interpolate()), | 9285 PrivateCoreLibName(Symbols::Interpolate()), |
| 9286 interpolate_arg); | 9286 interpolate_arg); |
| 9287 } | 9287 } |
| 9288 return primary; | 9288 return primary; |
| 9289 } | 9289 } |
| 9290 | 9290 |
| 9291 | 9291 |
| 9292 AstNode* Parser::ParseArgumentDefinitionTest() { | 9292 AstNode* Parser::ParseArgumentDefinitionTest() { |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9778 void Parser::SkipQualIdent() { | 9778 void Parser::SkipQualIdent() { |
| 9779 ASSERT(IsIdentifier()); | 9779 ASSERT(IsIdentifier()); |
| 9780 ConsumeToken(); | 9780 ConsumeToken(); |
| 9781 if (CurrentToken() == Token::kPERIOD) { | 9781 if (CurrentToken() == Token::kPERIOD) { |
| 9782 ConsumeToken(); // Consume the kPERIOD token. | 9782 ConsumeToken(); // Consume the kPERIOD token. |
| 9783 ExpectIdentifier("identifier expected after '.'"); | 9783 ExpectIdentifier("identifier expected after '.'"); |
| 9784 } | 9784 } |
| 9785 } | 9785 } |
| 9786 | 9786 |
| 9787 } // namespace dart | 9787 } // namespace dart |
| OLD | NEW |