mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-11-14 05:08:32 +00:00
When building an expression referencing the result of name lookup, if the lookup result is non-constant then check we can access it from the current scope. * If it is a global, then use a new `GlobalRef` instruction to get the value of that global. In lowering, create global variables to hold the values of global `let` bindings so that `GlobalRef` can access those values. * If it is a local, walk the lexical scopes between it and the point of use and ensure it is usable through from all of them. Error if there's an intervening declarative scope such as a class, add a TODO to handle captures for intervening functions, and allow `typeof(...)` to name things it can't read the value of since it's unevaluated. Global `let`s (which includes `let`s at class scope) now also have their initializers collected into the global inits block. If the initializer is non-constant, the wrapper binding also lives in the global inits block; otherwise it continues to live in the file block and the variable emitted for it is a global constant. Assisted-by: Gemini and Claude via Antigravity
50 lines
1.9 KiB
C++
50 lines
1.9 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/full_pattern_stack.h"
|
|
|
|
#include "toolchain/check/context.h"
|
|
#include "toolchain/check/pattern.h"
|
|
|
|
namespace Carbon::Check {
|
|
|
|
auto FullPatternStack::StartPatternInitializer() -> void {
|
|
CARBON_CHECK(IsAnyNameBindingDeclKind(kind_stack_.back()));
|
|
for (auto& [name_id, inst_id] : bind_name_stack_.PeekArray()) {
|
|
CARBON_CHECK(
|
|
inst_id == SemIR::InstId::InitTombstone,
|
|
"stashing the lookup result would overwrite an existing stash {0}",
|
|
inst_id);
|
|
auto& lookup_result = lookup_->Get(name_id);
|
|
if (!lookup_result.empty()) {
|
|
// Temporarily overwrite the result of name lookup for this binding to be
|
|
// `InitTombstone`, so that references to it in the initializer are
|
|
// diagnosed as errors. The original result of name lookup is stashed in
|
|
// `bind_name_stack_` so we can restore it later.
|
|
//
|
|
// TODO: find a way to preserve location information, so that we can
|
|
// provide good diagnostics for a redeclaration of `name_id` in
|
|
// the initializer, if that becomes possible.
|
|
std::swap(lookup_result.back().inst_id, inst_id);
|
|
}
|
|
}
|
|
next_var_index_stack_.back() = 0;
|
|
}
|
|
|
|
auto FullPatternStack::EndPatternInitializer() -> void {
|
|
for (auto& [name_id, inst_id] : bind_name_stack_.PeekArray()) {
|
|
auto& lookup_result = lookup_->Get(name_id);
|
|
if (!lookup_result.empty()) {
|
|
// Restore the original result of name lookup for this binding.
|
|
std::swap(lookup_result.back().inst_id, inst_id);
|
|
}
|
|
CARBON_CHECK(inst_id == SemIR::InstId::InitTombstone,
|
|
"name_id resolved to a non-tombstone value {0} during "
|
|
"initializer handling",
|
|
inst_id);
|
|
}
|
|
}
|
|
|
|
} // namespace Carbon::Check
|