Files
carbon-lang/toolchain/parser/parser_handle_function.cpp
T
Jon Ross-Perkins 918c089e03 Add namespace support. (#2940)
This handles namespacing of functions. Parsing and semantics are changed
significantly, while lowering works without changes. Variables can't be
namespaced yet because they're dealing with patterns, and I didn't dig
through that code.

Most of the logic is done through the new name declaration stack, which
is necessary because semantics isn't quite sure where the declaration
name ends. It'd be complex for parsing to send a signal about this,
probably involving node variants and rewrites of the tree, and this
solution seems to work well. Unfortunately this means a new stack, but
that may be inevitable due to the extra information needing to be
tracked.

Note this doesn't deal with scoped lookups of non-namespace things,
which we'll need for generics. That'll probably involve pushing resolved
scopes onto a stack (or maybe just setting a singleton value?) to affect
contextual name lookup. But, I think the basics are there to make it
work when we can test the behavior.

This renames "designator expression" to "qualified expression" and adds
"qualified declaration" in order to use terminology more consistent with
C++.

Namespaces will probably need to be considered for name mangling down
the line, but this still uses the basic name.
2023-07-06 20:43:40 +00:00

97 lines
3.5 KiB
C++

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/parser/parser_context.h"
namespace Carbon {
auto ParserHandleFunctionIntroducer(ParserContext& context) -> void {
auto state = context.PopState();
context.AddLeafNode(ParseNodeKind::FunctionIntroducer, context.Consume());
state.state = ParserState::FunctionAfterParameters;
context.PushState(state);
context.PushState(ParserState::DeclarationNameAndParamsAsRequired,
state.token);
}
auto ParserHandleFunctionAfterParameters(ParserContext& context) -> void {
auto state = context.PopState();
// Regardless of whether there's a return type, we'll finish the signature.
state.state = ParserState::FunctionSignatureFinish;
context.PushState(state);
// If there is a return type, parse the expression before adding the return
// type nod.e
if (context.PositionIs(TokenKind::MinusGreater)) {
context.PushState(ParserState::FunctionReturnTypeFinish);
++context.position();
context.PushStateForExpression(PrecedenceGroup::ForType());
}
}
auto ParserHandleFunctionReturnTypeFinish(ParserContext& context) -> void {
auto state = context.PopState();
context.AddNode(ParseNodeKind::ReturnType, state.token, state.subtree_start,
state.has_error);
}
auto ParserHandleFunctionSignatureFinish(ParserContext& context) -> void {
auto state = context.PopState();
switch (context.PositionKind()) {
case TokenKind::Semi: {
context.AddNode(ParseNodeKind::FunctionDeclaration, context.Consume(),
state.subtree_start, state.has_error);
break;
}
case TokenKind::OpenCurlyBrace: {
if (auto decl_context = context.GetDeclarationContext();
decl_context == ParserContext::DeclarationContext::Interface ||
decl_context == ParserContext::DeclarationContext::NamedConstraint) {
CARBON_DIAGNOSTIC(
MethodImplNotAllowed, Error,
"Method implementations are not allowed in interfaces.");
context.emitter().Emit(*context.position(), MethodImplNotAllowed);
context.RecoverFromDeclarationError(state,
ParseNodeKind::FunctionDeclaration,
/*skip_past_likely_end=*/true);
break;
}
context.AddNode(ParseNodeKind::FunctionDefinitionStart, context.Consume(),
state.subtree_start, state.has_error);
// Any error is recorded on the FunctionDefinitionStart.
state.has_error = false;
state.state = ParserState::FunctionDefinitionFinish;
context.PushState(state);
context.PushState(ParserState::StatementScopeLoop);
break;
}
default: {
if (!state.has_error) {
context.EmitExpectedDeclarationSemiOrDefinition(TokenKind::Fn);
}
// Only need to skip if we've not already found a new line.
bool skip_past_likely_end =
context.tokens().GetLine(*context.position()) ==
context.tokens().GetLine(state.token);
context.RecoverFromDeclarationError(
state, ParseNodeKind::FunctionDeclaration, skip_past_likely_end);
break;
}
}
}
auto ParserHandleFunctionDefinitionFinish(ParserContext& context) -> void {
auto state = context.PopState();
context.AddNode(ParseNodeKind::FunctionDefinition, context.Consume(),
state.subtree_start, state.has_error);
}
} // namespace Carbon