Stop using std::pair in the implementation of tuples (#479)

This commit is contained in:
Geoff Romer
2021-04-26 11:43:06 -07:00
committed by GitHub
parent 3ff01fa60d
commit 1933cfeeeb
10 changed files with 127 additions and 139 deletions
@@ -66,14 +66,14 @@ void Heap::CheckAlive(Address address, int line_num) {
auto CopyVal(const Value* val, int line_num) -> const Value* {
switch (val->tag) {
case ValKind::TupleV: {
auto elts = new std::vector<std::pair<std::string, Address>>();
for (auto& i : *val->u.tuple.elts) {
const Value* elt =
CopyVal(state->heap.Read(i.second, line_num), line_num);
Address new_address = state->heap.AllocateValue(elt);
elts->push_back(make_pair(i.first, new_address));
auto* elements = new std::vector<TupleElement>();
for (const TupleElement& element : *val->u.tuple.elements) {
const Value* new_element =
CopyVal(state->heap.Read(element.address, line_num), line_num);
Address new_address = state->heap.AllocateValue(new_element);
elements->push_back({.name = element.name, .address = new_address});
}
return MakeTupleVal(elts);
return MakeTupleVal(elements);
}
case ValKind::AltV: {
const Value* arg =
@@ -133,8 +133,8 @@ void Heap::DeallocateSubObjects(const Value* val) {
DeallocateSubObjects(val->u.struct_val.inits);
break;
case ValKind::TupleV:
for (auto& elt : *val->u.tuple.elts) {
Deallocate(elt.second);
for (const TupleElement& element : *val->u.tuple.elements) {
Deallocate(element.address);
}
break;
default:
@@ -411,13 +411,13 @@ void DeallocateLocals(int line_num, Frame* frame) {
void CreateTuple(Frame* frame, Action* act, const Expression* /*exp*/) {
// { { (v1,...,vn) :: C, E, F} :: S, H}
// -> { { `(v1,...,vn) :: C, E, F} :: S, H}
auto elts = new std::vector<std::pair<std::string, Address>>();
auto elements = new std::vector<TupleElement>();
auto f = act->u.exp->u.tuple.fields->begin();
for (auto i = act->results.begin(); i != act->results.end(); ++i, ++f) {
Address a = state->heap.AllocateValue(*i); // copy?
elts->push_back(make_pair(f->first, a));
elements->push_back({.name = f->name, .address = a});
}
const Value* tv = MakeTupleVal(elts);
const Value* tv = MakeTupleVal(elements);
frame->todo.Pop(1);
frame->todo.Push(MakeValAct(tv));
}
@@ -440,21 +440,21 @@ auto PatternMatch(const Value* p, const Value* v, Env values,
case ValKind::TupleV:
switch (v->tag) {
case ValKind::TupleV: {
if (p->u.tuple.elts->size() != v->u.tuple.elts->size()) {
if (p->u.tuple.elements->size() != v->u.tuple.elements->size()) {
std::cerr << "runtime error: arity mismatch in tuple pattern match"
<< std::endl;
exit(-1);
}
for (auto& elt : *p->u.tuple.elts) {
auto a = FindTupleField(elt.first, v);
for (const TupleElement& element : *p->u.tuple.elements) {
auto a = FindTupleField(element.name, v);
if (a == std::nullopt) {
std::cerr << "runtime error: field " << elt.first << "not in ";
std::cerr << "runtime error: field " << element.name << "not in ";
PrintValue(v, std::cerr);
std::cerr << std::endl;
exit(-1);
}
std::optional<Env> matches = PatternMatch(
state->heap.Read(elt.second, line_num),
state->heap.Read(element.address, line_num),
state->heap.Read(*a, line_num), values, vars, line_num);
if (!matches) {
return std::nullopt;
@@ -526,20 +526,20 @@ void PatternAssignment(const Value* pat, const Value* val, int line_num) {
case ValKind::TupleV: {
switch (val->tag) {
case ValKind::TupleV: {
if (pat->u.tuple.elts->size() != val->u.tuple.elts->size()) {
if (pat->u.tuple.elements->size() != val->u.tuple.elements->size()) {
std::cerr << "runtime error: arity mismatch in tuple pattern match"
<< std::endl;
exit(-1);
}
for (auto& elt : *pat->u.tuple.elts) {
auto a = FindTupleField(elt.first, val);
for (const TupleElement& element : *pat->u.tuple.elements) {
auto a = FindTupleField(element.name, val);
if (a == std::nullopt) {
std::cerr << "runtime error: field " << elt.first << "not in ";
std::cerr << "runtime error: field " << element.name << "not in ";
PrintValue(val, std::cerr);
std::cerr << std::endl;
exit(-1);
}
PatternAssignment(state->heap.Read(elt.second, line_num),
PatternAssignment(state->heap.Read(element.address, line_num),
state->heap.Read(*a, line_num), line_num);
}
break;
@@ -629,7 +629,7 @@ void StepLvalue() {
case ExpressionKind::Tuple: {
// { {(f1=e1,...) :: C, E, F} :: S, H}
// -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H}
const Expression* e1 = (*exp->u.tuple.fields)[0].second;
const Expression* e1 = (*exp->u.tuple.fields)[0].expression;
frame->todo.Push(MakeLvalAct(e1));
act->pos++;
break;
@@ -680,7 +680,7 @@ void StepExp() {
if (exp->u.tuple.fields->size() > 0) {
// { {(f1=e1,...) :: C, E, F} :: S, H}
// -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H}
const Expression* e1 = (*exp->u.tuple.fields)[0].second;
const Expression* e1 = (*exp->u.tuple.fields)[0].expression;
frame->todo.Push(MakeExpAct(e1));
act->pos++;
} else {
@@ -1090,7 +1090,7 @@ void HandleValue() {
// H}
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
// H}
const Expression* elt = (*exp->u.tuple.fields)[act->pos].second;
const Expression* elt = (*exp->u.tuple.fields)[act->pos].expression;
frame->todo.Pop(1);
frame->todo.Push(MakeLvalAct(elt));
} else {
@@ -1122,7 +1122,7 @@ void HandleValue() {
// H}
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
// H}
const Expression* elt = (*exp->u.tuple.fields)[act->pos].second;
const Expression* elt = (*exp->u.tuple.fields)[act->pos].expression;
frame->todo.Pop(1);
frame->todo.Push(MakeExpAct(elt));
} else {
@@ -1467,8 +1467,7 @@ auto InterpProgram(std::list<Declaration>* fs) -> int {
}
InitGlobals(fs);
const Expression* arg = MakeTuple(
0, new std::vector<std::pair<std::string, const Expression*>>());
const Expression* arg = MakeTuple(0, new std::vector<FieldInitializer>());
const Expression* call_main = MakeCall(0, MakeVar(0, "main"), arg);
auto todo = Stack(MakeExpAct(call_main));
auto* scope = new Scope(globals, std::list<std::string>());
+27 -30
View File
@@ -57,11 +57,12 @@ auto ReifyType(const Value* t, int line_num) -> const Expression* {
return MakeFunType(0, ReifyType(t->u.fun_type.param, line_num),
ReifyType(t->u.fun_type.ret, line_num));
case ValKind::TupleV: {
auto args = new std::vector<std::pair<std::string, const Expression*>>();
for (auto& field : *t->u.tuple.elts) {
auto args = new std::vector<FieldInitializer>();
for (const TupleElement& field : *t->u.tuple.elements) {
args->push_back(
{field.first,
ReifyType(state->heap.Read(field.second, line_num), line_num)});
{.name = field.name,
.expression = ReifyType(state->heap.Read(field.address, line_num),
line_num)});
}
return MakeTuple(0, args);
}
@@ -172,9 +173,8 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
}
}
case ExpressionKind::Tuple: {
auto new_args =
new std::vector<std::pair<std::string, const Expression*>>();
auto arg_types = new std::vector<std::pair<std::string, Address>>();
auto new_args = new std::vector<FieldInitializer>();
auto arg_types = new std::vector<TupleElement>();
auto new_types = types;
if (expected && expected->tag != ValKind::TupleV) {
std::cerr << e->line_num << ": compilation error, didn't expect a tuple"
@@ -182,7 +182,7 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
exit(-1);
}
if (expected &&
e->u.tuple.fields->size() != expected->u.tuple.elts->size()) {
e->u.tuple.fields->size() != expected->u.tuple.elements->size()) {
std::cerr << e->line_num
<< ": compilation error, tuples of different length"
<< std::endl;
@@ -193,22 +193,23 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
arg != e->u.tuple.fields->end(); ++arg, ++i) {
const Value* arg_expected = nullptr;
if (expected && expected->tag == ValKind::TupleV) {
if ((*expected->u.tuple.elts)[i].first != arg->first) {
if ((*expected->u.tuple.elements)[i].name != arg->name) {
std::cerr << e->line_num
<< ": compilation error, field names do not match, "
<< "expected " << (*expected->u.tuple.elts)[i].first
<< " but got " << arg->first << std::endl;
<< "expected " << (*expected->u.tuple.elements)[i].name
<< " but got " << arg->name << std::endl;
exit(-1);
}
arg_expected = state->heap.Read((*expected->u.tuple.elts)[i].second,
e->line_num);
arg_expected = state->heap.Read(
(*expected->u.tuple.elements)[i].address, e->line_num);
}
auto arg_res =
TypeCheckExp(arg->second, new_types, values, arg_expected, context);
auto arg_res = TypeCheckExp(arg->expression, new_types, values,
arg_expected, context);
new_types = arg_res.types;
new_args->push_back(std::make_pair(arg->first, arg_res.exp));
new_args->push_back({.name = arg->name, .expression = arg_res.exp});
arg_types->push_back(
{arg->first, state->heap.AllocateValue(arg_res.type)});
{.name = arg->name,
.address = state->heap.AllocateValue(arg_res.type)});
}
auto tuple_e = MakeTuple(e->line_num, new_args);
auto tuple_t = MakeTupleVal(arg_types);
@@ -241,12 +242,12 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
<< *e->u.get_field.field << std::endl;
exit(-1);
case ValKind::TupleV:
for (auto& field : *t->u.tuple.elts) {
if (*e->u.get_field.field == field.first) {
for (const TupleElement& field : *t->u.tuple.elements) {
if (*e->u.get_field.field == field.name) {
auto new_e =
MakeGetField(e->line_num, res.exp, *e->u.get_field.field);
return TCResult(new_e,
state->heap.Read(field.second, e->line_num),
state->heap.Read(field.address, e->line_num),
res.types);
}
}
@@ -534,8 +535,7 @@ auto CheckOrEnsureReturn(const Statement* stmt, bool void_return, int line_num)
-> const Statement* {
if (!stmt) {
if (void_return) {
auto args = new std::vector<std::pair<std::string, const Expression*>>();
return MakeReturn(line_num, MakeTuple(line_num, args));
return MakeReturn(line_num, MakeUnit(line_num));
} else {
std::cerr
<< "control-flow reaches end of non-void function without a return"
@@ -586,11 +586,8 @@ auto CheckOrEnsureReturn(const Statement* stmt, bool void_return, int line_num)
case StatementKind::Continue:
case StatementKind::VariableDefinition:
if (void_return) {
auto args =
new std::vector<std::pair<std::string, const Expression*>>();
return MakeSeq(
stmt->line_num, stmt,
MakeReturn(stmt->line_num, MakeTuple(stmt->line_num, args)));
return MakeSeq(stmt->line_num, stmt,
MakeReturn(stmt->line_num, MakeUnit(stmt->line_num)));
} else {
std::cerr
<< stmt->line_num
@@ -718,10 +715,10 @@ auto StructDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
auto st = TypeOfStructDef(&definition, tops.types, tops.values);
Address a = state->heap.AllocateValue(st);
tops.values.Set(Name(), a); // Is this obsolete?
auto field_types = new std::vector<std::pair<std::string, Address>>();
auto field_types = new std::vector<TupleElement>();
for (const auto& [field_name, field_value] : *st->u.struct_type.fields) {
field_types->push_back(
{field_name, state->heap.AllocateValue(field_value)});
field_types->push_back({.name = field_name,
.address = state->heap.AllocateValue(field_value)});
}
auto fun_ty = MakeFunTypeVal(MakeTupleVal(field_types), st);
tops.types.Set(Name(), fun_ty);
+27 -24
View File
@@ -42,9 +42,9 @@ 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;
for (const TupleElement& element : *tuple->u.tuple.elements) {
if (element.name == name) {
return element.address;
}
}
return std::nullopt;
@@ -89,11 +89,10 @@ auto MakeStructVal(const Value* type, const Value* inits) -> const Value* {
return v;
}
auto MakeTupleVal(std::vector<std::pair<std::string, Address>>* elts)
-> const Value* {
auto MakeTupleVal(std::vector<TupleElement>* elements) -> const Value* {
auto* v = new Value();
v->tag = ValKind::TupleV;
v->u.tuple.elts = elts;
v->u.tuple.elements = elements;
return v;
}
@@ -199,7 +198,7 @@ auto MakeStructTypeVal(std::string name, VarValues* fields, VarValues* methods)
auto MakeVoidTypeVal() -> const Value* {
auto* v = new Value();
v->tag = ValKind::TupleV;
v->u.tuple.elts = new std::vector<std::pair<std::string, Address>>();
v->u.tuple.elements = new std::vector<TupleElement>();
return v;
}
@@ -239,16 +238,16 @@ auto PrintValue(const Value* val, std::ostream& out) -> void {
case ValKind::TupleV: {
out << "(";
bool add_commas = false;
for (const auto& elt : *val->u.tuple.elts) {
for (const TupleElement& element : *val->u.tuple.elements) {
if (add_commas) {
out << ", ";
} else {
add_commas = true;
}
out << elt.first << " = ";
state->heap.PrintAddress(elt.second, out);
out << "@" << elt.second;
out << element.name << " = ";
state->heap.PrintAddress(element.address, out);
out << "@" << element.address;
}
out << ")";
break;
@@ -328,15 +327,17 @@ auto TypeEqual(const Value* t1, const Value* t2) -> bool {
case ValKind::ChoiceTV:
return *t1->u.choice_type.name == *t2->u.choice_type.name;
case ValKind::TupleV: {
if (t1->u.tuple.elts->size() != t2->u.tuple.elts->size()) {
if (t1->u.tuple.elements->size() != t2->u.tuple.elements->size()) {
return false;
}
for (size_t i = 0; i < t1->u.tuple.elts->size(); ++i) {
if ((*t1->u.tuple.elts)[i].first != (*t2->u.tuple.elts)[i].first) {
for (size_t i = 0; i < t1->u.tuple.elements->size(); ++i) {
if ((*t1->u.tuple.elements)[i].name !=
(*t2->u.tuple.elements)[i].name) {
return false;
}
if (!TypeEqual(state->heap.Read((*t1->u.tuple.elts)[i].second, 0),
state->heap.Read((*t2->u.tuple.elts)[i].second, 0))) {
if (!TypeEqual(
state->heap.Read((*t1->u.tuple.elements)[i].address, 0),
state->heap.Read((*t2->u.tuple.elements)[i].address, 0))) {
return false;
}
}
@@ -358,20 +359,21 @@ 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)
static auto FieldsValueEqual(std::vector<TupleElement>* ts1,
std::vector<TupleElement>* 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; });
for (const TupleElement& element : *ts1) {
auto iter = std::find_if(
ts2->begin(), ts2->end(),
[&](const TupleElement& e2) { return e2.name == element.name; });
if (iter == ts2->end()) {
return false;
}
if (!ValueEqual(state->heap.Read(address, line_num),
state->heap.Read(iter->second, line_num), line_num)) {
if (!ValueEqual(state->heap.Read(element.address, line_num),
state->heap.Read(iter->address, line_num), line_num)) {
return false;
}
}
@@ -395,7 +397,8 @@ auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool {
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);
return FieldsValueEqual(v1->u.tuple.elements, v2->u.tuple.elements,
line_num);
default:
case ValKind::VarTV:
case ValKind::IntTV:
+11 -4
View File
@@ -17,7 +17,6 @@ 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*;
@@ -28,6 +27,15 @@ auto FieldsEqual(VarValues* ts1, VarValues* ts2) -> bool;
auto FindTupleField(const std::string& name, const Value* tuple)
-> std::optional<Address>;
// A TupleElement represents the value of a single tuple field.
struct TupleElement {
// The field name.
std::string name;
// Location of the field's value.
Address address;
};
enum class ValKind {
IntV,
FunV,
@@ -82,7 +90,7 @@ struct Value {
} alt;
struct {
VarAddresses* elts;
std::vector<TupleElement>* elements;
} tuple;
Address ptr;
@@ -134,8 +142,7 @@ auto MakeFunVal(std::string name, const Value* param, const Statement* body)
-> const Value*;
auto MakePtrVal(Address addr) -> const Value*;
auto MakeStructVal(const Value* type, const Value* inits) -> const Value*;
auto MakeTupleVal(std::vector<std::pair<std::string, Address>>* elts)
-> const Value*;
auto MakeTupleVal(std::vector<TupleElement>* elts) -> const Value*;
auto MakeAltVal(std::string alt_name, std::string choice_name, Address argument)
-> const Value*;
auto MakeAltCons(std::string alt_name, std::string choice_name) -> const Value*;