forked from carbon-language/carbon-lang
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bindings.cpp
88 lines (74 loc) · 2.99 KB
/
bindings.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// 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";
}
}
void Bindings::Print(llvm::raw_ostream& out) const {
std::vector<std::pair<Nonnull<const GenericBinding*>, Nonnull<const Value*>>>
args(args_.begin(), args_.end());
std::vector<std::pair<Nonnull<const ImplBinding*>, Nonnull<const Value*>>>
witnesses(witnesses_.begin(), witnesses_.end());
std::stable_sort(args.begin(), args.end(), [](const auto& a, const auto& b) {
return a.first->index() < b.first->index();
});
std::stable_sort(
witnesses.begin(), witnesses.end(), [](const auto& a, const auto& b) {
return a.first->type_var()->index() < b.first->type_var()->index();
});
llvm::ListSeparator sep;
out << " > bindings args: [";
for (const auto& [binding, value] : args) {
out << sep << "`" << *binding << "`: `" << *value << "`";
}
out << "]\n > bindings witnesses: [";
for (const auto& [binding, value] : witnesses) {
out << sep << "`" << *binding << "`: `" << *value << "`";
}
out << "]";
}
auto Bindings::None() -> Nonnull<const Bindings*> {
static Nonnull<const Bindings*> bindings = new Bindings;
return bindings;
}
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