mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
See arena.h for discussion of what canonicalization means in this context. This is primarily intended to support implementing a memo table of template instantiations to resolve #2951, but could be useful for other purposes as well. Additional changes: - Pass `VTable` constructor parameters by pointer, to avoid the need to define `operator==` and `hash_value` for it. - Clean up the recurring pattern of allocating identical `NamedElement`s on the stack and heap. Instead we always allocate it on the heap and pass it by pointer. - Add `Print()` and `Dump()` to `Bindings` as a debugging convenience. --------- Co-authored-by: Jon Ross-Perkins <jperkins@google.com> Co-authored-by: Richard Smith <richard@metafoo.co.uk>
73 lines
2.3 KiB
C++
73 lines
2.3 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 "explorer/ast/bindings.h"
|
|
|
|
#include "common/error.h"
|
|
#include "explorer/ast/impl_binding.h"
|
|
#include "explorer/ast/pattern.h"
|
|
#include "explorer/ast/value.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
namespace Carbon {
|
|
|
|
Bindings::Bindings(CloneContext& context, const Bindings& other) {
|
|
for (auto [binding, value] : other.args_) {
|
|
args_.insert({context.Remap(binding), context.Clone(value)});
|
|
}
|
|
for (auto [binding, value] : other.witnesses_) {
|
|
witnesses_.insert({context.Remap(binding), context.Clone(value)});
|
|
}
|
|
}
|
|
|
|
void Bindings::Add(Nonnull<const GenericBinding*> binding,
|
|
Nonnull<const Value*> value,
|
|
std::optional<Nonnull<const Value*>> witness) {
|
|
bool added_value = args_.insert({binding, value}).second;
|
|
CARBON_CHECK(added_value) << "Add of already-existing binding";
|
|
|
|
if (witness) {
|
|
// TODO: Eventually we should check that we have a witness if and only if
|
|
// the binding has an impl binding.
|
|
auto impl_binding = binding->impl_binding();
|
|
CARBON_CHECK(impl_binding) << "Given witness but have no impl binding";
|
|
bool added_witness = witnesses_.insert({*impl_binding, *witness}).second;
|
|
CARBON_CHECK(added_witness) << "Add of already-existing binding";
|
|
}
|
|
}
|
|
|
|
auto Bindings::None() -> Nonnull<const Bindings*> {
|
|
static Nonnull<const Bindings*> bindings = new Bindings;
|
|
return bindings;
|
|
}
|
|
|
|
void Bindings::Print(llvm::raw_ostream& out) const {
|
|
out << "{";
|
|
llvm::ListSeparator sep;
|
|
for (const auto& [name, value] : args_) {
|
|
out << sep << *name << " -> " << *value;
|
|
}
|
|
for (const auto& [name, value] : witnesses_) {
|
|
out << sep << *name << " -> " << *value;
|
|
}
|
|
out << "}";
|
|
}
|
|
|
|
auto Bindings::SymbolicIdentity(
|
|
Nonnull<Arena*> arena,
|
|
llvm::ArrayRef<Nonnull<const GenericBinding*>> bindings)
|
|
-> Nonnull<const Bindings*> {
|
|
auto* result = arena->New<Bindings>();
|
|
for (const auto* binding : bindings) {
|
|
std::optional<Nonnull<const Value*>> witness;
|
|
if (binding->impl_binding()) {
|
|
witness = *binding->impl_binding().value()->symbolic_identity();
|
|
}
|
|
result->Add(binding, *binding->symbolic_identity(), witness);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
} // namespace Carbon
|