Files
carbon-lang/toolchain/check/handle_let.cpp
T
Jon Ross-Perkins d0fb4b5815 Change DiagnoseDuplicateName to expect an inst ID for the duplicate. (#3616)
This makes duplicate and previous definition handling match. While we
may want to make both point more fine-grained at the name, the necessary
logic seems likely to be equivalent.

Note, I'm looking at this mainly due to duplicate names in imports,
where it's especially helpful to take an instruction instead of a parse
node. We'll eventually want to handle parse nodes from other imports
better, and I think this is the way it would most likely work.
2024-01-18 23:23:31 +00:00

74 lines
2.8 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/check/context.h"
#include "toolchain/check/convert.h"
#include "toolchain/check/modifiers.h"
#include "toolchain/sem_ir/inst.h"
namespace Carbon::Check {
auto HandleLetIntroducer(Context& context, Parse::LetIntroducerId parse_node)
-> bool {
context.decl_state_stack().Push(DeclState::Let);
// Push a bracketing node to establish the pattern context.
context.node_stack().Push(parse_node);
return true;
}
auto HandleLetInitializer(Context& /*context*/,
Parse::LetInitializerId /*parse_node*/) -> bool {
return true;
}
auto HandleLetDecl(Context& context, Parse::LetDeclId parse_node) -> bool {
auto value_id = context.node_stack().PopExpr();
if (context.node_stack().PeekIs<Parse::NodeKind::TuplePattern>()) {
return context.TODO(parse_node, "tuple pattern in let");
}
SemIR::InstId pattern_id = context.node_stack().PopPattern();
context.node_stack()
.PopAndDiscardSoloParseNode<Parse::NodeKind::LetIntroducer>();
// Process declaration modifiers.
CheckAccessModifiersOnDecl(context, Lex::TokenKind::Let);
RequireDefaultFinalOnlyInInterfaces(context, Lex::TokenKind::Let);
LimitModifiersOnDecl(
context, KeywordModifierSet::Access | KeywordModifierSet::Interface,
Lex::TokenKind::Let);
auto modifiers = context.decl_state_stack().innermost().modifier_set;
if (!!(modifiers & KeywordModifierSet::Access)) {
context.TODO(context.decl_state_stack().innermost().saw_access_modifier,
"access modifier");
}
if (!!(modifiers & KeywordModifierSet::Interface)) {
context.TODO(context.decl_state_stack().innermost().saw_decl_modifier,
"interface modifier");
}
context.decl_state_stack().Pop(DeclState::Let);
// Convert the value to match the type of the pattern.
auto pattern = context.insts().GetWithParseNode(pattern_id);
value_id = ConvertToValueOfType(context, parse_node, value_id,
pattern.inst.type_id());
// Update the binding with its value and add it to the current block, after
// the computation of the value.
// TODO: Support other kinds of pattern here.
auto bind_name = pattern.inst.As<SemIR::AnyBindName>();
CARBON_CHECK(!bind_name.value_id.is_valid())
<< "Binding should not already have a value!";
bind_name.value_id = value_id;
pattern.inst = bind_name;
context.ReplaceInstBeforeConstantUse(pattern_id, pattern);
context.inst_block_stack().AddInstId(pattern_id);
// Add the name of the binding to the current scope.
auto name_id = context.bind_names().Get(bind_name.bind_name_id).name_id;
context.AddNameToLookup(name_id, pattern_id);
return true;
}
} // namespace Carbon::Check