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

Unified Diff: src/parser.cc

Issue 663683006: Implement ES6 Template Literals (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Even better static error reporting Created 6 years, 1 month 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 | « src/parser.h ('k') | src/preparser.h » ('j') | src/preparser.h » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 7fc5dd0512b4ba73be38148b35a9faaffc63be8a..7bf7541bc81338169d490f35661fa8b0fcae4fa7 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -813,6 +813,7 @@ Parser::Parser(CompilationInfo* info, ParseInfo* parse_info)
set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
set_allow_classes(FLAG_harmony_classes);
set_allow_harmony_object_literals(FLAG_harmony_object_literals);
+ set_allow_harmony_templates(FLAG_harmony_templates);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) {
use_counts_[feature] = 0;
@@ -3907,6 +3908,7 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
reusable_preparser_->set_allow_classes(allow_classes());
reusable_preparser_->set_allow_harmony_object_literals(
allow_harmony_object_literals());
+ reusable_preparser_->set_allow_harmony_templates(allow_harmony_templates());
}
PreParser::PreParseResult result =
reusable_preparser_->PreParseLazyFunction(strict_mode(),
@@ -5025,4 +5027,141 @@ void Parser::ParseOnBackground() {
log_ = NULL;
}
}
+
+
+ParserTraits::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
+ return new (zone()) ParserTraits::TemplateLiteral(zone(), pos);
+}
+
+
+void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) {
+ int pos = scanner()->location().beg_pos;
+ int end = scanner()->location().end_pos - (tail ? 1 : 2);
+ const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory());
+ Literal* cooked = factory()->NewStringLiteral(tv, pos);
+ (*state)->AddTemplateSpan(cooked, end, zone());
+}
+
+
+void Parser::AddTemplateExpression(TemplateLiteralState* state,
+ Expression* expression) {
+ (*state)->AddExpression(expression, zone());
+}
+
+
+Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state,
+ int start, Expression* tag) {
+#define COOKED_STRING(i) cooked_strings->at(i)
rossberg 2014/11/14 12:28:07 Nit: please remove these macros, they don't seem w
+#define POS(i) cooked_strings->at(i)->position()
+#define EXPR(i) expressions->at(i)
+ TemplateLiteral* lit = *state;
+ int pos = lit->position();
+ const ZoneList<Expression*>* cooked_strings = lit->cooked();
+ const ZoneList<Expression*>* expressions = lit->expressions();
+ CHECK(cooked_strings->length() == (expressions->length() + 1));
+
+ if (!tag) {
+ // Build tree of BinaryOps to simplify code-generation
+ Expression* expr = NULL;
+
+ if (expressions->length() == 0) {
+ // Simple case: treat as string literal
+ expr = COOKED_STRING(0);
+ } else {
+ int i;
+ expr = factory()->NewBinaryOperation(Token::ADD,
+ COOKED_STRING(0), EXPR(0), POS(0));
+ for (i = 1; i < expressions->length(); ++i) {
+ expr = factory()->NewBinaryOperation(Token::ADD,
+ expr, factory()->NewBinaryOperation(Token::ADD, COOKED_STRING(i),
+ EXPR(i), POS(i)), POS(i));
rossberg 2014/11/14 12:28:07 Nit: indentation?
+ }
+ expr = factory()->NewBinaryOperation(Token::ADD, expr, COOKED_STRING(i),
+ POS(i));
+ }
+ return expr;
+ } else {
+ ZoneList<Expression*>* raw_strings = TemplateRawStrings(lit);
+ Handle<String> source(String::cast(script()->source()));
+
+ int cooked_idx = function_state_->NextMaterializedLiteralIndex();
+ int raw_idx = function_state_->NextMaterializedLiteralIndex();
+
+ // GetTemplateCallSite
+ ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
+ args->Add(factory()->NewArrayLiteral(
+ const_cast<ZoneList<Expression*>*>(cooked_strings), cooked_idx, pos),
+ zone());
+ args->Add(factory()->NewArrayLiteral(
+ const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos), zone());
+ this->CheckPossibleEvalCall(tag, scope_);
+ Expression* expr = factory()->NewCallRuntime(
rossberg 2014/11/14 12:28:07 Nit: rename from 'expr' to 'call_site'
+ ast_value_factory()->get_template_callsite_string(), NULL, args, start);
+
+ // Call TagFn
+ ZoneList<Expression*>* call_args = new (zone()) ZoneList<Expression*>(
+ expressions->length() + 1, zone());
+ call_args->Add(expr, zone());
+ call_args->AddAll(*expressions, zone());
+ expr = factory()->NewCall(tag, call_args, pos);
+ return expr;
+ }
+#undef COOKED_STRING
+#undef POS
+#undef EXPR
+}
+
+
+ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit) {
+ const ZoneList<int>* lengths = lit->lengths();
+ const ZoneList<Expression*>* cooked_strings = lit->cooked();
+ int total = lengths->length();
+ ZoneList<Expression*>* raw_strings;
+ SmartArrayPointer<char> raw_chars;
+
+ // Given a TemplateLiteral, produce a list of raw strings, used for generating
+ // a CallSite object for a tagged template invocations.
+ //
+ // A raw string will consist of the unescaped characters of a template span,
+ // with end-of-line sequences normalized to U+000A LINE FEEDs, and without
+ // leading or trailing template delimiters.
+ //
+
+ DCHECK(total);
+
+ Handle<String> source(String::cast(script()->source()));
+
+ raw_strings = new (zone()) ZoneList<Expression*>(total, zone());
+
+ for (int index = 0; index < total; ++index) {
+ int span_start = cooked_strings->at(index)->position() + 1;
+ int span_end = lengths->at(index) - 1;
+ int length;
+ int to_index = 0;
+
+ raw_chars = source->ToCString(
+ ALLOW_NULLS, FAST_STRING_TRAVERSAL, span_start, span_end, &length);
+
+ // Normalize raw line-feeds. [U+000D U+000A] (CRLF) and [U+000D] (CR) must
+ // be translated into U+000A (LF).
+ for (int from_index = 0; from_index < length; ++from_index) {
+ char ch = raw_chars[from_index];
+ if (ch == '\r') {
+ if (raw_chars[from_index + 1] == '\n') {
rossberg 2014/11/14 12:28:07 Perhaps add a comment explaining that it is actual
caitp (gmail) 2014/11/14 13:25:18 Hmm, I'm not sure this is guaranteed to be safe, a
+ ++from_index;
+ }
+ ch = '\n';
rossberg 2014/11/14 12:28:07 Nit: put this first.
+ }
+ raw_chars[to_index++] = ch;
+ }
+
+ const AstRawString* raw_str = ast_value_factory()->GetOneByteString(
+ OneByteVector(raw_chars.get(), to_index));
+ Literal* raw_lit = factory()->NewStringLiteral(raw_str, span_start - 1);
+ raw_strings->Add(raw_lit, zone());
+ }
+
+ return raw_strings;
+}
+
} } // namespace v8::internal
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | src/preparser.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698