mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Stop using std::pair in the implementation of tuples (#479)
This commit is contained in:
@@ -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>());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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*;
|
||||
|
||||
Reference in New Issue
Block a user