Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 DCHECK(info_->cached_data() != NULL); | 258 DCHECK(info_->cached_data() != NULL); |
| 259 if (compile_options() == ScriptCompiler::kConsumeParserCache) { | 259 if (compile_options() == ScriptCompiler::kConsumeParserCache) { |
| 260 cached_parse_data_ = ParseData::FromCachedData(*info_->cached_data()); | 260 cached_parse_data_ = ParseData::FromCachedData(*info_->cached_data()); |
| 261 } | 261 } |
| 262 } | 262 } |
| 263 } | 263 } |
| 264 | 264 |
| 265 | 265 |
| 266 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) { | 266 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) { |
| 267 DCHECK(ast_value_factory()); | 267 DCHECK(ast_value_factory()); |
| 268 DCHECK(scope_type != MODULE_SCOPE || allow_harmony_modules()); | |
| 268 Scope* result = new (zone()) | 269 Scope* result = new (zone()) |
| 269 Scope(isolate(), zone(), parent, scope_type, ast_value_factory()); | 270 Scope(isolate(), zone(), parent, scope_type, ast_value_factory()); |
| 270 result->Initialize(); | 271 result->Initialize(); |
| 271 return result; | 272 return result; |
| 272 } | 273 } |
| 273 | 274 |
| 274 | 275 |
| 275 FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope, | 276 FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope, |
| 276 int pos, int end_pos) { | 277 int pos, int end_pos) { |
| 277 int materialized_literal_count = -1; | 278 int materialized_literal_count = -1; |
| (...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 927 | 928 |
| 928 // Enters 'scope'. | 929 // Enters 'scope'. |
| 929 AstNodeFactory function_factory(ast_value_factory()); | 930 AstNodeFactory function_factory(ast_value_factory()); |
| 930 FunctionState function_state(&function_state_, &scope_, *scope, | 931 FunctionState function_state(&function_state_, &scope_, *scope, |
| 931 &function_factory); | 932 &function_factory); |
| 932 | 933 |
| 933 scope_->SetStrictMode(info->strict_mode()); | 934 scope_->SetStrictMode(info->strict_mode()); |
| 934 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); | 935 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); |
| 935 bool ok = true; | 936 bool ok = true; |
| 936 int beg_pos = scanner()->location().beg_pos; | 937 int beg_pos = scanner()->location().beg_pos; |
| 937 ParseSourceElements(body, Token::EOS, info->is_eval(), true, eval_scope, | 938 if (info->is_module()) { |
| 938 &ok); | 939 DCHECK(allow_harmony_modules()); |
| 940 Module* module = ParseModule(&ok); | |
| 941 if (ok) { | |
| 942 // TODO(adamk): Do something with returned Module | |
| 943 CHECK(module); | |
| 944 body->Add(factory()->NewEmptyStatement(RelocInfo::kNoPosition), zone()); | |
| 945 } | |
| 946 } else { | |
| 947 ParseStatementList(body, Token::EOS, info->is_eval(), eval_scope, &ok); | |
| 948 } | |
| 939 | 949 |
| 940 if (ok && strict_mode() == STRICT) { | 950 if (ok && strict_mode() == STRICT) { |
| 941 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); | 951 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); |
| 942 } | 952 } |
| 943 | 953 |
| 944 if (ok && allow_harmony_scoping() && strict_mode() == STRICT) { | 954 if (ok && allow_harmony_scoping() && strict_mode() == STRICT) { |
| 945 CheckConflictingVarDeclarations(scope_, &ok); | 955 CheckConflictingVarDeclarations(scope_, &ok); |
| 946 } | 956 } |
| 947 | 957 |
| 948 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { | 958 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1073 DCHECK(target_stack_ == NULL); | 1083 DCHECK(target_stack_ == NULL); |
| 1074 | 1084 |
| 1075 if (result != NULL) { | 1085 if (result != NULL) { |
| 1076 Handle<String> inferred_name(shared_info->inferred_name()); | 1086 Handle<String> inferred_name(shared_info->inferred_name()); |
| 1077 result->set_inferred_name(inferred_name); | 1087 result->set_inferred_name(inferred_name); |
| 1078 } | 1088 } |
| 1079 return result; | 1089 return result; |
| 1080 } | 1090 } |
| 1081 | 1091 |
| 1082 | 1092 |
| 1083 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, | 1093 void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token, |
| 1084 int end_token, bool is_eval, bool is_global, | 1094 bool is_eval, Scope** eval_scope, bool* ok) { |
| 1085 Scope** eval_scope, bool* ok) { | 1095 // StatementList :: |
| 1086 // SourceElements :: | 1096 // (StatementListItem)* <end_token> |
| 1087 // (ModuleElement)* <end_token> | |
| 1088 | 1097 |
| 1089 // Allocate a target stack to use for this set of source | 1098 // Allocate a target stack to use for this set of source |
| 1090 // elements. This way, all scripts and functions get their own | 1099 // elements. This way, all scripts and functions get their own |
| 1091 // target stack thus avoiding illegal breaks and continues across | 1100 // target stack thus avoiding illegal breaks and continues across |
| 1092 // functions. | 1101 // functions. |
| 1093 TargetScope scope(&this->target_stack_); | 1102 TargetScope scope(&this->target_stack_); |
| 1094 | 1103 |
| 1095 DCHECK(processor != NULL); | 1104 DCHECK(body != NULL); |
| 1096 bool directive_prologue = true; // Parsing directive prologue. | 1105 bool directive_prologue = true; // Parsing directive prologue. |
| 1097 | 1106 |
| 1098 while (peek() != end_token) { | 1107 while (peek() != end_token) { |
| 1099 if (directive_prologue && peek() != Token::STRING) { | 1108 if (directive_prologue && peek() != Token::STRING) { |
| 1100 directive_prologue = false; | 1109 directive_prologue = false; |
| 1101 } | 1110 } |
| 1102 | 1111 |
| 1103 Scanner::Location token_loc = scanner()->peek_location(); | 1112 Scanner::Location token_loc = scanner()->peek_location(); |
| 1104 Statement* stat; | 1113 Statement* stat = ParseStatementListItem(CHECK_OK); |
| 1105 if (is_global && !is_eval) { | |
| 1106 stat = ParseModuleElement(NULL, CHECK_OK); | |
| 1107 } else { | |
| 1108 stat = ParseBlockElement(NULL, CHECK_OK); | |
| 1109 } | |
| 1110 if (stat == NULL || stat->IsEmpty()) { | 1114 if (stat == NULL || stat->IsEmpty()) { |
| 1111 directive_prologue = false; // End of directive prologue. | 1115 directive_prologue = false; // End of directive prologue. |
| 1112 continue; | 1116 continue; |
| 1113 } | 1117 } |
| 1114 | 1118 |
| 1115 if (directive_prologue) { | 1119 if (directive_prologue) { |
| 1116 // A shot at a directive. | 1120 // A shot at a directive. |
| 1117 ExpressionStatement* e_stat; | 1121 ExpressionStatement* e_stat; |
| 1118 Literal* literal; | 1122 Literal* literal; |
| 1119 // Still processing directive prologue? | 1123 // Still processing directive prologue? |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1155 // incremented after parsing is done. | 1159 // incremented after parsing is done. |
| 1156 ++use_counts_[v8::Isolate::kUseAsm]; | 1160 ++use_counts_[v8::Isolate::kUseAsm]; |
| 1157 scope_->SetAsmModule(); | 1161 scope_->SetAsmModule(); |
| 1158 } | 1162 } |
| 1159 } else { | 1163 } else { |
| 1160 // End of the directive prologue. | 1164 // End of the directive prologue. |
| 1161 directive_prologue = false; | 1165 directive_prologue = false; |
| 1162 } | 1166 } |
| 1163 } | 1167 } |
| 1164 | 1168 |
| 1165 processor->Add(stat, zone()); | 1169 body->Add(stat, zone()); |
| 1166 } | 1170 } |
| 1167 | 1171 |
| 1168 return 0; | 1172 return 0; |
| 1169 } | 1173 } |
| 1170 | 1174 |
| 1171 | 1175 |
| 1172 Statement* Parser::ParseModuleElement(ZoneList<const AstRawString*>* labels, | 1176 Statement* Parser::ParseStatementListItem(bool* ok) { |
| 1173 bool* ok) { | 1177 // (Ecma 262 6th Edition, 13.1): |
| 1174 // (Ecma 262 5th Edition, clause 14): | 1178 // StatementListItem: |
| 1175 // SourceElement: | |
| 1176 // Statement | 1179 // Statement |
| 1177 // FunctionDeclaration | 1180 // Declaration |
| 1178 // | |
| 1179 // In harmony mode we allow additionally the following productions | |
| 1180 // ModuleElement: | |
| 1181 // LetDeclaration | |
| 1182 // ConstDeclaration | |
| 1183 // ModuleDeclaration | |
| 1184 // ImportDeclaration | |
| 1185 // ExportDeclaration | |
| 1186 // GeneratorDeclaration | |
| 1187 | 1181 |
| 1188 switch (peek()) { | 1182 switch (peek()) { |
| 1189 case Token::FUNCTION: | 1183 case Token::FUNCTION: |
| 1190 return ParseFunctionDeclaration(NULL, ok); | 1184 return ParseFunctionDeclaration(NULL, ok); |
| 1191 case Token::CLASS: | 1185 case Token::CLASS: |
| 1192 return ParseClassDeclaration(NULL, ok); | 1186 return ParseClassDeclaration(NULL, ok); |
| 1187 case Token::CONST: | |
| 1188 case Token::VAR: | |
| 1189 return ParseVariableStatement(kStatementListItem, NULL, ok); | |
| 1190 case Token::LET: | |
| 1191 DCHECK(allow_harmony_scoping()); | |
| 1192 if (strict_mode() == STRICT) { | |
| 1193 return ParseVariableStatement(kStatementListItem, NULL, ok); | |
| 1194 } | |
| 1195 // Fall through. | |
| 1196 default: | |
| 1197 return ParseStatement(NULL, ok); | |
| 1198 } | |
| 1199 } | |
| 1200 | |
| 1201 | |
| 1202 Statement* Parser::ParseModuleItem(bool* ok) { | |
| 1203 // (Ecma 262 6th Edition, 15.2): | |
| 1204 // ModuleItem : | |
| 1205 // ImportDeclaration | |
| 1206 // ExportDeclaration | |
| 1207 // StatementListItem | |
| 1208 | |
| 1209 switch (peek()) { | |
| 1193 case Token::IMPORT: | 1210 case Token::IMPORT: |
| 1194 return ParseImportDeclaration(ok); | 1211 return ParseImportDeclaration(ok); |
| 1195 case Token::EXPORT: | 1212 case Token::EXPORT: |
| 1196 return ParseExportDeclaration(ok); | 1213 return ParseExportDeclaration(ok); |
| 1197 case Token::CONST: | 1214 default: |
| 1198 return ParseVariableStatement(kModuleElement, NULL, ok); | 1215 return ParseStatementListItem(ok); |
| 1199 case Token::LET: | |
| 1200 DCHECK(allow_harmony_scoping()); | |
| 1201 if (strict_mode() == STRICT) { | |
| 1202 return ParseVariableStatement(kModuleElement, NULL, ok); | |
| 1203 } | |
| 1204 // Fall through. | |
| 1205 default: { | |
| 1206 Statement* stmt = ParseStatement(labels, CHECK_OK); | |
| 1207 // Handle 'module' as a context-sensitive keyword. | |
| 1208 if (FLAG_harmony_modules && | |
| 1209 peek() == Token::IDENTIFIER && | |
| 1210 !scanner()->HasAnyLineTerminatorBeforeNext() && | |
| 1211 stmt != NULL) { | |
| 1212 ExpressionStatement* estmt = stmt->AsExpressionStatement(); | |
| 1213 if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL && | |
| 1214 estmt->expression()->AsVariableProxy()->raw_name() == | |
| 1215 ast_value_factory()->module_string() && | |
| 1216 !scanner()->literal_contains_escapes()) { | |
| 1217 return ParseModuleDeclaration(NULL, ok); | |
| 1218 } | |
| 1219 } | |
| 1220 return stmt; | |
| 1221 } | |
| 1222 } | 1216 } |
| 1223 } | 1217 } |
| 1224 | 1218 |
| 1225 | 1219 |
| 1226 Statement* Parser::ParseModuleDeclaration(ZoneList<const AstRawString*>* names, | |
| 1227 bool* ok) { | |
| 1228 // ModuleDeclaration: | |
| 1229 // 'module' Identifier Module | |
| 1230 | |
| 1231 int pos = peek_position(); | |
| 1232 const AstRawString* name = | |
| 1233 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); | |
| 1234 | |
| 1235 #ifdef DEBUG | |
| 1236 if (FLAG_print_interface_details) | |
| 1237 PrintF("# Module %.*s ", name->length(), name->raw_data()); | |
| 1238 #endif | |
| 1239 | |
| 1240 Module* module = ParseModule(CHECK_OK); | |
| 1241 VariableProxy* proxy = NewUnresolved(name, MODULE, module->interface()); | |
| 1242 Declaration* declaration = | |
| 1243 factory()->NewModuleDeclaration(proxy, module, scope_, pos); | |
| 1244 Declare(declaration, true, CHECK_OK); | |
| 1245 | |
| 1246 #ifdef DEBUG | |
| 1247 if (FLAG_print_interface_details) | |
| 1248 PrintF("# Module %.*s ", name->length(), name->raw_data()); | |
| 1249 if (FLAG_print_interfaces) { | |
| 1250 PrintF("module %.*s: ", name->length(), name->raw_data()); | |
| 1251 module->interface()->Print(); | |
| 1252 } | |
| 1253 #endif | |
| 1254 | |
| 1255 if (names) names->Add(name, zone()); | |
| 1256 if (module->body() == NULL) | |
| 1257 return factory()->NewEmptyStatement(pos); | |
| 1258 else | |
| 1259 return factory()->NewModuleStatement(proxy, module->body(), pos); | |
| 1260 } | |
| 1261 | |
| 1262 | |
| 1263 Module* Parser::ParseModule(bool* ok) { | 1220 Module* Parser::ParseModule(bool* ok) { |
| 1264 // Module: | 1221 // (Ecma 262 6th Edition, 15.2): |
| 1265 // '{' ModuleElement '}' | 1222 // Module : |
| 1266 // '=' ModulePath ';' | 1223 // ModuleBody? |
| 1267 // 'at' String ';' | 1224 // |
| 1268 | 1225 // ModuleBody : |
| 1269 switch (peek()) { | 1226 // ModuleItem* |
| 1270 case Token::LBRACE: | |
| 1271 return ParseModuleLiteral(ok); | |
| 1272 | |
| 1273 case Token::ASSIGN: { | |
| 1274 Expect(Token::ASSIGN, CHECK_OK); | |
| 1275 Module* result = ParseModulePath(CHECK_OK); | |
| 1276 ExpectSemicolon(CHECK_OK); | |
| 1277 return result; | |
| 1278 } | |
| 1279 | |
| 1280 default: { | |
| 1281 ExpectContextualKeyword(CStrVector("at"), CHECK_OK); | |
| 1282 Module* result = ParseModuleUrl(CHECK_OK); | |
| 1283 ExpectSemicolon(CHECK_OK); | |
| 1284 return result; | |
| 1285 } | |
| 1286 } | |
| 1287 } | |
| 1288 | |
| 1289 | |
| 1290 Module* Parser::ParseModuleLiteral(bool* ok) { | |
| 1291 // Module: | |
| 1292 // '{' ModuleElement '}' | |
| 1293 | 1227 |
| 1294 int pos = peek_position(); | 1228 int pos = peek_position(); |
| 1295 // Construct block expecting 16 statements. | 1229 // Construct block expecting 16 statements. |
| 1296 Block* body = factory()->NewBlock(NULL, 16, false, RelocInfo::kNoPosition); | 1230 Block* body = factory()->NewBlock(NULL, 16, false, RelocInfo::kNoPosition); |
| 1297 #ifdef DEBUG | 1231 #ifdef DEBUG |
| 1298 if (FLAG_print_interface_details) PrintF("# Literal "); | 1232 if (FLAG_print_interface_details) PrintF("# Literal "); |
| 1299 #endif | 1233 #endif |
| 1300 Scope* scope = NewScope(scope_, MODULE_SCOPE); | 1234 Scope* scope = NewScope(scope_, MODULE_SCOPE); |
| 1301 | 1235 |
| 1302 Expect(Token::LBRACE, CHECK_OK); | |
| 1303 scope->set_start_position(scanner()->location().beg_pos); | 1236 scope->set_start_position(scanner()->location().beg_pos); |
| 1304 scope->SetStrictMode(STRICT); | 1237 scope->SetStrictMode(STRICT); |
| 1305 | 1238 |
| 1306 { | 1239 { |
| 1307 BlockState block_state(&scope_, scope); | 1240 BlockState block_state(&scope_, scope); |
| 1308 Target target(&this->target_stack_, body); | 1241 Target target(&this->target_stack_, body); |
| 1309 | 1242 |
| 1310 while (peek() != Token::RBRACE) { | 1243 while (peek() != Token::EOS) { |
| 1311 Statement* stat = ParseModuleElement(NULL, CHECK_OK); | 1244 Statement* stat = ParseModuleItem(CHECK_OK); |
| 1312 if (stat && !stat->IsEmpty()) { | 1245 if (stat && !stat->IsEmpty()) { |
| 1313 body->AddStatement(stat, zone()); | 1246 body->AddStatement(stat, zone()); |
| 1314 } | 1247 } |
| 1315 } | 1248 } |
| 1316 } | 1249 } |
| 1317 | 1250 |
| 1318 Expect(Token::RBRACE, CHECK_OK); | |
| 1319 scope->set_end_position(scanner()->location().end_pos); | 1251 scope->set_end_position(scanner()->location().end_pos); |
| 1320 body->set_scope(scope); | 1252 body->set_scope(scope); |
| 1321 | 1253 |
| 1322 // Check that all exports are bound. | 1254 // Check that all exports are bound. |
| 1323 Interface* interface = scope->interface(); | 1255 Interface* interface = scope->interface(); |
| 1324 for (Interface::Iterator it = interface->iterator(); | 1256 for (Interface::Iterator it = interface->iterator(); |
| 1325 !it.done(); it.Advance()) { | 1257 !it.done(); it.Advance()) { |
| 1326 if (scope->LookupLocal(it.name()) == NULL) { | 1258 if (scope->LookupLocal(it.name()) == NULL) { |
| 1327 ParserTraits::ReportMessage("module_export_undefined", it.name()); | 1259 ParserTraits::ReportMessage("module_export_undefined", it.name()); |
| 1328 *ok = false; | 1260 *ok = false; |
| 1329 return NULL; | 1261 return NULL; |
| 1330 } | 1262 } |
| 1331 } | 1263 } |
| 1332 | 1264 |
| 1333 interface->MakeModule(ok); | 1265 interface->MakeModule(ok); |
| 1334 DCHECK(*ok); | 1266 DCHECK(*ok); |
| 1335 interface->Freeze(ok); | 1267 interface->Freeze(ok); |
| 1336 DCHECK(*ok); | 1268 DCHECK(*ok); |
| 1337 return factory()->NewModuleLiteral(body, interface, pos); | 1269 return factory()->NewModuleLiteral(body, interface, pos); |
| 1338 } | 1270 } |
| 1339 | 1271 |
| 1340 | 1272 |
| 1341 Module* Parser::ParseModulePath(bool* ok) { | |
| 1342 // ModulePath: | |
| 1343 // Identifier | |
| 1344 // ModulePath '.' Identifier | |
| 1345 | |
| 1346 int pos = peek_position(); | |
| 1347 Module* result = ParseModuleVariable(CHECK_OK); | |
| 1348 while (Check(Token::PERIOD)) { | |
| 1349 const AstRawString* name = ParseIdentifierName(CHECK_OK); | |
| 1350 #ifdef DEBUG | |
| 1351 if (FLAG_print_interface_details) | |
| 1352 PrintF("# Path .%.*s ", name->length(), name->raw_data()); | |
| 1353 #endif | |
| 1354 Module* member = factory()->NewModulePath(result, name, pos); | |
| 1355 result->interface()->Add(name, member->interface(), zone(), ok); | |
| 1356 if (!*ok) { | |
| 1357 #ifdef DEBUG | |
| 1358 if (FLAG_print_interfaces) { | |
| 1359 PrintF("PATH TYPE ERROR at '%.*s'\n", name->length(), name->raw_data()); | |
| 1360 PrintF("result: "); | |
| 1361 result->interface()->Print(); | |
| 1362 PrintF("member: "); | |
| 1363 member->interface()->Print(); | |
| 1364 } | |
| 1365 #endif | |
| 1366 ParserTraits::ReportMessage("invalid_module_path", name); | |
| 1367 return NULL; | |
| 1368 } | |
| 1369 result = member; | |
| 1370 } | |
| 1371 | |
| 1372 return result; | |
| 1373 } | |
| 1374 | |
| 1375 | |
| 1376 Module* Parser::ParseModuleVariable(bool* ok) { | 1273 Module* Parser::ParseModuleVariable(bool* ok) { |
|
rossberg
2015/01/27 20:00:56
Is this still used?
adamk
2015/01/27 20:11:02
No, it's not. I thought it might be useful for "im
| |
| 1377 // ModulePath: | 1274 // ModulePath: |
| 1378 // Identifier | 1275 // Identifier |
| 1379 | 1276 |
| 1380 int pos = peek_position(); | 1277 int pos = peek_position(); |
| 1381 const AstRawString* name = | 1278 const AstRawString* name = |
| 1382 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); | 1279 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| 1383 #ifdef DEBUG | 1280 #ifdef DEBUG |
| 1384 if (FLAG_print_interface_details) | 1281 if (FLAG_print_interface_details) |
| 1385 PrintF("# Module variable %.*s ", name->length(), name->raw_data()); | 1282 PrintF("# Module variable %.*s ", name->length(), name->raw_data()); |
| 1386 #endif | 1283 #endif |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1414 Interface* interface = scope->interface(); | 1311 Interface* interface = scope->interface(); |
| 1415 Module* result = factory()->NewModuleLiteral(body, interface, pos); | 1312 Module* result = factory()->NewModuleLiteral(body, interface, pos); |
| 1416 interface->Freeze(ok); | 1313 interface->Freeze(ok); |
| 1417 DCHECK(*ok); | 1314 DCHECK(*ok); |
| 1418 interface->Unify(scope->interface(), zone(), ok); | 1315 interface->Unify(scope->interface(), zone(), ok); |
| 1419 DCHECK(*ok); | 1316 DCHECK(*ok); |
| 1420 return result; | 1317 return result; |
| 1421 } | 1318 } |
| 1422 | 1319 |
| 1423 | 1320 |
| 1424 Module* Parser::ParseModuleSpecifier(bool* ok) { | 1321 Statement* Parser::ParseImportDeclaration(bool* ok) { |
| 1425 // ModuleSpecifier: | |
| 1426 // String | |
| 1427 // ModulePath | |
| 1428 | |
| 1429 if (peek() == Token::STRING) { | |
| 1430 return ParseModuleUrl(ok); | |
| 1431 } else { | |
| 1432 return ParseModulePath(ok); | |
| 1433 } | |
| 1434 } | |
| 1435 | |
| 1436 | |
| 1437 Block* Parser::ParseImportDeclaration(bool* ok) { | |
| 1438 // ImportDeclaration: | 1322 // ImportDeclaration: |
| 1439 // 'import' IdentifierName (',' IdentifierName)* 'from' ModuleSpecifier ';' | 1323 // 'import' IdentifierName (',' IdentifierName)* 'from' ModuleUrl ';' |
| 1440 // | 1324 // |
| 1441 // TODO(ES6): implement destructuring ImportSpecifiers | 1325 // TODO(ES6): implement current syntax |
| 1442 | 1326 |
| 1443 int pos = peek_position(); | 1327 int pos = peek_position(); |
| 1444 Expect(Token::IMPORT, CHECK_OK); | 1328 Expect(Token::IMPORT, CHECK_OK); |
| 1445 ZoneList<const AstRawString*> names(1, zone()); | 1329 ZoneList<const AstRawString*> names(1, zone()); |
| 1446 | 1330 |
| 1447 const AstRawString* name = ParseIdentifierName(CHECK_OK); | 1331 const AstRawString* name = ParseIdentifierName(CHECK_OK); |
| 1448 names.Add(name, zone()); | 1332 names.Add(name, zone()); |
| 1449 while (peek() == Token::COMMA) { | 1333 while (peek() == Token::COMMA) { |
| 1450 Consume(Token::COMMA); | 1334 Consume(Token::COMMA); |
| 1451 name = ParseIdentifierName(CHECK_OK); | 1335 name = ParseIdentifierName(CHECK_OK); |
| 1452 names.Add(name, zone()); | 1336 names.Add(name, zone()); |
| 1453 } | 1337 } |
| 1454 | 1338 |
| 1455 ExpectContextualKeyword(CStrVector("from"), CHECK_OK); | 1339 ExpectContextualKeyword(CStrVector("from"), CHECK_OK); |
| 1456 Module* module = ParseModuleSpecifier(CHECK_OK); | 1340 Module* module = ParseModuleUrl(CHECK_OK); |
|
arv (Not doing code reviews)
2015/01/27 01:17:17
This is fine for now but this should not return a
adamk
2015/01/27 01:58:37
Yeah, the API probably just needs to match ParseSt
| |
| 1457 ExpectSemicolon(CHECK_OK); | 1341 ExpectSemicolon(CHECK_OK); |
| 1458 | 1342 |
| 1459 // Generate a separate declaration for each identifier. | 1343 // TODO(ES6): Do something with ParseModuleUrl's return value. |
| 1460 // TODO(ES6): once we implement destructuring, make that one declaration. | 1344 USE(module); |
| 1461 Block* block = factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); | 1345 |
| 1462 for (int i = 0; i < names.length(); ++i) { | 1346 for (int i = 0; i < names.length(); ++i) { |
| 1463 #ifdef DEBUG | 1347 // TODO(ES6): Add a let declaration for each name |
|
rossberg
2015/01/27 20:00:55
Nit: misleading comment, as imports cannot be let-
adamk
2015/01/27 20:11:02
Fair enough, s/let/appropriate/
| |
| 1464 if (FLAG_print_interface_details) | |
| 1465 PrintF("# Import %.*s ", name->length(), name->raw_data()); | |
| 1466 #endif | |
| 1467 Interface* interface = Interface::NewUnknown(zone()); | |
| 1468 module->interface()->Add(names[i], interface, zone(), ok); | |
| 1469 if (!*ok) { | |
| 1470 #ifdef DEBUG | |
| 1471 if (FLAG_print_interfaces) { | |
| 1472 PrintF("IMPORT TYPE ERROR at '%.*s'\n", name->length(), | |
| 1473 name->raw_data()); | |
| 1474 PrintF("module: "); | |
| 1475 module->interface()->Print(); | |
| 1476 } | |
| 1477 #endif | |
| 1478 ParserTraits::ReportMessage("invalid_module_path", name); | |
| 1479 return NULL; | |
| 1480 } | |
| 1481 VariableProxy* proxy = NewUnresolved(names[i], LET, interface); | |
| 1482 Declaration* declaration = | |
| 1483 factory()->NewImportDeclaration(proxy, module, scope_, pos); | |
| 1484 Declare(declaration, true, CHECK_OK); | |
| 1485 } | 1348 } |
| 1486 | 1349 |
| 1487 return block; | 1350 return factory()->NewEmptyStatement(pos); |
| 1488 } | 1351 } |
| 1489 | 1352 |
| 1490 | 1353 |
| 1491 Statement* Parser::ParseExportDeclaration(bool* ok) { | 1354 Statement* Parser::ParseExportDeclaration(bool* ok) { |
| 1492 // ExportDeclaration: | 1355 // ExportDeclaration: |
| 1493 // 'export' Identifier (',' Identifier)* ';' | 1356 // 'export' Identifier (',' Identifier)* ';' |
| 1494 // 'export' VariableDeclaration | 1357 // 'export' VariableDeclaration |
| 1495 // 'export' FunctionDeclaration | 1358 // 'export' FunctionDeclaration |
| 1496 // 'export' GeneratorDeclaration | 1359 // 'export' GeneratorDeclaration |
| 1497 // 'export' ModuleDeclaration | 1360 // 'export' ModuleDeclaration |
| 1498 // | 1361 // |
| 1499 // TODO(ES6): implement structuring ExportSpecifiers | 1362 // TODO(ES6): implement current syntax |
| 1500 | 1363 |
| 1501 Expect(Token::EXPORT, CHECK_OK); | 1364 Expect(Token::EXPORT, CHECK_OK); |
| 1502 | 1365 |
| 1503 Statement* result = NULL; | 1366 Statement* result = NULL; |
| 1504 ZoneList<const AstRawString*> names(1, zone()); | 1367 ZoneList<const AstRawString*> names(1, zone()); |
| 1505 switch (peek()) { | 1368 switch (peek()) { |
| 1506 case Token::IDENTIFIER: { | 1369 case Token::IDENTIFIER: { |
| 1507 int pos = position(); | 1370 int pos = position(); |
| 1508 const AstRawString* name = | 1371 const AstRawString* name = |
| 1509 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); | 1372 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| 1510 // Handle 'module' as a context-sensitive keyword. | 1373 names.Add(name, zone()); |
| 1511 if (name != ast_value_factory()->module_string()) { | 1374 while (peek() == Token::COMMA) { |
| 1375 Consume(Token::COMMA); | |
| 1376 name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); | |
| 1512 names.Add(name, zone()); | 1377 names.Add(name, zone()); |
| 1513 while (peek() == Token::COMMA) { | |
| 1514 Consume(Token::COMMA); | |
| 1515 name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); | |
| 1516 names.Add(name, zone()); | |
| 1517 } | |
| 1518 ExpectSemicolon(CHECK_OK); | |
| 1519 result = factory()->NewEmptyStatement(pos); | |
| 1520 } else { | |
| 1521 result = ParseModuleDeclaration(&names, CHECK_OK); | |
| 1522 } | 1378 } |
| 1379 ExpectSemicolon(CHECK_OK); | |
| 1380 result = factory()->NewEmptyStatement(pos); | |
| 1523 break; | 1381 break; |
| 1524 } | 1382 } |
| 1525 | 1383 |
| 1526 case Token::FUNCTION: | 1384 case Token::FUNCTION: |
| 1527 result = ParseFunctionDeclaration(&names, CHECK_OK); | 1385 result = ParseFunctionDeclaration(&names, CHECK_OK); |
| 1528 break; | 1386 break; |
| 1529 | 1387 |
| 1530 case Token::CLASS: | 1388 case Token::CLASS: |
| 1531 result = ParseClassDeclaration(&names, CHECK_OK); | 1389 result = ParseClassDeclaration(&names, CHECK_OK); |
| 1532 break; | 1390 break; |
| 1533 | 1391 |
| 1534 case Token::VAR: | 1392 case Token::VAR: |
| 1535 case Token::LET: | 1393 case Token::LET: |
| 1536 case Token::CONST: | 1394 case Token::CONST: |
| 1537 result = ParseVariableStatement(kModuleElement, &names, CHECK_OK); | 1395 result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK); |
| 1538 break; | 1396 break; |
| 1539 | 1397 |
| 1540 default: | 1398 default: |
| 1541 *ok = false; | 1399 *ok = false; |
| 1542 ReportUnexpectedToken(scanner()->current_token()); | 1400 ReportUnexpectedToken(scanner()->current_token()); |
| 1543 return NULL; | 1401 return NULL; |
| 1544 } | 1402 } |
| 1545 | 1403 |
| 1546 // Every export of a module may be assigned. | 1404 // Every export of a module may be assigned. |
| 1547 for (int i = 0; i < names.length(); ++i) { | 1405 for (int i = 0; i < names.length(); ++i) { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1574 // ExportDeclaration* declaration = | 1432 // ExportDeclaration* declaration = |
| 1575 // factory()->NewExportDeclaration(proxy, scope_, position); | 1433 // factory()->NewExportDeclaration(proxy, scope_, position); |
| 1576 // scope_->AddDeclaration(declaration); | 1434 // scope_->AddDeclaration(declaration); |
| 1577 } | 1435 } |
| 1578 | 1436 |
| 1579 DCHECK(result != NULL); | 1437 DCHECK(result != NULL); |
| 1580 return result; | 1438 return result; |
| 1581 } | 1439 } |
| 1582 | 1440 |
| 1583 | 1441 |
| 1584 Statement* Parser::ParseBlockElement(ZoneList<const AstRawString*>* labels, | |
| 1585 bool* ok) { | |
| 1586 // (Ecma 262 5th Edition, clause 14): | |
| 1587 // SourceElement: | |
| 1588 // Statement | |
| 1589 // FunctionDeclaration | |
| 1590 // | |
| 1591 // In harmony mode we allow additionally the following productions | |
| 1592 // BlockElement (aka SourceElement): | |
| 1593 // LetDeclaration | |
| 1594 // ConstDeclaration | |
| 1595 // GeneratorDeclaration | |
| 1596 // ClassDeclaration | |
| 1597 | |
| 1598 switch (peek()) { | |
| 1599 case Token::FUNCTION: | |
| 1600 return ParseFunctionDeclaration(NULL, ok); | |
| 1601 case Token::CLASS: | |
| 1602 return ParseClassDeclaration(NULL, ok); | |
| 1603 case Token::CONST: | |
| 1604 return ParseVariableStatement(kModuleElement, NULL, ok); | |
| 1605 case Token::LET: | |
| 1606 DCHECK(allow_harmony_scoping()); | |
| 1607 if (strict_mode() == STRICT) { | |
| 1608 return ParseVariableStatement(kModuleElement, NULL, ok); | |
| 1609 } | |
| 1610 // Fall through. | |
| 1611 default: | |
| 1612 return ParseStatement(labels, ok); | |
| 1613 } | |
| 1614 } | |
| 1615 | |
| 1616 | |
| 1617 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels, | 1442 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels, |
| 1618 bool* ok) { | 1443 bool* ok) { |
| 1619 // Statement :: | 1444 // Statement :: |
| 1620 // Block | 1445 // Block |
| 1621 // VariableStatement | 1446 // VariableStatement |
| 1622 // EmptyStatement | 1447 // EmptyStatement |
| 1623 // ExpressionStatement | 1448 // ExpressionStatement |
| 1624 // IfStatement | 1449 // IfStatement |
| 1625 // IterationStatement | 1450 // IterationStatement |
| 1626 // ContinueStatement | 1451 // ContinueStatement |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2060 factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition); | 1885 factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition); |
| 2061 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 1886 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
| 2062 | 1887 |
| 2063 // Parse the statements and collect escaping labels. | 1888 // Parse the statements and collect escaping labels. |
| 2064 Expect(Token::LBRACE, CHECK_OK); | 1889 Expect(Token::LBRACE, CHECK_OK); |
| 2065 block_scope->set_start_position(scanner()->location().beg_pos); | 1890 block_scope->set_start_position(scanner()->location().beg_pos); |
| 2066 { BlockState block_state(&scope_, block_scope); | 1891 { BlockState block_state(&scope_, block_scope); |
| 2067 Target target(&this->target_stack_, body); | 1892 Target target(&this->target_stack_, body); |
| 2068 | 1893 |
| 2069 while (peek() != Token::RBRACE) { | 1894 while (peek() != Token::RBRACE) { |
| 2070 Statement* stat = ParseBlockElement(NULL, CHECK_OK); | 1895 Statement* stat = ParseStatementListItem(CHECK_OK); |
| 2071 if (stat && !stat->IsEmpty()) { | 1896 if (stat && !stat->IsEmpty()) { |
| 2072 body->AddStatement(stat, zone()); | 1897 body->AddStatement(stat, zone()); |
| 2073 } | 1898 } |
| 2074 } | 1899 } |
| 2075 } | 1900 } |
| 2076 Expect(Token::RBRACE, CHECK_OK); | 1901 Expect(Token::RBRACE, CHECK_OK); |
| 2077 block_scope->set_end_position(scanner()->location().end_pos); | 1902 block_scope->set_end_position(scanner()->location().end_pos); |
| 2078 block_scope = block_scope->FinalizeBlockScope(); | 1903 block_scope = block_scope->FinalizeBlockScope(); |
| 2079 body->set_scope(block_scope); | 1904 body->set_scope(block_scope); |
| 2080 return body; | 1905 return body; |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2475 // no line-terminator between the two words. | 2300 // no line-terminator between the two words. |
| 2476 if (extension_ != NULL && peek() == Token::FUNCTION && | 2301 if (extension_ != NULL && peek() == Token::FUNCTION && |
| 2477 !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL && | 2302 !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL && |
| 2478 expr->AsVariableProxy() != NULL && | 2303 expr->AsVariableProxy() != NULL && |
| 2479 expr->AsVariableProxy()->raw_name() == | 2304 expr->AsVariableProxy()->raw_name() == |
| 2480 ast_value_factory()->native_string() && | 2305 ast_value_factory()->native_string() && |
| 2481 !scanner()->literal_contains_escapes()) { | 2306 !scanner()->literal_contains_escapes()) { |
| 2482 return ParseNativeDeclaration(ok); | 2307 return ParseNativeDeclaration(ok); |
| 2483 } | 2308 } |
| 2484 | 2309 |
| 2485 // Parsed expression statement, or the context-sensitive 'module' keyword. | 2310 // Parsed expression statement, followed by semicolon. |
| 2486 // Only expect semicolon in the former case. | |
| 2487 // Also detect attempts at 'let' declarations in sloppy mode. | 2311 // Also detect attempts at 'let' declarations in sloppy mode. |
|
rossberg
2015/01/27 20:00:56
Nit: remove the "also"
adamk
2015/01/27 20:11:02
Done.
| |
| 2488 if (!FLAG_harmony_modules || peek() != Token::IDENTIFIER || | 2312 if (peek() == Token::IDENTIFIER && expr->AsVariableProxy() != NULL && |
| 2489 scanner()->HasAnyLineTerminatorBeforeNext() || | 2313 expr->AsVariableProxy()->raw_name() == |
| 2490 expr->AsVariableProxy() == NULL || | 2314 ast_value_factory()->let_string()) { |
| 2491 expr->AsVariableProxy()->raw_name() != | 2315 ReportMessage("sloppy_lexical", NULL); |
| 2492 ast_value_factory()->module_string() || | 2316 *ok = false; |
| 2493 scanner()->literal_contains_escapes()) { | 2317 return NULL; |
| 2494 if (peek() == Token::IDENTIFIER && expr->AsVariableProxy() != NULL && | |
| 2495 expr->AsVariableProxy()->raw_name() == | |
| 2496 ast_value_factory()->let_string()) { | |
| 2497 ReportMessage("sloppy_lexical", NULL); | |
| 2498 *ok = false; | |
| 2499 return NULL; | |
| 2500 } | |
| 2501 ExpectSemicolon(CHECK_OK); | |
| 2502 } | 2318 } |
| 2319 ExpectSemicolon(CHECK_OK); | |
| 2503 return factory()->NewExpressionStatement(expr, pos); | 2320 return factory()->NewExpressionStatement(expr, pos); |
| 2504 } | 2321 } |
| 2505 | 2322 |
| 2506 | 2323 |
| 2507 IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels, | 2324 IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels, |
| 2508 bool* ok) { | 2325 bool* ok) { |
| 2509 // IfStatement :: | 2326 // IfStatement :: |
| 2510 // 'if' '(' Expression ')' Statement ('else' Statement)? | 2327 // 'if' '(' Expression ')' Statement ('else' Statement)? |
| 2511 | 2328 |
| 2512 int pos = peek_position(); | 2329 int pos = peek_position(); |
| (...skipping 1393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3906 Assignment* assignment = factory()->NewAssignment( | 3723 Assignment* assignment = factory()->NewAssignment( |
| 3907 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition); | 3724 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition); |
| 3908 VariableProxy* get_proxy = factory()->NewVariableProxy( | 3725 VariableProxy* get_proxy = factory()->NewVariableProxy( |
| 3909 function_state_->generator_object_variable()); | 3726 function_state_->generator_object_variable()); |
| 3910 Yield* yield = factory()->NewYield( | 3727 Yield* yield = factory()->NewYield( |
| 3911 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); | 3728 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); |
| 3912 body->Add(factory()->NewExpressionStatement( | 3729 body->Add(factory()->NewExpressionStatement( |
| 3913 yield, RelocInfo::kNoPosition), zone()); | 3730 yield, RelocInfo::kNoPosition), zone()); |
| 3914 } | 3731 } |
| 3915 | 3732 |
| 3916 ParseSourceElements(body, Token::RBRACE, false, false, NULL, CHECK_OK); | 3733 ParseStatementList(body, Token::RBRACE, false, NULL, CHECK_OK); |
| 3917 | 3734 |
| 3918 if (is_generator) { | 3735 if (is_generator) { |
| 3919 VariableProxy* get_proxy = factory()->NewVariableProxy( | 3736 VariableProxy* get_proxy = factory()->NewVariableProxy( |
| 3920 function_state_->generator_object_variable()); | 3737 function_state_->generator_object_variable()); |
| 3921 Expression* undefined = | 3738 Expression* undefined = |
| 3922 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); | 3739 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); |
| 3923 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, | 3740 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, |
| 3924 RelocInfo::kNoPosition); | 3741 RelocInfo::kNoPosition); |
| 3925 body->Add(factory()->NewExpressionStatement( | 3742 body->Add(factory()->NewExpressionStatement( |
| 3926 yield, RelocInfo::kNoPosition), zone()); | 3743 yield, RelocInfo::kNoPosition), zone()); |
| (...skipping 1418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5345 } else { | 5162 } else { |
| 5346 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 5163 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); |
| 5347 running_hash = StringHasher::ComputeRunningHash(running_hash, data, | 5164 running_hash = StringHasher::ComputeRunningHash(running_hash, data, |
| 5348 raw_string->length()); | 5165 raw_string->length()); |
| 5349 } | 5166 } |
| 5350 } | 5167 } |
| 5351 | 5168 |
| 5352 return running_hash; | 5169 return running_hash; |
| 5353 } | 5170 } |
| 5354 } } // namespace v8::internal | 5171 } } // namespace v8::internal |
| OLD | NEW |