Files
carbon-lang/explorer/ast/bindings.h
T
Jon Ross-Perkins 53af8f04b2 Provide a Printable CRTP parent to replace HasPrintable templates. (#3166)
With the toolchain splitting namespaces, ostream.h's `operator<<`
templates aren't reliably found with name lookup, likely due to the loss
of associated namespaces (zygoloid commented on this at
https://github.com/carbon-language/carbon-lang/pull/3161#discussion_r1307941999).
This is especially a barrier to moving the lex files into `Carbon::Lex`;
versus other parts of the toolchain, they contain more printable types
which are used cross-namespace, including `Carbon::Testing`. As a
consequence, I'm looking at migrating ostream.h to a more reliable
approach that doesn't rely as much on everything being in the `Carbon`
namespace.
2023-08-30 21:32:19 +00:00

93 lines
2.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
#ifndef CARBON_EXPLORER_AST_BINDINGS_H_
#define CARBON_EXPLORER_AST_BINDINGS_H_
#include <map>
#include <utility>
#include "common/ostream.h"
#include "explorer/ast/clone_context.h"
#include "explorer/base/nonnull.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
namespace Carbon {
class Arena;
class ImplBinding;
class GenericBinding;
class Value;
using BindingMap =
std::map<Nonnull<const GenericBinding*>, Nonnull<const Value*>>;
using ImplWitnessMap =
std::map<Nonnull<const ImplBinding*>, Nonnull<const Value*>>;
// A set of evaluated bindings in some context, such as a function or class.
//
// These are shared by a context and all unparameterized entities within that
// context. For example, a class and the name of a method within that class
// will have the same set of bindings.
class Bindings : public Printable<Bindings> {
public:
// Gets an empty set of bindings.
static auto None() -> Nonnull<const Bindings*>;
// Makes a set of symbolic identity bindings for the given collection of
// generic bindings and their impl bindings.
static auto SymbolicIdentity(
Nonnull<Arena*> arena,
llvm::ArrayRef<Nonnull<const GenericBinding*>> bindings)
-> Nonnull<const Bindings*>;
// Create an empty set of bindings.
Bindings() = default;
// Create an instantiated set of bindings for use during evaluation,
// containing both arguments and witnesses.
explicit Bindings(BindingMap args, ImplWitnessMap witnesses)
: args_(std::move(args)), witnesses_(std::move(witnesses)) {}
enum NoWitnessesTag { NoWitnesses };
// Create a set of bindings for use during type-checking, containing only the
// arguments but not the corresponding witnesses.
explicit Bindings(BindingMap args, NoWitnessesTag /*unused*/)
: args_(std::move(args)) {}
explicit Bindings(CloneContext& context, const Bindings& other);
template <typename F>
auto Decompose(F f) const {
return f(args_, witnesses_);
}
void Print(llvm::raw_ostream& out) const;
// Add a value, and perhaps a witness, for a generic binding.
void Add(Nonnull<const GenericBinding*> binding, Nonnull<const Value*> value,
std::optional<Nonnull<const Value*>> witness);
// Argument values corresponding to generic bindings.
auto args() const -> const BindingMap& { return args_; }
// Witnesses corresponding to impl bindings.
auto witnesses() const -> const ImplWitnessMap& { return witnesses_; }
// Determine whether this is an empty set of bindings.
[[nodiscard]] auto empty() const -> bool {
return args_.empty() && witnesses_.empty();
}
private:
BindingMap args_;
ImplWitnessMap witnesses_;
};
} // namespace Carbon
#endif // CARBON_EXPLORER_AST_BINDINGS_H_