Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: runtime/vm/parser.cc

Issue 8318031: Interpolated strings are never considered compile time const (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/language.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698