Fix equality for tuples (#446)

* fix tuple equality, added test cases

* added a comment to an old function

* Update executable_semantics/interpreter/value.cpp

Co-authored-by: Geoff Romer <gromer@google.com>

* fix error in Geoffrey's edit

Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
Jeremy G. Siek
2021-04-21 17:12:10 -04:00
committed by GitHub
co-authored by Geoff Romer
parent 6639a915dc
commit c1d651fc15
10 changed files with 77 additions and 4 deletions
+3
View File
@@ -62,6 +62,9 @@ EXAMPLES = [
"struct2",
"struct3",
"tuple_assign",
"tuple_equality",
"tuple_equality2",
"tuple_equality3",
"tuple_match",
"tuple1",
"tuple2",
@@ -288,8 +288,7 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
ExpectType(e->line_num, "!", MakeBoolTypeVal(), ts[0]);
return TCResult(new_e, MakeBoolTypeVal(), new_types);
case Operator::Eq:
ExpectType(e->line_num, "==(1)", MakeIntTypeVal(), ts[0]);
ExpectType(e->line_num, "==(2)", MakeIntTypeVal(), ts[1]);
ExpectType(e->line_num, "==", ts[0], ts[1]);
return TCResult(new_e, MakeBoolTypeVal(), new_types);
}
break;
+29 -1
View File
@@ -4,6 +4,7 @@
#include "executable_semantics/interpreter/value.h"
#include <algorithm>
#include <cassert>
#include <iostream>
@@ -360,6 +361,31 @@ auto TypeEqual(const Value* t1, const Value* t2) -> bool {
}
}
// Returns true if all the fields of the two tuples contain equal values
// and returns false otherwise.
static auto FieldsValueEqual(VarAddresses* ts1, VarAddresses* ts2, int line_num)
-> bool {
if (ts1->size() != ts2->size()) {
return false;
}
for (const auto& [name, address] : *ts1) {
auto iter =
std::find_if(ts2->begin(), ts2->end(),
[name = name](const auto& p) { return p.first == name; });
if (iter == ts2->end()) {
return false;
}
if (!ValueEqual(state->heap[address], state->heap[iter->second],
line_num)) {
return false;
}
}
return true;
}
// Returns true if the two values are equal and returns false otherwise.
//
// This function implements the `==` operator of Carbon.
auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool {
if (v1->tag != v2->tag) {
return false;
@@ -373,6 +399,9 @@ auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool {
return v1->u.ptr == v2->u.ptr;
case ValKind::FunV:
return v1->u.fun.body == v2->u.fun.body;
case ValKind::TupleV:
return FieldsValueEqual(v1->u.tuple.elts, v2->u.tuple.elts, line_num);
default:
case ValKind::VarTV:
case ValKind::IntTV:
case ValKind::BoolTV:
@@ -384,7 +413,6 @@ auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool {
case ValKind::ChoiceTV:
case ValKind::ContinuationTV:
return TypeEqual(v1, v2);
case ValKind::TupleV:
case ValKind::StructV:
case ValKind::AltV:
case ValKind::VarPatV:
+2 -1
View File
@@ -17,6 +17,7 @@ namespace Carbon {
struct Value;
using Address = unsigned int;
using VarValues = std::list<std::pair<std::string, const Value*>>;
using VarAddresses = std::vector<std::pair<std::string, Address>>;
auto FindInVarValues(const std::string& field, VarValues* inits)
-> const Value*;
@@ -81,7 +82,7 @@ struct Value {
} alt;
struct {
std::vector<std::pair<std::string, Address>>* elts;
VarAddresses* elts;
} tuple;
Address ptr;
+13
View File
@@ -0,0 +1,13 @@
// 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
fn main() -> Int {
var (Int,Int): t1 = (5, 2);
var (Int,Int): t2 = (5, 2);
if (t1 == t2) {
return 0;
} else {
return 1;
}
}
+1
View File
@@ -0,0 +1 @@
result: 0
+13
View File
@@ -0,0 +1,13 @@
// 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
fn main() -> Int {
var (Int,Int): t1 = (5, 2);
var (Int,Int): t2 = (5, 4);
if (t1 == t2) {
return 1;
} else {
return 0;
}
}
+1
View File
@@ -0,0 +1 @@
result: 0
+13
View File
@@ -0,0 +1,13 @@
// 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
fn main() -> Int {
var (Int,Int): t1 = (5, 2);
var (Int,Int): t2 = (5,);
if (t1 == t2) {
return 1;
} else {
return 0;
}
}
+1
View File
@@ -0,0 +1 @@
result: 0