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

Side by Side Diff: src/parser.cc

Issue 882893002: Implement ParseExportDeclaration per latest ES6 spec draft (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 11 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
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 1252 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 } 1263 }
1264 1264
1265 interface->MakeModule(ok); 1265 interface->MakeModule(ok);
1266 DCHECK(*ok); 1266 DCHECK(*ok);
1267 interface->Freeze(ok); 1267 interface->Freeze(ok);
1268 DCHECK(*ok); 1268 DCHECK(*ok);
1269 return factory()->NewModuleLiteral(body, interface, pos); 1269 return factory()->NewModuleLiteral(body, interface, pos);
1270 } 1270 }
1271 1271
1272 1272
1273 Module* Parser::ParseModuleUrl(bool* ok) { 1273 Module* Parser::ParseModuleSpecifier(bool* ok) {
1274 // Module: 1274 // Module:
1275 // String 1275 // String
1276 1276
1277 int pos = peek_position(); 1277 int pos = peek_position();
1278 Expect(Token::STRING, CHECK_OK); 1278 Expect(Token::STRING, CHECK_OK);
1279 const AstRawString* symbol = GetSymbol(scanner()); 1279 const AstRawString* symbol = GetSymbol(scanner());
1280 1280
1281 // TODO(ES6): Request JS resource from environment... 1281 // TODO(ES6): Request JS resource from environment...
1282 1282
1283 #ifdef DEBUG 1283 #ifdef DEBUG
1284 if (FLAG_print_interface_details) PrintF("# Url "); 1284 if (FLAG_print_interface_details) PrintF("# Url ");
1285 #endif 1285 #endif
1286 1286
1287 // Create an empty literal as long as the feature isn't finished. 1287 // Create an empty literal as long as the feature isn't finished.
1288 USE(symbol); 1288 USE(symbol);
1289 Scope* scope = NewScope(scope_, MODULE_SCOPE); 1289 Scope* scope = NewScope(scope_, MODULE_SCOPE);
1290 Block* body = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); 1290 Block* body = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
1291 body->set_scope(scope); 1291 body->set_scope(scope);
1292 Interface* interface = scope->interface(); 1292 Interface* interface = scope->interface();
1293 Module* result = factory()->NewModuleLiteral(body, interface, pos); 1293 Module* result = factory()->NewModuleLiteral(body, interface, pos);
1294 interface->Freeze(ok); 1294 interface->Freeze(ok);
1295 DCHECK(*ok); 1295 DCHECK(*ok);
1296 interface->Unify(scope->interface(), zone(), ok); 1296 interface->Unify(scope->interface(), zone(), ok);
1297 DCHECK(*ok); 1297 DCHECK(*ok);
1298 return result; 1298 return result;
1299 } 1299 }
1300 1300
1301 1301
1302 void* Parser::ParseModuleDeclarationClause(
1303 ZoneList<const AstRawString*>* names, bool* ok) {
1304 // Handles both imports and exports:
1305 //
1306 // ImportOrExportClause :
1307 // '{' '}'
1308 // '{' ImportOrExportsList '}'
1309 // '{' ImportOrExportsList ',' '}'
1310 //
1311 // ImportOrExportsList :
1312 // ImportOrExportSpecifier
1313 // ImportOrExportsList ',' ImportOrExportSpecifier
1314 //
1315 // ImportOrExportSpecifier :
1316 // IdentifierName
1317 // IdentifierName 'as' IdentifierName
1318
1319 Expect(Token::LBRACE, CHECK_OK);
1320
1321 while (peek() != Token::RBRACE) {
1322 const AstRawString* name = ParseIdentifierName(CHECK_OK);
1323 names->Add(name, zone());
1324 const AstRawString* export_name = NULL;
1325 if (CheckContextualKeyword(CStrVector("as"))) {
1326 export_name = ParseIdentifierName(CHECK_OK);
1327 }
1328 // TODO(ES6): Return the export_name as well as the name.
1329 USE(export_name);
1330 if (peek() == Token::RBRACE) break;
1331 Expect(Token::COMMA, CHECK_OK);
1332 }
1333
1334 Expect(Token::RBRACE, CHECK_OK);
1335
1336 return 0;
1337 }
1338
1339
1302 Statement* Parser::ParseImportDeclaration(bool* ok) { 1340 Statement* Parser::ParseImportDeclaration(bool* ok) {
1303 // ImportDeclaration: 1341 // ImportDeclaration:
1304 // 'import' IdentifierName (',' IdentifierName)* 'from' ModuleUrl ';' 1342 // 'import' IdentifierName (',' IdentifierName)* 'from' ModuleUrl ';'
1305 // 1343 //
1306 // TODO(ES6): implement current syntax 1344 // TODO(ES6): implement current syntax
1307 1345
1308 int pos = peek_position(); 1346 int pos = peek_position();
1309 Expect(Token::IMPORT, CHECK_OK); 1347 Expect(Token::IMPORT, CHECK_OK);
1310 ZoneList<const AstRawString*> names(1, zone()); 1348 ZoneList<const AstRawString*> names(1, zone());
1311 1349
1312 const AstRawString* name = ParseIdentifierName(CHECK_OK); 1350 const AstRawString* name = ParseIdentifierName(CHECK_OK);
1313 names.Add(name, zone()); 1351 names.Add(name, zone());
1314 while (peek() == Token::COMMA) { 1352 while (peek() == Token::COMMA) {
1315 Consume(Token::COMMA); 1353 Consume(Token::COMMA);
1316 name = ParseIdentifierName(CHECK_OK); 1354 name = ParseIdentifierName(CHECK_OK);
1317 names.Add(name, zone()); 1355 names.Add(name, zone());
1318 } 1356 }
1319 1357
1320 ExpectContextualKeyword(CStrVector("from"), CHECK_OK); 1358 ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1321 Module* module = ParseModuleUrl(CHECK_OK); 1359 Module* module = ParseModuleSpecifier(CHECK_OK);
1322 ExpectSemicolon(CHECK_OK); 1360 ExpectSemicolon(CHECK_OK);
1323 1361
1324 // TODO(ES6): Do something with ParseModuleUrl's return value. 1362 // TODO(ES6): Do something with ParseModuleSpecifier's return value.
1325 USE(module); 1363 USE(module);
1326 1364
1327 for (int i = 0; i < names.length(); ++i) { 1365 for (int i = 0; i < names.length(); ++i) {
1328 // TODO(ES6): Add an appropriate declaration for each name 1366 // TODO(ES6): Add an appropriate declaration for each name
1329 } 1367 }
1330 1368
1331 return factory()->NewEmptyStatement(pos); 1369 return factory()->NewEmptyStatement(pos);
1332 } 1370 }
1333 1371
1334 1372
1373 Statement* Parser::ParseExportDefault(bool* ok) {
1374 // Supports the following productions, starting after the 'default' token:
1375 // 'export' 'default' FunctionDeclaration
1376 // 'export' 'default' ClassDeclaration
1377 // 'export' 'default' AssignmentExpression[In] ';'
1378 //
1379 // TODO(ES6): Allow FunctionDeclaration[Default] and
1380 // ClassDeclaration[Default].
1381
1382 Statement* result = NULL;
1383 switch (peek()) {
1384 case Token::FUNCTION:
arv (Not doing code reviews) 2015/01/28 02:57:19 This is going to be problematic. export default su
adamk 2015/01/28 18:05:04 That's the TODO above about FunctionDeclaration[De
1385 result = ParseFunctionDeclaration(NULL, CHECK_OK);
1386 break;
1387
1388 case Token::CLASS:
1389 result = ParseClassDeclaration(NULL, CHECK_OK);
arv (Not doing code reviews) 2015/01/28 02:57:19 Same here
1390 break;
1391
1392 default: {
1393 int pos = peek_position();
1394 Expression* expr = ParseAssignmentExpression(true, CHECK_OK);
1395 ExpectSemicolon(CHECK_OK);
1396 result = factory()->NewExpressionStatement(expr, pos);
1397 break;
1398 }
1399 }
1400
1401 // TODO(ES6): Add default export to scope_->interface()
1402
1403 return result;
1404 }
1405
1406
1335 Statement* Parser::ParseExportDeclaration(bool* ok) { 1407 Statement* Parser::ParseExportDeclaration(bool* ok) {
1336 // ExportDeclaration: 1408 // ExportDeclaration:
1337 // 'export' Identifier (',' Identifier)* ';' 1409 // 'export' '*' 'from' ModuleSpecifier ';'
1338 // 'export' VariableDeclaration 1410 // 'export' ExportClause ('from' ModuleSpecifier)? ';'
1339 // 'export' FunctionDeclaration 1411 // 'export' VariableStatement
1340 // 'export' GeneratorDeclaration 1412 // 'export' Declaration
1341 // 'export' ModuleDeclaration 1413 // 'export' 'default' ... (handled in ParseExportDefault)
1342 //
1343 // TODO(ES6): implement current syntax
1344 1414
1415 int pos = peek_position();
1345 Expect(Token::EXPORT, CHECK_OK); 1416 Expect(Token::EXPORT, CHECK_OK);
1346 1417
1347 Statement* result = NULL; 1418 Statement* result = NULL;
1348 ZoneList<const AstRawString*> names(1, zone()); 1419 ZoneList<const AstRawString*> names(1, zone());
1420 bool is_export_from = false;
1349 switch (peek()) { 1421 switch (peek()) {
1350 case Token::IDENTIFIER: { 1422 case Token::DEFAULT:
1351 int pos = position(); 1423 Consume(Token::DEFAULT);
1352 const AstRawString* name = 1424 return ParseExportDefault(ok);
1353 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 1425
1354 names.Add(name, zone()); 1426 case Token::MUL: {
1355 while (peek() == Token::COMMA) { 1427 Consume(Token::MUL);
1356 Consume(Token::COMMA); 1428 ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1357 name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 1429 Module* module = ParseModuleSpecifier(CHECK_OK);
1358 names.Add(name, zone()); 1430 ExpectSemicolon(CHECK_OK);
1431 // TODO(ES6): Do something with the return value
1432 // of ParseModuleSpecifier.
1433 USE(module);
1434 is_export_from = true;
1435 result = factory()->NewEmptyStatement(pos);
1436 break;
1437 }
1438
1439 case Token::LBRACE:
1440 ParseModuleDeclarationClause(&names, CHECK_OK);
1441 if (CheckContextualKeyword(CStrVector("from"))) {
1442 Module* module = ParseModuleSpecifier(CHECK_OK);
1443 // TODO(ES6): Do something with the return value
1444 // of ParseModuleSpecifier.
1445 USE(module);
1446 is_export_from = true;
1359 } 1447 }
1360 ExpectSemicolon(CHECK_OK); 1448 ExpectSemicolon(CHECK_OK);
1361 result = factory()->NewEmptyStatement(pos); 1449 result = factory()->NewEmptyStatement(pos);
1362 break; 1450 break;
1363 }
1364 1451
1365 case Token::FUNCTION: 1452 case Token::FUNCTION:
1366 result = ParseFunctionDeclaration(&names, CHECK_OK); 1453 result = ParseFunctionDeclaration(&names, CHECK_OK);
1367 break; 1454 break;
1368 1455
1369 case Token::CLASS: 1456 case Token::CLASS:
1370 result = ParseClassDeclaration(&names, CHECK_OK); 1457 result = ParseClassDeclaration(&names, CHECK_OK);
1371 break; 1458 break;
1372 1459
1373 case Token::VAR: 1460 case Token::VAR:
(...skipping 14 matching lines...) Expand all
1388 if (var == NULL) { 1475 if (var == NULL) {
1389 // TODO(sigurds) This is an export that has no definition yet, 1476 // TODO(sigurds) This is an export that has no definition yet,
1390 // not clear what to do in this case. 1477 // not clear what to do in this case.
1391 continue; 1478 continue;
1392 } 1479 }
1393 if (!IsImmutableVariableMode(var->mode())) { 1480 if (!IsImmutableVariableMode(var->mode())) {
1394 var->set_maybe_assigned(); 1481 var->set_maybe_assigned();
1395 } 1482 }
1396 } 1483 }
1397 1484
1398 // Extract declared names into export declarations and interface. 1485 // TODO(ES6): Handle 'export from' once imports are properly implemented.
1399 Interface* interface = scope_->interface(); 1486 // For now we just drop such exports on the floor.
1400 for (int i = 0; i < names.length(); ++i) { 1487 if (!is_export_from) {
1488 // Extract declared names into export declarations and interface.
1489 Interface* interface = scope_->interface();
1490 for (int i = 0; i < names.length(); ++i) {
1401 #ifdef DEBUG 1491 #ifdef DEBUG
1402 if (FLAG_print_interface_details) 1492 if (FLAG_print_interface_details)
1403 PrintF("# Export %.*s ", names[i]->length(), names[i]->raw_data()); 1493 PrintF("# Export %.*s ", names[i]->length(), names[i]->raw_data());
1404 #endif 1494 #endif
1405 Interface* inner = Interface::NewUnknown(zone()); 1495 Interface* inner = Interface::NewUnknown(zone());
1406 interface->Add(names[i], inner, zone(), CHECK_OK); 1496 interface->Add(names[i], inner, zone(), CHECK_OK);
1407 if (!*ok) 1497 if (!*ok)
1408 return NULL; 1498 return NULL;
1409 VariableProxy* proxy = NewUnresolved(names[i], LET, inner); 1499 VariableProxy* proxy = NewUnresolved(names[i], LET, inner);
1410 USE(proxy); 1500 USE(proxy);
1411 // TODO(rossberg): Rethink whether we actually need to store export 1501 // TODO(rossberg): Rethink whether we actually need to store export
1412 // declarations (for compilation?). 1502 // declarations (for compilation?).
1413 // ExportDeclaration* declaration = 1503 // ExportDeclaration* declaration =
1414 // factory()->NewExportDeclaration(proxy, scope_, position); 1504 // factory()->NewExportDeclaration(proxy, scope_, position);
1415 // scope_->AddDeclaration(declaration); 1505 // scope_->AddDeclaration(declaration);
1506 }
1416 } 1507 }
1417 1508
1418 DCHECK(result != NULL); 1509 DCHECK(result != NULL);
1419 return result; 1510 return result;
1420 } 1511 }
1421 1512
1422 1513
1423 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels, 1514 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
1424 bool* ok) { 1515 bool* ok) {
1425 // Statement :: 1516 // Statement ::
(...skipping 3717 matching lines...) Expand 10 before | Expand all | Expand 10 after
5143 } else { 5234 } else {
5144 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); 5235 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
5145 running_hash = StringHasher::ComputeRunningHash(running_hash, data, 5236 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
5146 raw_string->length()); 5237 raw_string->length());
5147 } 5238 }
5148 } 5239 }
5149 5240
5150 return running_hash; 5241 return running_hash;
5151 } 5242 }
5152 } } // namespace v8::internal 5243 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | test/cctest/test-parsing.cc » ('j') | test/cctest/test-parsing.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698