| 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" |
| (...skipping 6532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6543 // Make sure that the instantiator is captured. | 6543 // Make sure that the instantiator is captured. |
| 6544 CaptureReceiver(); | 6544 CaptureReceiver(); |
| 6545 } | 6545 } |
| 6546 new_object = new ConstructorCallNode( | 6546 new_object = new ConstructorCallNode( |
| 6547 new_pos, type_arguments, constructor, arguments); | 6547 new_pos, type_arguments, constructor, arguments); |
| 6548 } | 6548 } |
| 6549 return new_object; | 6549 return new_object; |
| 6550 } | 6550 } |
| 6551 | 6551 |
| 6552 | 6552 |
| 6553 String& Parser::Interpolate(ArrayNode* values) { | |
| 6554 const String& class_name = | |
| 6555 String::Handle(String::NewSymbol(kStringClassName)); | |
| 6556 const Class& cls = Class::Handle(LookupImplClass(class_name)); | |
| 6557 ASSERT(!cls.IsNull()); | |
| 6558 const String& func_name = String::Handle(String::NewSymbol(kInterpolateName)); | |
| 6559 const Function& func = | |
| 6560 Function::Handle(cls.LookupStaticFunction(func_name)); | |
| 6561 ASSERT(!func.IsNull()); | |
| 6562 | |
| 6563 // Build the array of literal values to interpolate. | |
| 6564 const Array& value_arr = Array::Handle(Array::New(values->length())); | |
| 6565 for (int i = 0; i < values->length(); i++) { | |
| 6566 ASSERT(values->ElementAt(i)->IsLiteralNode()); | |
| 6567 value_arr.SetAt(i, values->ElementAt(i)->AsLiteralNode()->literal()); | |
| 6568 } | |
| 6569 | |
| 6570 // Build argument array to pass to the interpolation function. | |
| 6571 GrowableArray<const Object*> interpolate_arg; | |
| 6572 interpolate_arg.Add(&value_arr); | |
| 6573 const Array& kNoArgumentNames = Array::Handle(); | |
| 6574 | |
| 6575 // Call interpolation function. | |
| 6576 String& concatenated = String::ZoneHandle(); | |
| 6577 concatenated ^= DartEntry::InvokeStatic(func, | |
| 6578 interpolate_arg, | |
| 6579 kNoArgumentNames); | |
| 6580 if (concatenated.IsUnhandledException()) { | |
| 6581 ErrorMsg("Exception thrown in Parser::Interpolate"); | |
| 6582 } | |
| 6583 concatenated = String::NewSymbol(concatenated); | |
| 6584 return concatenated; | |
| 6585 } | |
| 6586 | |
| 6587 | |
| 6588 // A string literal consists of the concatenation of the next n tokens | 6553 // A string literal consists of the concatenation of the next n tokens |
| 6589 // that satisfy the EBNF grammar: | 6554 // that satisfy the EBNF grammar: |
| 6590 // literal = kSTRING {{ interpol }+ kSTRING } | 6555 // literal = kSTRING {{ interpol }+ kSTRING } |
| 6591 // interpol = kINTERPOL_VAR | (kINTERPOL_START expression kINTERPOL_END) | 6556 // interpol = kINTERPOL_VAR | (kINTERPOL_START expression kINTERPOL_END) |
| 6592 // In other words, the scanner breaks down interpolated strings so that | 6557 // In other words, the scanner breaks down interpolated strings so that |
| 6593 // a string literal always begins and ends with a kSTRING token, and | 6558 // a string literal always begins and ends with a kSTRING token, and |
| 6594 // there are never two kSTRING tokens next to each other. | 6559 // there are never two kSTRING tokens next to each other. |
| 6595 AstNode* Parser::ParseStringLiteral() { | 6560 AstNode* Parser::ParseStringLiteral() { |
| 6596 AstNode* primary = NULL; | 6561 AstNode* primary = NULL; |
| 6597 intptr_t literal_start = token_index_; | 6562 intptr_t literal_start = token_index_; |
| 6598 if ((CurrentToken() == Token::kSTRING) && | 6563 if ((CurrentToken() == Token::kSTRING) && |
| 6599 (LookaheadToken(1) != Token::kINTERPOL_VAR) && | 6564 (LookaheadToken(1) != Token::kINTERPOL_VAR) && |
| 6600 (LookaheadToken(1) != Token::kINTERPOL_START)) { | 6565 (LookaheadToken(1) != Token::kINTERPOL_START)) { |
| 6601 // Common case: no interpolation. | 6566 // Common case: no interpolation. |
| 6602 primary = new LiteralNode(literal_start, *CurrentLiteral()); | 6567 primary = new LiteralNode(literal_start, *CurrentLiteral()); |
| 6603 ConsumeToken(); | 6568 ConsumeToken(); |
| 6604 return primary; | 6569 return primary; |
| 6605 } | 6570 } |
| 6606 // String interpolation needed. | 6571 // String interpolation needed. |
| 6607 bool is_compiletime_const = true; | |
| 6608 ArrayNode* values = new ArrayNode(token_index_, TypeArguments::ZoneHandle()); | 6572 ArrayNode* values = new ArrayNode(token_index_, TypeArguments::ZoneHandle()); |
| 6609 GrowableArray<const Object*> arg_values; | 6573 GrowableArray<const Object*> arg_values; |
| 6610 while (CurrentToken() == Token::kSTRING) { | 6574 while (CurrentToken() == Token::kSTRING) { |
| 6611 values->AddElement(new LiteralNode(token_index_, *CurrentLiteral())); | 6575 values->AddElement(new LiteralNode(token_index_, *CurrentLiteral())); |
| 6612 ConsumeToken(); | 6576 ConsumeToken(); |
| 6613 if ((CurrentToken() != Token::kINTERPOL_VAR) && | 6577 if ((CurrentToken() != Token::kINTERPOL_VAR) && |
| 6614 (CurrentToken() != Token::kINTERPOL_START)) { | 6578 (CurrentToken() != Token::kINTERPOL_START)) { |
| 6615 break; | 6579 break; |
| 6616 } | 6580 } |
| 6617 while ((CurrentToken() == Token::kINTERPOL_VAR) || | 6581 while ((CurrentToken() == Token::kINTERPOL_VAR) || |
| 6618 (CurrentToken() == Token::kINTERPOL_START)) { | 6582 (CurrentToken() == Token::kINTERPOL_START)) { |
| 6619 AstNode* expr = NULL; | 6583 AstNode* expr = NULL; |
| 6620 const intptr_t expr_pos = token_index_; | |
| 6621 if (CurrentToken() == Token::kINTERPOL_VAR) { | 6584 if (CurrentToken() == Token::kINTERPOL_VAR) { |
| 6622 expr = ResolveVarOrField(token_index_, *CurrentLiteral()); | 6585 expr = ResolveVarOrField(token_index_, *CurrentLiteral()); |
| 6623 ASSERT(!expr->IsPrimaryNode()); | 6586 ASSERT(!expr->IsPrimaryNode()); |
| 6624 ConsumeToken(); | 6587 ConsumeToken(); |
| 6625 } else { | 6588 } else { |
| 6626 ASSERT(CurrentToken() == Token::kINTERPOL_START); | 6589 ASSERT(CurrentToken() == Token::kINTERPOL_START); |
| 6627 ConsumeToken(); | 6590 ConsumeToken(); |
| 6628 expr = ParseExpr(kAllowConst); | 6591 expr = ParseExpr(kAllowConst); |
| 6629 ExpectToken(Token::kINTERPOL_END); | 6592 ExpectToken(Token::kINTERPOL_END); |
| 6630 } | 6593 } |
| 6631 | |
| 6632 // Check if this interpolated string is still considered a compile time | |
| 6633 // constant. If it is we need to evaluate if the current string part is | |
| 6634 // a constant or not. | |
| 6635 if (is_compiletime_const) { | |
| 6636 const Object* const_expr = expr->EvalConstExpr(); | |
| 6637 if (const_expr != NULL) { | |
| 6638 // Change expr into a literal. | |
| 6639 expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr)); | |
| 6640 } else { | |
| 6641 is_compiletime_const = false; | |
| 6642 } | |
| 6643 } | |
| 6644 values->AddElement(expr); | 6594 values->AddElement(expr); |
| 6645 } | 6595 } |
| 6646 // A string literal always ends with a kSTRING token. | 6596 // A string literal always ends with a kSTRING token. |
| 6647 ASSERT(CurrentToken() == Token::kSTRING); | 6597 ASSERT(CurrentToken() == Token::kSTRING); |
| 6648 } | 6598 } |
| 6649 if (is_compiletime_const) { | 6599 ArgumentListNode* interpolate_arg = |
| 6650 primary = new LiteralNode(literal_start, Interpolate(values)); | 6600 new ArgumentListNode(values->token_index()); |
| 6651 } else { | 6601 interpolate_arg->Add(values); |
| 6652 ArgumentListNode* interpolate_arg = | 6602 primary = MakeStaticCall(kStringClassName, |
| 6653 new ArgumentListNode(values->token_index()); | 6603 kInterpolateName, |
| 6654 interpolate_arg->Add(values); | 6604 interpolate_arg); |
| 6655 primary = MakeStaticCall(kStringClassName, | |
| 6656 kInterpolateName, | |
| 6657 interpolate_arg); | |
| 6658 } | |
| 6659 return primary; | 6605 return primary; |
| 6660 } | 6606 } |
| 6661 | 6607 |
| 6662 | 6608 |
| 6663 AstNode* Parser::ParsePrimary() { | 6609 AstNode* Parser::ParsePrimary() { |
| 6664 TRACE_PARSER("ParsePrimary"); | 6610 TRACE_PARSER("ParsePrimary"); |
| 6665 AstNode* primary = NULL; | 6611 AstNode* primary = NULL; |
| 6666 if (IsFunctionLiteral()) { | 6612 if (IsFunctionLiteral()) { |
| 6667 // The name of a literal function is visible from inside the function, but | 6613 // The name of a literal function is visible from inside the function, but |
| 6668 // must not collide with names in the scope declaring the literal. | 6614 // must not collide with names in the scope declaring the literal. |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7034 } | 6980 } |
| 7035 | 6981 |
| 7036 | 6982 |
| 7037 void Parser::SkipNestedExpr() { | 6983 void Parser::SkipNestedExpr() { |
| 7038 const bool saved_mode = SetAllowFunctionLiterals(true); | 6984 const bool saved_mode = SetAllowFunctionLiterals(true); |
| 7039 SkipExpr(); | 6985 SkipExpr(); |
| 7040 SetAllowFunctionLiterals(saved_mode); | 6986 SetAllowFunctionLiterals(saved_mode); |
| 7041 } | 6987 } |
| 7042 | 6988 |
| 7043 } // namespace dart | 6989 } // namespace dart |
| OLD | NEW |