mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
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.
74 lines
2.8 KiB
C++
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
|