Unify tuple types with tuples-of-types in the interpreter (#442)

This commit is contained in:
Geoff Romer
2021-04-12 16:13:00 -07:00
committed by GitHub
parent 22656c8e09
commit cf7c97bf28
7 changed files with 82 additions and 149 deletions
+33 -29
View File
@@ -4,6 +4,7 @@
#include "executable_semantics/interpreter/value.h"
#include <cassert>
#include <iostream>
#include "executable_semantics/interpreter/interpreter.h"
@@ -37,6 +38,17 @@ auto FieldsEqual(VarValues* ts1, VarValues* ts2) -> bool {
}
}
auto FindTupleField(const std::string& name, const Value* tuple)
-> std::optional<Address> {
assert(tuple->tag == ValKind::TupleV);
for (const auto& i : *tuple->u.tuple.elts) {
if (i.first == name) {
return i.second;
}
}
return std::nullopt;
}
auto MakeIntVal(int i) -> const Value* {
auto* v = new Value();
v->tag = ValKind::IntV;
@@ -183,17 +195,10 @@ auto MakeStructTypeVal(std::string name, VarValues* fields, VarValues* methods)
return v;
}
auto MakeTupleTypeVal(VarValues* fields) -> const Value* {
auto* v = new Value();
v->tag = ValKind::TupleTV;
v->u.tuple_type.fields = fields;
return v;
}
auto MakeVoidTypeVal() -> const Value* {
auto* v = new Value();
v->tag = ValKind::TupleTV;
v->u.tuple_type.fields = new VarValues();
v->tag = ValKind::TupleV;
v->u.tuple.elts = new std::vector<std::pair<std::string, Address>>();
return v;
}
@@ -288,22 +293,6 @@ void PrintValue(const Value* val, std::ostream& out) {
case ValKind::VarTV:
out << *val->u.var_type;
break;
case ValKind::TupleTV: {
out << "Tuple(";
bool add_commas = false;
for (const auto& elt : *val->u.tuple_type.fields) {
if (add_commas) {
out << ", ";
} else {
add_commas = true;
}
out << elt.first << " = ";
PrintValue(elt.second, out);
}
out << ")";
break;
}
case ValKind::StructTV:
out << "struct " << *val->u.struct_type.name;
break;
@@ -337,14 +326,30 @@ auto TypeEqual(const Value* t1, const Value* t2) -> bool {
return *t1->u.struct_type.name == *t2->u.struct_type.name;
case ValKind::ChoiceTV:
return *t1->u.choice_type.name == *t2->u.choice_type.name;
case ValKind::TupleTV:
return FieldsEqual(t1->u.tuple_type.fields, t2->u.tuple_type.fields);
case ValKind::TupleV: {
if (t1->u.tuple.elts->size() != t2->u.tuple.elts->size()) {
return false;
}
for (size_t i = 0; i < t1->u.tuple.elts->size(); ++i) {
std::optional<Address> t2_field =
FindTupleField((*t1->u.tuple.elts)[i].first, t2);
if (t2_field == std::nullopt) {
return false;
}
if (!TypeEqual(state->heap[(*t1->u.tuple.elts)[i].second],
state->heap[*t2_field])) {
return false;
}
}
return true;
}
case ValKind::IntTV:
case ValKind::BoolTV:
case ValKind::ContinuationTV:
return true;
default:
return false;
std::cerr << "TypeEqual used to compare non-type values" << std::endl;
exit(-1);
}
}
@@ -370,7 +375,6 @@ auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool {
case ValKind::FunctionTV:
case ValKind::PointerTV:
case ValKind::AutoTV:
case ValKind::TupleTV:
case ValKind::StructTV:
case ValKind::ChoiceTV:
case ValKind::ContinuationTV: