Implement #4864: Core is a keyword (#4909)

Change representation of package names from `IdentifierId` to
`PackageNameId`, and add a special value `PackageNameId::Core` for the
Core package. Add a `Core` expression to name the Core package, and
support for parsing the `Core` keyword in `package` and `import`
declarations.

For now, I've made no changes to instruction fingerprinting or name
mangling. This means that fingerprints and mangled names will collide
between names in the `Core` package and names in a `r#Core` package. See
#4908.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
Richard Smith
2025-02-11 21:33:57 +00:00
committed by GitHub
co-authored by Jon Ross-Perkins
parent 50b3c825e4
commit 8eb4e24cb6
62 changed files with 935 additions and 487 deletions
+28 -15
View File
@@ -42,32 +42,45 @@ static auto HandleDeclContent(Context& context, Context::StateStackEntry state,
Tree::PackagingNames names{
.node_id = ImportDeclId(NodeId(state.subtree_start)),
.is_export = is_export};
if (declaration != NodeKind::LibraryDecl) {
if (auto package_name_token =
context.ConsumeIf(Lex::TokenKind::Identifier)) {
if (names.is_export) {
names.is_export = false;
state.has_error = true;
CARBON_DIAGNOSTIC(ExportImportPackage, Error,
"`export` cannot be used when importing a package");
context.emitter().Emit(*package_name_token, ExportImportPackage);
}
names.package_id = context.tokens().GetIdentifier(*package_name_token);
context.AddLeafNode(NodeKind::PackageName, *package_name_token);
} else if (declaration == NodeKind::PackageDecl ||
!context.PositionIs(Lex::TokenKind::Library)) {
// Parse the package name.
if (declaration == NodeKind::LibraryDecl ||
(declaration == NodeKind::ImportDecl &&
context.PositionIs(Lex::TokenKind::Library))) {
// This is either `library ...` or `import library ...`, so no package name
// is expected.
} else {
// We require a package name. This is either an identifier or the `Core`
// keyword.
auto package_name_position = *context.position();
if (auto ident = context.ConsumeIf(Lex::TokenKind::Identifier)) {
names.package_id =
PackageNameId::ForIdentifier(context.tokens().GetIdentifier(*ident));
context.AddLeafNode(NodeKind::IdentifierPackageName, *ident);
} else if (auto core = context.ConsumeIf(Lex::TokenKind::Core)) {
names.package_id = PackageNameId::Core;
context.AddLeafNode(NodeKind::CorePackageName, *core);
} else {
CARBON_DIAGNOSTIC(ExpectedIdentifierAfterPackage, Error,
"expected identifier after `package`");
CARBON_DIAGNOSTIC(ExpectedIdentifierAfterImport, Error,
"expected identifier or `library` after `import`");
context.emitter().Emit(*context.position(),
context.emitter().Emit(package_name_position,
declaration == NodeKind::PackageDecl
? ExpectedIdentifierAfterPackage
: ExpectedIdentifierAfterImport);
on_parse_error();
return;
}
if (names.is_export) {
names.is_export = false;
state.has_error = true;
CARBON_DIAGNOSTIC(ExportImportPackage, Error,
"`export` cannot be used when importing a package");
context.emitter().Emit(package_name_position, ExportImportPackage);
}
}
// Parse the optional library keyword.