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

Unified Diff: runtime/vm/parser.cc

Issue 9582040: Re-introduce string concatenation (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 4989)
+++ runtime/vm/parser.cc (working copy)
@@ -7488,37 +7488,74 @@
}
+String& Parser::Interpolate(ArrayNode* values) {
+ const String& class_name =
+ String::Handle(String::NewSymbol(kStringClassName));
+ const Class& cls = Class::Handle(LookupImplClass(class_name));
+ ASSERT(!cls.IsNull());
+ const String& func_name = String::Handle(String::NewSymbol(kInterpolateName));
+ const Function& func =
+ Function::Handle(cls.LookupStaticFunction(func_name));
+ ASSERT(!func.IsNull());
+
+ // Build the array of literal values to interpolate.
+ const Array& value_arr = Array::Handle(Array::New(values->length()));
+ for (int i = 0; i < values->length(); i++) {
+ ASSERT(values->ElementAt(i)->IsLiteralNode());
+ value_arr.SetAt(i, values->ElementAt(i)->AsLiteralNode()->literal());
+ }
+
+ // Build argument array to pass to the interpolation function.
+ GrowableArray<const Object*> interpolate_arg;
+ interpolate_arg.Add(&value_arr);
+ const Array& kNoArgumentNames = Array::Handle();
+
+ // Call interpolation function.
+ String& concatenated = String::ZoneHandle();
+ concatenated ^= DartEntry::InvokeStatic(func,
+ interpolate_arg,
+ kNoArgumentNames);
+ if (concatenated.IsUnhandledException()) {
+ ErrorMsg("Exception thrown in Parser::Interpolate");
+ }
+ concatenated = String::NewSymbol(concatenated);
+ return concatenated;
+}
+
+
// A string literal consists of the concatenation of the next n tokens
// that satisfy the EBNF grammar:
-// literal = kSTRING {{ interpol }+ kSTRING }
+// literal = kSTRING {{ interpol } kSTRING }
// interpol = kINTERPOL_VAR | (kINTERPOL_START expression kINTERPOL_END)
// In other words, the scanner breaks down interpolated strings so that
-// a string literal always begins and ends with a kSTRING token, and
-// there are never two kSTRING tokens next to each other.
+// a string literal always begins and ends with a kSTRING token.
AstNode* Parser::ParseStringLiteral() {
TRACE_PARSER("ParseStringLiteral");
AstNode* primary = NULL;
const intptr_t literal_start = token_index_;
- if ((CurrentToken() == Token::kSTRING) &&
- (LookaheadToken(1) != Token::kINTERPOL_VAR) &&
- (LookaheadToken(1) != Token::kINTERPOL_START)) {
+ ASSERT(CurrentToken() == Token::kSTRING);
+ Token::Kind l1_token = LookaheadToken(1);
+ if ((l1_token != Token::kSTRING) &&
+ (l1_token != Token::kINTERPOL_VAR) &&
+ (l1_token != Token::kINTERPOL_START)) {
// Common case: no interpolation.
primary = new LiteralNode(literal_start, *CurrentLiteral());
ConsumeToken();
return primary;
}
// String interpolation needed.
+ bool is_compiletime_const = true;
ArrayNode* values = new ArrayNode(token_index_, TypeArguments::ZoneHandle());
while (CurrentToken() == Token::kSTRING) {
values->AddElement(new LiteralNode(token_index_, *CurrentLiteral()));
ConsumeToken();
- if ((CurrentToken() != Token::kINTERPOL_VAR) &&
- (CurrentToken() != Token::kINTERPOL_START)) {
- break;
- }
while ((CurrentToken() == Token::kINTERPOL_VAR) ||
(CurrentToken() == Token::kINTERPOL_START)) {
AstNode* expr = NULL;
+ const intptr_t expr_pos = token_index_;
+ // TODO(hausner): Remove the statement below when we allow interpolated
+ // strings to be compile time constants.
+ is_compiletime_const = false;
if (CurrentToken() == Token::kINTERPOL_VAR) {
expr = ResolveVarOrField(token_index_, *CurrentLiteral());
ASSERT(!expr->IsPrimaryNode());
@@ -7529,17 +7566,31 @@
expr = ParseExpr(kAllowConst);
ExpectToken(Token::kINTERPOL_END);
}
+ // Check if this interpolated string is still considered a compile time
+ // constant. If it is we need to evaluate if the current string part is
+ // a constant or not.
+ if (is_compiletime_const) {
+ const Object* const_expr = expr->EvalConstExpr();
+ if (const_expr != NULL) {
+ // Change expr into a literal.
+ expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr));
+ } else {
+ is_compiletime_const = false;
+ }
+ }
values->AddElement(expr);
}
- // A string literal always ends with a kSTRING token.
- ASSERT(CurrentToken() == Token::kSTRING);
}
- ArgumentListNode* interpolate_arg =
- new ArgumentListNode(values->token_index());
- interpolate_arg->Add(values);
- primary = MakeStaticCall(kStringClassName,
- kInterpolateName,
- interpolate_arg);
+ if (is_compiletime_const) {
+ primary = new LiteralNode(literal_start, Interpolate(values));
+ } else {
+ ArgumentListNode* interpolate_arg =
+ new ArgumentListNode(values->token_index());
+ interpolate_arg->Add(values);
+ primary = MakeStaticCall(kStringClassName,
+ kInterpolateName,
+ interpolate_arg);
+ }
return primary;
}
@@ -7857,10 +7908,6 @@
ASSERT(CurrentToken() == Token::kSTRING);
while (CurrentToken() == Token::kSTRING) {
ConsumeToken();
- if ((CurrentToken() != Token::kINTERPOL_VAR) &&
- (CurrentToken() != Token::kINTERPOL_START)) {
- break;
- }
while (true) {
if (CurrentToken() == Token::kINTERPOL_VAR) {
ConsumeToken();
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698