From d55d3e4c47f3704c54249beffd1fbbc73614dc94 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Fri, 7 Jun 2024 12:03:24 -0700 Subject: [PATCH] Merge check's handle_let and handle_variable files. (#4040) Per request on #4032 --- ...{handle_let.cpp => handle_let_and_var.cpp} | 101 ++++++++++++++++ toolchain/check/handle_variable.cpp | 114 ------------------ 2 files changed, 101 insertions(+), 114 deletions(-) rename toolchain/check/{handle_let.cpp => handle_let_and_var.cpp} (60%) delete mode 100644 toolchain/check/handle_variable.cpp diff --git a/toolchain/check/handle_let.cpp b/toolchain/check/handle_let_and_var.cpp similarity index 60% rename from toolchain/check/handle_let.cpp rename to toolchain/check/handle_let_and_var.cpp index 647e090ad349..b9088c6f0e53 100644 --- a/toolchain/check/handle_let.cpp +++ b/toolchain/check/handle_let_and_var.cpp @@ -22,12 +22,36 @@ auto HandleLetIntroducer(Context& context, Parse::LetIntroducerId node_id) return true; } +auto HandleVariableIntroducer(Context& context, + Parse::VariableIntroducerId node_id) -> bool { + // No action, just a bracketing node. + context.node_stack().Push(node_id); + context.decl_introducer_state_stack().Push(); + return true; +} + +auto HandleReturnedModifier(Context& context, Parse::ReturnedModifierId node_id) + -> bool { + // No action, just a bracketing node. + context.node_stack().Push(node_id); + return true; +} + auto HandleLetInitializer(Context& context, Parse::LetInitializerId node_id) -> bool { context.node_stack().Push(node_id); return true; } +auto HandleVariableInitializer(Context& context, + Parse::VariableInitializerId node_id) -> bool { + if (context.scope_stack().PeekIndex() == ScopeIndex::Package) { + context.inst_block_stack().PushGlobalInit(); + } + context.node_stack().Push(node_id); + return true; +} + static auto BuildAssociatedConstantDecl(Context& context, Parse::LetDeclId node_id, SemIR::InstId pattern_id, @@ -146,4 +170,81 @@ auto HandleLetDecl(Context& context, Parse::LetDeclId node_id) -> bool { return true; } +auto HandleVariableDecl(Context& context, Parse::VariableDeclId node_id) + -> bool { + // Handle the optional initializer. + std::optional init_id; + if (context.node_stack().PeekNextIs()) { + init_id = context.node_stack().PopExpr(); + context.node_stack() + .PopAndDiscardSoloNodeId(); + } + + if (context.node_stack().PeekIs()) { + if (init_id && context.scope_stack().PeekIndex() == ScopeIndex::Package) { + context.inst_block_stack().PopGlobalInit(); + } + return context.TODO(node_id, "tuple pattern in var"); + } + + auto value_id = context.node_stack().PopPattern(); + + // Pop the `returned` specifier if present. + context.node_stack() + .PopAndDiscardSoloNodeIdIf(); + + context.node_stack() + .PopAndDiscardSoloNodeId(); + + // Process declaration modifiers. + // TODO: For a qualified `var` declaration, this should use the target scope + // of the name introduced in the declaration. See #2590. + auto [_, parent_scope_inst] = context.name_scopes().GetInstIfValid( + context.scope_stack().PeekNameScopeId()); + auto introducer = + context.decl_introducer_state_stack().Pop(); + CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst); + LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access); + + // Extract the name binding. + if (auto bind_name = context.insts().TryGetAs(value_id)) { + // Form a corresponding name in the current context, and bind the name to + // the variable. + auto name_context = context.decl_name_stack().MakeUnqualifiedName( + context.insts().GetLocId(value_id), + context.bind_names().Get(bind_name->bind_name_id).name_id); + context.decl_name_stack().AddNameOrDiagnoseDuplicate( + name_context, value_id, introducer.modifier_set.GetAccessKind()); + value_id = bind_name->value_id; + } else if (auto field_decl = + context.insts().TryGetAs(value_id)) { + // Introduce the field name into the class. + auto name_context = context.decl_name_stack().MakeUnqualifiedName( + context.insts().GetLocId(value_id), field_decl->name_id); + context.decl_name_stack().AddNameOrDiagnoseDuplicate( + name_context, value_id, introducer.modifier_set.GetAccessKind()); + } + // TODO: Handle other kinds of pattern. + + // If there was an initializer, assign it to the storage. + if (init_id) { + if (context.GetCurrentScopeAs()) { + // TODO: In a class scope, we should instead save the initializer + // somewhere so that we can use it as a default. + context.TODO(node_id, "Field initializer"); + } else { + init_id = Initialize(context, node_id, value_id, *init_id); + // TODO: Consider using different instruction kinds for assignment versus + // initialization. + context.AddInst(node_id, + {.lhs_id = value_id, .rhs_id = *init_id}); + } + if (context.scope_stack().PeekIndex() == ScopeIndex::Package) { + context.inst_block_stack().PopGlobalInit(); + } + } + + return true; +} + } // namespace Carbon::Check diff --git a/toolchain/check/handle_variable.cpp b/toolchain/check/handle_variable.cpp deleted file mode 100644 index 007265f40dae..000000000000 --- a/toolchain/check/handle_variable.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// 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/handle.h" -#include "toolchain/check/modifiers.h" -#include "toolchain/lex/token_index.h" - -namespace Carbon::Check { - -auto HandleVariableIntroducer(Context& context, - Parse::VariableIntroducerId node_id) -> bool { - // No action, just a bracketing node. - context.node_stack().Push(node_id); - context.decl_introducer_state_stack().Push(); - return true; -} - -auto HandleReturnedModifier(Context& context, Parse::ReturnedModifierId node_id) - -> bool { - // No action, just a bracketing node. - context.node_stack().Push(node_id); - return true; -} - -auto HandleVariableInitializer(Context& context, - Parse::VariableInitializerId node_id) -> bool { - if (context.scope_stack().PeekIndex() == ScopeIndex::Package) { - context.inst_block_stack().PushGlobalInit(); - } - context.node_stack().Push(node_id); - return true; -} - -auto HandleVariableDecl(Context& context, Parse::VariableDeclId node_id) - -> bool { - // Handle the optional initializer. - std::optional init_id; - if (context.node_stack().PeekNextIs()) { - init_id = context.node_stack().PopExpr(); - context.node_stack() - .PopAndDiscardSoloNodeId(); - } - - if (context.node_stack().PeekIs()) { - if (init_id && context.scope_stack().PeekIndex() == ScopeIndex::Package) { - context.inst_block_stack().PopGlobalInit(); - } - return context.TODO(node_id, "tuple pattern in var"); - } - - auto value_id = context.node_stack().PopPattern(); - - // Pop the `returned` specifier if present. - context.node_stack() - .PopAndDiscardSoloNodeIdIf(); - - context.node_stack() - .PopAndDiscardSoloNodeId(); - - // Process declaration modifiers. - // TODO: For a qualified `var` declaration, this should use the target scope - // of the name introduced in the declaration. See #2590. - auto [_, parent_scope_inst] = context.name_scopes().GetInstIfValid( - context.scope_stack().PeekNameScopeId()); - auto introducer = - context.decl_introducer_state_stack().Pop(); - CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst); - LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access); - - // Extract the name binding. - if (auto bind_name = context.insts().TryGetAs(value_id)) { - // Form a corresponding name in the current context, and bind the name to - // the variable. - auto name_context = context.decl_name_stack().MakeUnqualifiedName( - context.insts().GetLocId(value_id), - context.bind_names().Get(bind_name->bind_name_id).name_id); - context.decl_name_stack().AddNameOrDiagnoseDuplicate( - name_context, value_id, introducer.modifier_set.GetAccessKind()); - value_id = bind_name->value_id; - } else if (auto field_decl = - context.insts().TryGetAs(value_id)) { - // Introduce the field name into the class. - auto name_context = context.decl_name_stack().MakeUnqualifiedName( - context.insts().GetLocId(value_id), field_decl->name_id); - context.decl_name_stack().AddNameOrDiagnoseDuplicate( - name_context, value_id, introducer.modifier_set.GetAccessKind()); - } - // TODO: Handle other kinds of pattern. - - // If there was an initializer, assign it to the storage. - if (init_id) { - if (context.GetCurrentScopeAs()) { - // TODO: In a class scope, we should instead save the initializer - // somewhere so that we can use it as a default. - context.TODO(node_id, "Field initializer"); - } else { - init_id = Initialize(context, node_id, value_id, *init_id); - // TODO: Consider using different instruction kinds for assignment versus - // initialization. - context.AddInst(node_id, - {.lhs_id = value_id, .rhs_id = *init_id}); - } - if (context.scope_stack().PeekIndex() == ScopeIndex::Package) { - context.inst_block_stack().PopGlobalInit(); - } - } - - return true; -} - -} // namespace Carbon::Check