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

Side by Side Diff: src/parser.cc

Issue 934323004: Teach ModuleDescriptor about basic local exports (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 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 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 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 } 1274 }
1275 } 1275 }
1276 1276
1277 scope->set_end_position(scanner()->location().end_pos); 1277 scope->set_end_position(scanner()->location().end_pos);
1278 body->set_scope(scope); 1278 body->set_scope(scope);
1279 1279
1280 // Check that all exports are bound. 1280 // Check that all exports are bound.
1281 ModuleDescriptor* descriptor = scope->module(); 1281 ModuleDescriptor* descriptor = scope->module();
1282 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done(); 1282 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
1283 it.Advance()) { 1283 it.Advance()) {
1284 if (scope->LookupLocal(it.name()) == NULL) { 1284 if (scope->LookupLocal(it.local_name()) == NULL) {
1285 ParserTraits::ReportMessage("module_export_undefined", it.name()); 1285 ParserTraits::ReportMessage("module_export_undefined", it.local_name());
1286 *ok = false; 1286 *ok = false;
1287 return NULL; 1287 return NULL;
1288 } 1288 }
1289 } 1289 }
1290 1290
1291 scope->module()->Freeze(); 1291 scope->module()->Freeze();
1292 return body; 1292 return body;
1293 } 1293 }
1294 1294
1295 1295
1296 Literal* Parser::ParseModuleSpecifier(bool* ok) { 1296 Literal* Parser::ParseModuleSpecifier(bool* ok) {
1297 // ModuleSpecifier : 1297 // ModuleSpecifier :
1298 // StringLiteral 1298 // StringLiteral
1299 1299
1300 int pos = peek_position(); 1300 int pos = peek_position();
1301 Expect(Token::STRING, CHECK_OK); 1301 Expect(Token::STRING, CHECK_OK);
1302 return factory()->NewStringLiteral(GetSymbol(scanner()), pos); 1302 return factory()->NewStringLiteral(GetSymbol(scanner()), pos);
1303 } 1303 }
1304 1304
1305 1305
1306 void* Parser::ParseExportClause(ZoneList<const AstRawString*>* names, 1306 void* Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
1307 ZoneList<const AstRawString*>* local_names,
1307 Scanner::Location* reserved_loc, bool* ok) { 1308 Scanner::Location* reserved_loc, bool* ok) {
1308 // ExportClause : 1309 // ExportClause :
1309 // '{' '}' 1310 // '{' '}'
1310 // '{' ExportsList '}' 1311 // '{' ExportsList '}'
1311 // '{' ExportsList ',' '}' 1312 // '{' ExportsList ',' '}'
1312 // 1313 //
1313 // ExportsList : 1314 // ExportsList :
1314 // ExportSpecifier 1315 // ExportSpecifier
1315 // ExportsList ',' ExportSpecifier 1316 // ExportsList ',' ExportSpecifier
1316 // 1317 //
1317 // ExportSpecifier : 1318 // ExportSpecifier :
1318 // IdentifierName 1319 // IdentifierName
1319 // IdentifierName 'as' IdentifierName 1320 // IdentifierName 'as' IdentifierName
1320 1321
1321 Expect(Token::LBRACE, CHECK_OK); 1322 Expect(Token::LBRACE, CHECK_OK);
1322 1323
1323 Token::Value name_tok; 1324 Token::Value name_tok;
1324 while ((name_tok = peek()) != Token::RBRACE) { 1325 while ((name_tok = peek()) != Token::RBRACE) {
1325 // Keep track of the first reserved word encountered in case our 1326 // Keep track of the first reserved word encountered in case our
1326 // caller needs to report an error. 1327 // caller needs to report an error.
1327 if (!reserved_loc->IsValid() && 1328 if (!reserved_loc->IsValid() &&
1328 !Token::IsIdentifier(name_tok, STRICT, false)) { 1329 !Token::IsIdentifier(name_tok, STRICT, false)) {
1329 *reserved_loc = scanner()->location(); 1330 *reserved_loc = scanner()->location();
1330 } 1331 }
1331 const AstRawString* name = ParseIdentifierName(CHECK_OK); 1332 const AstRawString* local_name = ParseIdentifierName(CHECK_OK);
1332 names->Add(name, zone());
1333 const AstRawString* export_name = NULL; 1333 const AstRawString* export_name = NULL;
1334 if (CheckContextualKeyword(CStrVector("as"))) { 1334 if (CheckContextualKeyword(CStrVector("as"))) {
1335 export_name = ParseIdentifierName(CHECK_OK); 1335 export_name = ParseIdentifierName(CHECK_OK);
1336 } 1336 }
1337 // TODO(ES6): Return the export_name as well as the name. 1337 if (export_name == NULL) {
1338 USE(export_name); 1338 export_name = local_name;
1339 }
1340 export_names->Add(export_name, zone());
1341 local_names->Add(local_name, zone());
1339 if (peek() == Token::RBRACE) break; 1342 if (peek() == Token::RBRACE) break;
1340 Expect(Token::COMMA, CHECK_OK); 1343 Expect(Token::COMMA, CHECK_OK);
1341 } 1344 }
1342 1345
1343 Expect(Token::RBRACE, CHECK_OK); 1346 Expect(Token::RBRACE, CHECK_OK);
1344 1347
1345 return 0; 1348 return 0;
1346 } 1349 }
1347 1350
1348 1351
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1472 return factory()->NewEmptyStatement(pos); 1475 return factory()->NewEmptyStatement(pos);
1473 } 1476 }
1474 1477
1475 1478
1476 Statement* Parser::ParseExportDefault(bool* ok) { 1479 Statement* Parser::ParseExportDefault(bool* ok) {
1477 // Supports the following productions, starting after the 'default' token: 1480 // Supports the following productions, starting after the 'default' token:
1478 // 'export' 'default' FunctionDeclaration 1481 // 'export' 'default' FunctionDeclaration
1479 // 'export' 'default' ClassDeclaration 1482 // 'export' 'default' ClassDeclaration
1480 // 'export' 'default' AssignmentExpression[In] ';' 1483 // 'export' 'default' AssignmentExpression[In] ';'
1481 1484
1485 Expect(Token::DEFAULT, CHECK_OK);
1486 Scanner::Location default_loc = scanner()->location();
1487
1488 ZoneList<const AstRawString*> names(1, zone());
1482 Statement* result = NULL; 1489 Statement* result = NULL;
1483 switch (peek()) { 1490 switch (peek()) {
1484 case Token::FUNCTION: 1491 case Token::FUNCTION:
1485 // TODO(ES6): Support parsing anonymous function declarations here. 1492 // TODO(ES6): Support parsing anonymous function declarations here.
1486 result = ParseFunctionDeclaration(NULL, CHECK_OK); 1493 result = ParseFunctionDeclaration(&names, CHECK_OK);
1487 break; 1494 break;
1488 1495
1489 case Token::CLASS: 1496 case Token::CLASS:
1490 // TODO(ES6): Support parsing anonymous class declarations here. 1497 // TODO(ES6): Support parsing anonymous class declarations here.
1491 result = ParseClassDeclaration(NULL, CHECK_OK); 1498 result = ParseClassDeclaration(&names, CHECK_OK);
1492 break; 1499 break;
1493 1500
1494 default: { 1501 default: {
1495 int pos = peek_position(); 1502 int pos = peek_position();
1496 Expression* expr = ParseAssignmentExpression(true, CHECK_OK); 1503 Expression* expr = ParseAssignmentExpression(true, CHECK_OK);
1497 ExpectSemicolon(CHECK_OK); 1504 ExpectSemicolon(CHECK_OK);
1498 result = factory()->NewExpressionStatement(expr, pos); 1505 result = factory()->NewExpressionStatement(expr, pos);
1499 break; 1506 break;
1500 } 1507 }
1501 } 1508 }
1502 1509
1503 // TODO(ES6): Add default export to scope_->module() 1510 const AstRawString* default_string = ast_value_factory()->default_string();
1511
1512 DCHECK_LE(names.length(), 1);
1513 if (names.length() == 1) {
1514 scope_->module()->AddLocalExport(default_string, names.first(), zone(), ok);
1515 if (!*ok) {
1516 ParserTraits::ReportMessageAt(default_loc, "duplicate_export",
1517 default_string);
1518 return NULL;
1519 }
1520 } else {
1521 // TODO(ES6): Assign result to a const binding with the name "*default*"
1522 // and add an export entry with "*default*" as the local name.
1523 }
1504 1524
1505 return result; 1525 return result;
1506 } 1526 }
1507 1527
1508 1528
1509 Statement* Parser::ParseExportDeclaration(bool* ok) { 1529 Statement* Parser::ParseExportDeclaration(bool* ok) {
1510 // ExportDeclaration: 1530 // ExportDeclaration:
1511 // 'export' '*' 'from' ModuleSpecifier ';' 1531 // 'export' '*' 'from' ModuleSpecifier ';'
1512 // 'export' ExportClause ('from' ModuleSpecifier)? ';' 1532 // 'export' ExportClause ('from' ModuleSpecifier)? ';'
1513 // 'export' VariableStatement 1533 // 'export' VariableStatement
1514 // 'export' Declaration 1534 // 'export' Declaration
1515 // 'export' 'default' ... (handled in ParseExportDefault) 1535 // 'export' 'default' ... (handled in ParseExportDefault)
1516 1536
1517 int pos = peek_position(); 1537 int pos = peek_position();
1518 Expect(Token::EXPORT, CHECK_OK); 1538 Expect(Token::EXPORT, CHECK_OK);
1519 1539
1520 Statement* result = NULL; 1540 Statement* result = NULL;
1521 ZoneList<const AstRawString*> names(1, zone()); 1541 ZoneList<const AstRawString*> names(1, zone());
1522 bool is_export_from = false;
1523 switch (peek()) { 1542 switch (peek()) {
1524 case Token::DEFAULT: 1543 case Token::DEFAULT:
1525 Consume(Token::DEFAULT);
1526 return ParseExportDefault(ok); 1544 return ParseExportDefault(ok);
1527 1545
1528 case Token::MUL: { 1546 case Token::MUL: {
1529 Consume(Token::MUL); 1547 Consume(Token::MUL);
1530 ExpectContextualKeyword(CStrVector("from"), CHECK_OK); 1548 ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1531 Literal* module = ParseModuleSpecifier(CHECK_OK); 1549 Literal* module = ParseModuleSpecifier(CHECK_OK);
1532 ExpectSemicolon(CHECK_OK); 1550 ExpectSemicolon(CHECK_OK);
1533 // TODO(ES6): Do something with the return value 1551 // TODO(ES6): scope_->module()->AddStarExport(...)
1534 // of ParseModuleSpecifier.
1535 USE(module); 1552 USE(module);
1536 is_export_from = true; 1553 return factory()->NewEmptyStatement(pos);
1537 result = factory()->NewEmptyStatement(pos);
1538 break;
1539 } 1554 }
1540 1555
1541 case Token::LBRACE: { 1556 case Token::LBRACE: {
1542 // There are two cases here: 1557 // There are two cases here:
1543 // 1558 //
1544 // 'export' ExportClause ';' 1559 // 'export' ExportClause ';'
1545 // and 1560 // and
1546 // 'export' ExportClause FromClause ';' 1561 // 'export' ExportClause FromClause ';'
1547 // 1562 //
1548 // In the first case, the exported identifiers in ExportClause must 1563 // In the first case, the exported identifiers in ExportClause must
1549 // not be reserved words, while in the latter they may be. We 1564 // not be reserved words, while in the latter they may be. We
1550 // pass in a location that gets filled with the first reserved word 1565 // pass in a location that gets filled with the first reserved word
1551 // encountered, and then throw a SyntaxError if we are in the 1566 // encountered, and then throw a SyntaxError if we are in the
1552 // non-FromClause case. 1567 // non-FromClause case.
1553 Scanner::Location reserved_loc = Scanner::Location::invalid(); 1568 Scanner::Location reserved_loc = Scanner::Location::invalid();
1554 ParseExportClause(&names, &reserved_loc, CHECK_OK); 1569 ZoneList<const AstRawString*> export_names(1, zone());
1570 ZoneList<const AstRawString*> local_names(1, zone());
1571 ParseExportClause(&export_names, &local_names, &reserved_loc, CHECK_OK);
1572 Literal* indirect_export_module_specifier = NULL;
1555 if (CheckContextualKeyword(CStrVector("from"))) { 1573 if (CheckContextualKeyword(CStrVector("from"))) {
1556 Literal* module = ParseModuleSpecifier(CHECK_OK); 1574 indirect_export_module_specifier = ParseModuleSpecifier(CHECK_OK);
1557 // TODO(ES6): Do something with the return value
1558 // of ParseModuleSpecifier.
1559 USE(module);
1560 is_export_from = true;
1561 } else if (reserved_loc.IsValid()) { 1575 } else if (reserved_loc.IsValid()) {
1562 // No FromClause, so reserved words are invalid in ExportClause. 1576 // No FromClause, so reserved words are invalid in ExportClause.
1563 *ok = false; 1577 *ok = false;
1564 ReportMessageAt(reserved_loc, "unexpected_reserved"); 1578 ReportMessageAt(reserved_loc, "unexpected_reserved");
1565 return NULL; 1579 return NULL;
1566 } 1580 }
1567 ExpectSemicolon(CHECK_OK); 1581 ExpectSemicolon(CHECK_OK);
1568 result = factory()->NewEmptyStatement(pos); 1582 DCHECK_EQ(export_names.length(), local_names.length());
1569 break; 1583 const int length = export_names.length();
1584 if (indirect_export_module_specifier == NULL) {
1585 for (int i = 0; i < length; ++i) {
1586 scope_->module()->AddLocalExport(export_names[i], local_names[i],
1587 zone(), ok);
1588 if (!*ok) {
1589 // TODO(adamk): Possibly report this error at the right place.
arv (Not doing code reviews) 2015/02/19 15:05:44 Maybe pass one more list with the locations to Par
adamk 2015/02/19 19:10:09 Hmm. There will be cases, with "export * from ..."
1590 ParserTraits::ReportMessage("duplicate_export", export_names[i]);
1591 return NULL;
1592 }
1593 }
1594 } else {
1595 for (int i = 0; i < length; ++i) {
1596 // TODO(ES6): scope_->module()->AddIndirectExport(...);(
1597 }
1598 }
1599 return factory()->NewEmptyStatement(pos);
1570 } 1600 }
1571 1601
1572 case Token::FUNCTION: 1602 case Token::FUNCTION:
1573 result = ParseFunctionDeclaration(&names, CHECK_OK); 1603 result = ParseFunctionDeclaration(&names, CHECK_OK);
1574 break; 1604 break;
1575 1605
1576 case Token::CLASS: 1606 case Token::CLASS:
1577 result = ParseClassDeclaration(&names, CHECK_OK); 1607 result = ParseClassDeclaration(&names, CHECK_OK);
1578 break; 1608 break;
1579 1609
1580 case Token::VAR: 1610 case Token::VAR:
1581 case Token::LET: 1611 case Token::LET:
1582 case Token::CONST: 1612 case Token::CONST:
1583 result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK); 1613 result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK);
1584 break; 1614 break;
1585 1615
1586 default: 1616 default:
1587 *ok = false; 1617 *ok = false;
1588 ReportUnexpectedToken(scanner()->current_token()); 1618 ReportUnexpectedToken(scanner()->current_token());
1589 return NULL; 1619 return NULL;
1590 } 1620 }
1591 1621
1592 // Every export of a module may be assigned. 1622 // Extract declared names into export declarations.
1623 ModuleDescriptor* descriptor = scope_->module();
1593 for (int i = 0; i < names.length(); ++i) { 1624 for (int i = 0; i < names.length(); ++i) {
1594 Variable* var = scope_->Lookup(names[i]); 1625 descriptor->AddLocalExport(names[i], names[i], zone(), ok);
1595 if (var == NULL) { 1626 if (!*ok) {
1596 // TODO(sigurds) This is an export that has no definition yet, 1627 // TODO(adamk): Possibly report this error at the right place.
1597 // not clear what to do in this case. 1628 ParserTraits::ReportMessage("duplicate_export", names[i]);
1598 continue; 1629 return NULL;
1599 }
1600 if (!IsImmutableVariableMode(var->mode())) {
1601 var->set_maybe_assigned();
1602 } 1630 }
1603 } 1631 }
1604 1632
1605 // TODO(ES6): Handle 'export from' once imports are properly implemented. 1633 DCHECK_NOT_NULL(result);
1606 // For now we just drop such exports on the floor.
1607 if (!is_export_from) {
1608 // Extract declared names into export declarations and module descriptor.
1609 ModuleDescriptor* descriptor = scope_->module();
1610 for (int i = 0; i < names.length(); ++i) {
1611 // TODO(adamk): Make early errors here provide the right error message
1612 // (duplicate exported names).
1613 descriptor->Add(names[i], zone(), CHECK_OK);
1614 // TODO(rossberg): Rethink whether we actually need to store export
1615 // declarations (for compilation?).
1616 // ExportDeclaration* declaration =
1617 // factory()->NewExportDeclaration(proxy, scope_, position);
1618 // scope_->AddDeclaration(declaration);
1619 }
1620 }
1621
1622 DCHECK(result != NULL);
1623 return result; 1634 return result;
1624 } 1635 }
1625 1636
1626 1637
1627 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels, 1638 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
1628 bool* ok) { 1639 bool* ok) {
1629 // Statement :: 1640 // Statement ::
1630 // EmptyStatement 1641 // EmptyStatement
1631 // ... 1642 // ...
1632 1643
(...skipping 3807 matching lines...) Expand 10 before | Expand all | Expand 10 after
5440 } else { 5451 } else {
5441 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); 5452 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
5442 running_hash = StringHasher::ComputeRunningHash(running_hash, data, 5453 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
5443 raw_string->length()); 5454 raw_string->length());
5444 } 5455 }
5445 } 5456 }
5446 5457
5447 return running_hash; 5458 return running_hash;
5448 } 5459 }
5449 } } // namespace v8::internal 5460 } } // namespace v8::internal
OLDNEW
« src/messages.js ('K') | « src/parser.h ('k') | src/scopeinfo.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698