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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | src/preparser.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 pre_parse_timer_(NULL) { 806 pre_parse_timer_(NULL) {
807 DCHECK(!script().is_null() || info->source_stream() != NULL); 807 DCHECK(!script().is_null() || info->source_stream() != NULL);
808 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); 808 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
809 set_allow_modules(!info->is_native() && FLAG_harmony_modules); 809 set_allow_modules(!info->is_native() && FLAG_harmony_modules);
810 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native()); 810 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native());
811 set_allow_lazy(false); // Must be explicitly enabled. 811 set_allow_lazy(false); // Must be explicitly enabled.
812 set_allow_arrow_functions(FLAG_harmony_arrow_functions); 812 set_allow_arrow_functions(FLAG_harmony_arrow_functions);
813 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); 813 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
814 set_allow_classes(FLAG_harmony_classes); 814 set_allow_classes(FLAG_harmony_classes);
815 set_allow_harmony_object_literals(FLAG_harmony_object_literals); 815 set_allow_harmony_object_literals(FLAG_harmony_object_literals);
816 set_allow_harmony_templates(FLAG_harmony_templates);
816 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; 817 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
817 ++feature) { 818 ++feature) {
818 use_counts_[feature] = 0; 819 use_counts_[feature] = 0;
819 } 820 }
820 if (info->ast_value_factory() == NULL) { 821 if (info->ast_value_factory() == NULL) {
821 // info takes ownership of AstValueFactory. 822 // info takes ownership of AstValueFactory.
822 info->SetAstValueFactory( 823 info->SetAstValueFactory(
823 new AstValueFactory(zone(), parse_info->hash_seed)); 824 new AstValueFactory(zone(), parse_info->hash_seed));
824 } 825 }
825 } 826 }
(...skipping 3074 matching lines...) Expand 10 before | Expand all | Expand 10 after
3900 reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping()); 3901 reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
3901 reusable_preparser_->set_allow_modules(allow_modules()); 3902 reusable_preparser_->set_allow_modules(allow_modules());
3902 reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax()); 3903 reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax());
3903 reusable_preparser_->set_allow_lazy(true); 3904 reusable_preparser_->set_allow_lazy(true);
3904 reusable_preparser_->set_allow_arrow_functions(allow_arrow_functions()); 3905 reusable_preparser_->set_allow_arrow_functions(allow_arrow_functions());
3905 reusable_preparser_->set_allow_harmony_numeric_literals( 3906 reusable_preparser_->set_allow_harmony_numeric_literals(
3906 allow_harmony_numeric_literals()); 3907 allow_harmony_numeric_literals());
3907 reusable_preparser_->set_allow_classes(allow_classes()); 3908 reusable_preparser_->set_allow_classes(allow_classes());
3908 reusable_preparser_->set_allow_harmony_object_literals( 3909 reusable_preparser_->set_allow_harmony_object_literals(
3909 allow_harmony_object_literals()); 3910 allow_harmony_object_literals());
3911 reusable_preparser_->set_allow_harmony_templates(allow_harmony_templates());
3910 } 3912 }
3911 PreParser::PreParseResult result = 3913 PreParser::PreParseResult result =
3912 reusable_preparser_->PreParseLazyFunction(strict_mode(), 3914 reusable_preparser_->PreParseLazyFunction(strict_mode(),
3913 is_generator(), 3915 is_generator(),
3914 logger); 3916 logger);
3915 if (pre_parse_timer_ != NULL) { 3917 if (pre_parse_timer_ != NULL) {
3916 pre_parse_timer_->Stop(); 3918 pre_parse_timer_->Stop();
3917 } 3919 }
3918 return result; 3920 return result;
3919 } 3921 }
(...skipping 1098 matching lines...) Expand 10 before | Expand all | Expand 10 after
5018 info()->SetFunction(result); 5020 info()->SetFunction(result);
5019 5021
5020 // We cannot internalize on a background thread; a foreground task will take 5022 // We cannot internalize on a background thread; a foreground task will take
5021 // care of calling Parser::Internalize just before compilation. 5023 // care of calling Parser::Internalize just before compilation.
5022 5024
5023 if (compile_options() == ScriptCompiler::kProduceParserCache) { 5025 if (compile_options() == ScriptCompiler::kProduceParserCache) {
5024 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); 5026 if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
5025 log_ = NULL; 5027 log_ = NULL;
5026 } 5028 }
5027 } 5029 }
5030
5031
5032 ParserTraits::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
5033 return new (zone()) ParserTraits::TemplateLiteral(zone(), pos);
5034 }
5035
5036
5037 void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) {
5038 int pos = scanner()->location().beg_pos;
5039 int end = scanner()->location().end_pos - (tail ? 1 : 2);
5040 const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory());
5041 Literal* cooked = factory()->NewStringLiteral(tv, pos);
5042 (*state)->AddTemplateSpan(cooked, end, zone());
5043 }
5044
5045
5046 void Parser::AddTemplateExpression(TemplateLiteralState* state,
5047 Expression* expression) {
5048 (*state)->AddExpression(expression, zone());
5049 }
5050
5051
5052 Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state,
5053 int start, Expression* tag) {
5054 #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
5055 #define POS(i) cooked_strings->at(i)->position()
5056 #define EXPR(i) expressions->at(i)
5057 TemplateLiteral* lit = *state;
5058 int pos = lit->position();
5059 const ZoneList<Expression*>* cooked_strings = lit->cooked();
5060 const ZoneList<Expression*>* expressions = lit->expressions();
5061 CHECK(cooked_strings->length() == (expressions->length() + 1));
5062
5063 if (!tag) {
5064 // Build tree of BinaryOps to simplify code-generation
5065 Expression* expr = NULL;
5066
5067 if (expressions->length() == 0) {
5068 // Simple case: treat as string literal
5069 expr = COOKED_STRING(0);
5070 } else {
5071 int i;
5072 expr = factory()->NewBinaryOperation(Token::ADD,
5073 COOKED_STRING(0), EXPR(0), POS(0));
5074 for (i = 1; i < expressions->length(); ++i) {
5075 expr = factory()->NewBinaryOperation(Token::ADD,
5076 expr, factory()->NewBinaryOperation(Token::ADD, COOKED_STRING(i),
5077 EXPR(i), POS(i)), POS(i));
rossberg 2014/11/14 12:28:07 Nit: indentation?
5078 }
5079 expr = factory()->NewBinaryOperation(Token::ADD, expr, COOKED_STRING(i),
5080 POS(i));
5081 }
5082 return expr;
5083 } else {
5084 ZoneList<Expression*>* raw_strings = TemplateRawStrings(lit);
5085 Handle<String> source(String::cast(script()->source()));
5086
5087 int cooked_idx = function_state_->NextMaterializedLiteralIndex();
5088 int raw_idx = function_state_->NextMaterializedLiteralIndex();
5089
5090 // GetTemplateCallSite
5091 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
5092 args->Add(factory()->NewArrayLiteral(
5093 const_cast<ZoneList<Expression*>*>(cooked_strings), cooked_idx, pos),
5094 zone());
5095 args->Add(factory()->NewArrayLiteral(
5096 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos), zone());
5097 this->CheckPossibleEvalCall(tag, scope_);
5098 Expression* expr = factory()->NewCallRuntime(
rossberg 2014/11/14 12:28:07 Nit: rename from 'expr' to 'call_site'
5099 ast_value_factory()->get_template_callsite_string(), NULL, args, start);
5100
5101 // Call TagFn
5102 ZoneList<Expression*>* call_args = new (zone()) ZoneList<Expression*>(
5103 expressions->length() + 1, zone());
5104 call_args->Add(expr, zone());
5105 call_args->AddAll(*expressions, zone());
5106 expr = factory()->NewCall(tag, call_args, pos);
5107 return expr;
5108 }
5109 #undef COOKED_STRING
5110 #undef POS
5111 #undef EXPR
5112 }
5113
5114
5115 ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit) {
5116 const ZoneList<int>* lengths = lit->lengths();
5117 const ZoneList<Expression*>* cooked_strings = lit->cooked();
5118 int total = lengths->length();
5119 ZoneList<Expression*>* raw_strings;
5120 SmartArrayPointer<char> raw_chars;
5121
5122 // Given a TemplateLiteral, produce a list of raw strings, used for generating
5123 // a CallSite object for a tagged template invocations.
5124 //
5125 // A raw string will consist of the unescaped characters of a template span,
5126 // with end-of-line sequences normalized to U+000A LINE FEEDs, and without
5127 // leading or trailing template delimiters.
5128 //
5129
5130 DCHECK(total);
5131
5132 Handle<String> source(String::cast(script()->source()));
5133
5134 raw_strings = new (zone()) ZoneList<Expression*>(total, zone());
5135
5136 for (int index = 0; index < total; ++index) {
5137 int span_start = cooked_strings->at(index)->position() + 1;
5138 int span_end = lengths->at(index) - 1;
5139 int length;
5140 int to_index = 0;
5141
5142 raw_chars = source->ToCString(
5143 ALLOW_NULLS, FAST_STRING_TRAVERSAL, span_start, span_end, &length);
5144
5145 // Normalize raw line-feeds. [U+000D U+000A] (CRLF) and [U+000D] (CR) must
5146 // be translated into U+000A (LF).
5147 for (int from_index = 0; from_index < length; ++from_index) {
5148 char ch = raw_chars[from_index];
5149 if (ch == '\r') {
5150 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
5151 ++from_index;
5152 }
5153 ch = '\n';
rossberg 2014/11/14 12:28:07 Nit: put this first.
5154 }
5155 raw_chars[to_index++] = ch;
5156 }
5157
5158 const AstRawString* raw_str = ast_value_factory()->GetOneByteString(
5159 OneByteVector(raw_chars.get(), to_index));
5160 Literal* raw_lit = factory()->NewStringLiteral(raw_str, span_start - 1);
5161 raw_strings->Add(raw_lit, zone());
5162 }
5163
5164 return raw_strings;
5165 }
5166
5028 } } // namespace v8::internal 5167 } } // namespace v8::internal
OLDNEW
« 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