Unify StructElement and VarValues (#909)

This commit is contained in:
Geoff Romer
2021-10-27 16:33:38 -07:00
committed by GitHub
parent 2e5fa7c453
commit 0da907fd2a
4 changed files with 96 additions and 130 deletions
+30 -61
View File
@@ -17,36 +17,9 @@ namespace Carbon {
using llvm::cast;
auto FindInVarValues(const std::string& field, const VarValues& inits)
-> std::optional<Nonnull<const Value*>> {
for (auto& i : inits) {
if (i.first == field) {
return i.second;
}
}
return std::nullopt;
}
auto FieldsEqual(const VarValues& ts1, const VarValues& ts2) -> bool {
if (ts1.size() == ts2.size()) {
for (auto& iter1 : ts1) {
auto t2 = FindInVarValues(iter1.first, ts2);
if (!t2) {
return false;
}
if (!TypeEqual(iter1.second, *t2)) {
return false;
}
}
return true;
} else {
return false;
}
}
auto StructValue::FindField(const std::string& name) const
-> std::optional<Nonnull<const Value*>> {
for (const StructElement& element : elements_) {
for (const NamedValue& element : elements_) {
if (element.name == name) {
return element.value;
}
@@ -78,7 +51,7 @@ auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
}
case Value::Kind::ChoiceType: {
const auto& choice = cast<ChoiceType>(*v);
if (!FindInVarValues(f, choice.alternatives())) {
if (!choice.FindAlternative(f)) {
FATAL_RUNTIME_ERROR(source_loc)
<< "alternative " << f << " not in " << *v;
}
@@ -112,10 +85,9 @@ auto SetFieldImpl(Nonnull<Arena*> arena, Nonnull<const Value*> value,
}
switch (value->kind()) {
case Value::Kind::StructValue: {
std::vector<StructElement> elements =
cast<StructValue>(*value).elements();
std::vector<NamedValue> elements = cast<StructValue>(*value).elements();
auto it = std::find_if(elements.begin(), elements.end(),
[path_begin](const StructElement& element) {
[path_begin](const NamedValue& element) {
return element.name == *path_begin;
});
if (it == elements.end()) {
@@ -185,7 +157,7 @@ void Value::Print(llvm::raw_ostream& out) const {
const auto& struct_val = cast<StructValue>(*this);
out << "{";
llvm::ListSeparator sep;
for (const StructElement& element : struct_val.elements()) {
for (const NamedValue& element : struct_val.elements()) {
out << sep << "." << element.name << " = " << *element.value;
}
out << "}";
@@ -313,9 +285,8 @@ auto TypeEqual(Nonnull<const Value*> t1, Nonnull<const Value*> t2) -> bool {
return false;
}
for (size_t i = 0; i < struct1.fields().size(); ++i) {
if (struct1.fields()[i].first != struct2.fields()[i].first ||
!TypeEqual(struct1.fields()[i].second,
struct2.fields()[i].second)) {
if (struct1.fields()[i].name != struct2.fields()[i].name ||
!TypeEqual(struct1.fields()[i].value, struct2.fields()[i].value)) {
return false;
}
}
@@ -354,28 +325,6 @@ auto TypeEqual(Nonnull<const Value*> t1, Nonnull<const Value*> t2) -> bool {
}
}
// Returns true if all the fields of the two tuples contain equal values
// and returns false otherwise.
static auto FieldsValueEqual(const std::vector<StructElement>& ts1,
const std::vector<StructElement>& ts2,
SourceLocation source_loc) -> bool {
if (ts1.size() != ts2.size()) {
return false;
}
for (const StructElement& element : ts1) {
auto iter = std::find_if(
ts2.begin(), ts2.end(),
[&](const StructElement& e2) { return e2.name == element.name; });
if (iter == ts2.end()) {
return false;
}
if (!ValueEqual(element.value, iter->value, source_loc)) {
return false;
}
}
return true;
}
// Returns true if the two values are equal and returns false otherwise.
//
// This function implements the `==` operator of Carbon.
@@ -414,9 +363,19 @@ auto ValueEqual(Nonnull<const Value*> v1, Nonnull<const Value*> v2,
}
return true;
}
case Value::Kind::StructValue:
return FieldsValueEqual(cast<StructValue>(*v1).elements(),
cast<StructValue>(*v2).elements(), source_loc);
case Value::Kind::StructValue: {
const auto& struct_v1 = cast<StructValue>(*v1);
const auto& struct_v2 = cast<StructValue>(*v2);
CHECK(struct_v1.elements().size() == struct_v2.elements().size());
for (size_t i = 0; i < struct_v1.elements().size(); ++i) {
CHECK(struct_v1.elements()[i].name == struct_v2.elements()[i].name);
if (!ValueEqual(struct_v1.elements()[i].value,
struct_v2.elements()[i].value, source_loc)) {
return false;
}
}
return true;
}
case Value::Kind::StringValue:
return cast<StringValue>(*v1).value() == cast<StringValue>(*v2).value();
case Value::Kind::IntType:
@@ -441,4 +400,14 @@ auto ValueEqual(Nonnull<const Value*> v1, Nonnull<const Value*> v2,
}
}
auto ChoiceType::FindAlternative(std::string_view name) const
-> std::optional<Nonnull<const Value*>> {
for (const NamedValue& alternative : alternatives_) {
if (alternative.name == name) {
return alternative.value;
}
}
return std::nullopt;
}
} // namespace Carbon