mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 21:11:27 +01:00
Unify tuple types with tuples-of-types in the interpreter (#442)
This commit is contained in:
@@ -27,18 +27,6 @@ auto PatternMatch(const Value* pat, const Value* val, Env,
|
||||
std::list<std::string>*, int) -> std::optional<Env>;
|
||||
void HandleValue();
|
||||
|
||||
template <class T>
|
||||
static auto FindField(const std::string& field,
|
||||
const std::vector<std::pair<std::string, T>>& inits)
|
||||
-> std::optional<T> {
|
||||
for (const auto& i : inits) {
|
||||
if (i.first == field) {
|
||||
return i.second;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
// Auxiliary Functions
|
||||
//
|
||||
@@ -105,14 +93,6 @@ auto CopyVal(const Value* val, int line_num) -> const Value* {
|
||||
return MakeAutoTypeVal();
|
||||
case ValKind::ContinuationTV:
|
||||
return MakeContinuationTypeVal();
|
||||
case ValKind::TupleTV: {
|
||||
auto new_fields = new VarValues();
|
||||
for (auto& field : *val->u.tuple_type.fields) {
|
||||
auto v = CopyVal(field.second, line_num);
|
||||
new_fields->push_back(make_pair(field.first, v));
|
||||
}
|
||||
return MakeTupleTypeVal(new_fields);
|
||||
}
|
||||
case ValKind::StructTV:
|
||||
case ValKind::ChoiceTV:
|
||||
case ValKind::VarPatV:
|
||||
@@ -300,7 +280,7 @@ void InitGlobals(std::list<Declaration>* fs) {
|
||||
auto ChoiceDeclaration::InitGlobals(Env& globals) const -> void {
|
||||
auto alts = new VarValues();
|
||||
for (auto kv : alternatives) {
|
||||
auto t = ToType(this->line_num, InterpExp(Env(), kv.second));
|
||||
auto t = InterpExp(Env(), kv.second);
|
||||
alts->push_back(make_pair(kv.first, t));
|
||||
}
|
||||
auto ct = MakeChoiceTypeVal(name, alts);
|
||||
@@ -315,8 +295,7 @@ auto StructDeclaration::InitGlobals(Env& globals) const -> void {
|
||||
++i) {
|
||||
switch ((*i)->tag) {
|
||||
case MemberKind::FieldMember: {
|
||||
auto t =
|
||||
ToType(definition.line_num, InterpExp(Env(), (*i)->u.field.type));
|
||||
auto t = InterpExp(Env(), (*i)->u.field.type);
|
||||
fields->push_back(make_pair(*(*i)->u.field.name, t));
|
||||
break;
|
||||
}
|
||||
@@ -446,7 +425,7 @@ auto PatternMatch(const Value* p, const Value* v, Env values,
|
||||
exit(-1);
|
||||
}
|
||||
for (auto& elt : *p->u.tuple.elts) {
|
||||
auto a = FindField(elt.first, *v->u.tuple.elts);
|
||||
auto a = FindTupleField(elt.first, v);
|
||||
if (a == std::nullopt) {
|
||||
std::cerr << "runtime error: field " << elt.first << "not in ";
|
||||
PrintValue(v, std::cerr);
|
||||
@@ -530,7 +509,7 @@ void PatternAssignment(const Value* pat, const Value* val, int line_num) {
|
||||
exit(-1);
|
||||
}
|
||||
for (auto& elt : *pat->u.tuple.elts) {
|
||||
auto a = FindField(elt.first, *val->u.tuple.elts);
|
||||
auto a = FindTupleField(elt.first, val);
|
||||
if (a == std::nullopt) {
|
||||
std::cerr << "runtime error: field " << elt.first << "not in ";
|
||||
PrintValue(val, std::cerr);
|
||||
@@ -954,7 +933,7 @@ auto GetMember(Address a, const std::string& f) -> Address {
|
||||
const Value* v = state->heap[a];
|
||||
switch (v->tag) {
|
||||
case ValKind::StructV: {
|
||||
auto a = FindField(f, *v->u.struct_val.inits->u.tuple.elts);
|
||||
auto a = FindTupleField(f, v->u.struct_val.inits);
|
||||
if (a == std::nullopt) {
|
||||
std::cerr << "runtime error, member " << f << " not in ";
|
||||
PrintValue(v, std::cerr);
|
||||
@@ -964,7 +943,7 @@ auto GetMember(Address a, const std::string& f) -> Address {
|
||||
return *a;
|
||||
}
|
||||
case ValKind::TupleV: {
|
||||
auto a = FindField(f, *v->u.tuple.elts);
|
||||
auto a = FindTupleField(f, v);
|
||||
if (a == std::nullopt) {
|
||||
std::cerr << "field " << f << " not in ";
|
||||
PrintValue(v, std::cerr);
|
||||
@@ -1069,7 +1048,7 @@ void HandleValue() {
|
||||
// -> { { &v[i] :: C, E, F} :: S, H }
|
||||
const Value* tuple = act->results[0];
|
||||
std::string f = std::to_string(ToInteger(act->results[1]));
|
||||
auto a = FindField(f, *tuple->u.tuple.elts);
|
||||
auto a = FindTupleField(f, tuple);
|
||||
if (a == std::nullopt) {
|
||||
std::cerr << "runtime error: field " << f << "not in ";
|
||||
PrintValue(tuple, std::cerr);
|
||||
@@ -1139,7 +1118,7 @@ void HandleValue() {
|
||||
// { { v :: [][i] :: C, E, F} :: S, H}
|
||||
// -> { { v_i :: C, E, F} : S, H}
|
||||
std::string f = std::to_string(ToInteger(act->results[1]));
|
||||
auto a = FindField(f, *tuple->u.tuple.elts);
|
||||
auto a = FindTupleField(f, tuple);
|
||||
if (a == std::nullopt) {
|
||||
std::cerr << "runtime error, field " << f << " not in ";
|
||||
PrintValue(tuple, std::cerr);
|
||||
|
||||
@@ -39,53 +39,6 @@ void PrintTypeEnv(TypeEnv types, std::ostream& out) {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert tuples to tuple types.
|
||||
auto ToType(int line_num, const Value* val) -> const Value* {
|
||||
switch (val->tag) {
|
||||
case ValKind::TupleV: {
|
||||
auto fields = new VarValues();
|
||||
for (auto& elt : *val->u.tuple.elts) {
|
||||
const Value* ty = ToType(line_num, state->heap[elt.second]);
|
||||
fields->push_back(std::make_pair(elt.first, ty));
|
||||
}
|
||||
return MakeTupleTypeVal(fields);
|
||||
}
|
||||
case ValKind::TupleTV: {
|
||||
auto fields = new VarValues();
|
||||
for (auto& field : *val->u.tuple_type.fields) {
|
||||
const Value* ty = ToType(line_num, field.second);
|
||||
fields->push_back(std::make_pair(field.first, ty));
|
||||
}
|
||||
return MakeTupleTypeVal(fields);
|
||||
}
|
||||
case ValKind::PointerTV: {
|
||||
return MakePtrTypeVal(ToType(line_num, val->u.ptr_type.type));
|
||||
}
|
||||
case ValKind::FunctionTV: {
|
||||
return MakeFunTypeVal(ToType(line_num, val->u.fun_type.param),
|
||||
ToType(line_num, val->u.fun_type.ret));
|
||||
}
|
||||
case ValKind::VarPatV: {
|
||||
return MakeVarPatVal(*val->u.var_pat.name,
|
||||
ToType(line_num, val->u.var_pat.type));
|
||||
}
|
||||
case ValKind::ChoiceTV:
|
||||
case ValKind::StructTV:
|
||||
case ValKind::TypeTV:
|
||||
case ValKind::VarTV:
|
||||
case ValKind::BoolTV:
|
||||
case ValKind::IntTV:
|
||||
case ValKind::AutoTV:
|
||||
case ValKind::ContinuationTV:
|
||||
return val;
|
||||
default:
|
||||
std::cerr << line_num << ": in ToType, expected a type, not ";
|
||||
PrintValue(val, std::cerr);
|
||||
std::cerr << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// Reify type to type expression.
|
||||
auto ReifyType(const Value* t, int line_num) -> Expression* {
|
||||
switch (t->tag) {
|
||||
@@ -102,11 +55,11 @@ auto ReifyType(const Value* t, int line_num) -> Expression* {
|
||||
case ValKind::FunctionTV:
|
||||
return MakeFunType(0, ReifyType(t->u.fun_type.param, line_num),
|
||||
ReifyType(t->u.fun_type.ret, line_num));
|
||||
case ValKind::TupleTV: {
|
||||
case ValKind::TupleV: {
|
||||
auto args = new std::vector<std::pair<std::string, Expression*>>();
|
||||
for (auto& field : *t->u.tuple_type.fields) {
|
||||
for (auto& field : *t->u.tuple.elts) {
|
||||
args->push_back(
|
||||
make_pair(field.first, ReifyType(field.second, line_num)));
|
||||
{field.first, ReifyType(state->heap[field.second], line_num)});
|
||||
}
|
||||
return MakeTuple(0, args);
|
||||
}
|
||||
@@ -152,8 +105,7 @@ auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
|
||||
<< std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
auto t =
|
||||
ToType(e->line_num, InterpExp(values, e->u.pattern_variable.type));
|
||||
auto t = InterpExp(values, e->u.pattern_variable.type);
|
||||
if (t->tag == ValKind::AutoTV) {
|
||||
if (expected == nullptr) {
|
||||
std::cerr << e->line_num
|
||||
@@ -174,17 +126,18 @@ auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
|
||||
TCContext::ValueContext);
|
||||
auto t = res.type;
|
||||
switch (t->tag) {
|
||||
case ValKind::TupleTV: {
|
||||
case ValKind::TupleV: {
|
||||
auto i = ToInteger(InterpExp(values, e->u.index.offset));
|
||||
std::string f = std::to_string(i);
|
||||
auto field_t = FindInVarValues(f, t->u.tuple_type.fields);
|
||||
if (field_t == nullptr) {
|
||||
std::optional<Address> field_address = FindTupleField(f, t);
|
||||
if (field_address == std::nullopt) {
|
||||
std::cerr << e->line_num << ": compilation error, field " << f
|
||||
<< " is not in the tuple ";
|
||||
PrintValue(t, std::cerr);
|
||||
std::cerr << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
auto field_t = state->heap[*field_address];
|
||||
auto new_e = MakeIndex(e->line_num, res.exp, MakeInt(e->line_num, i));
|
||||
return TCResult(new_e, field_t, res.types);
|
||||
}
|
||||
@@ -196,29 +149,30 @@ auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
|
||||
}
|
||||
case ExpressionKind::Tuple: {
|
||||
auto new_args = new std::vector<std::pair<std::string, Expression*>>();
|
||||
auto arg_types = new VarValues();
|
||||
auto arg_types = new std::vector<std::pair<std::string, Address>>();
|
||||
auto new_types = types;
|
||||
int i = 0;
|
||||
for (auto arg = e->u.tuple.fields->begin();
|
||||
arg != e->u.tuple.fields->end(); ++arg, ++i) {
|
||||
const Value* arg_expected = nullptr;
|
||||
if (expected && expected->tag == ValKind::TupleTV) {
|
||||
arg_expected =
|
||||
FindInVarValues(arg->first, expected->u.tuple_type.fields);
|
||||
if (arg_expected == nullptr) {
|
||||
if (expected && expected->tag == ValKind::TupleV) {
|
||||
std::optional<Address> expected_field =
|
||||
FindTupleField(arg->first, expected);
|
||||
if (expected_field == std::nullopt) {
|
||||
std::cerr << e->line_num << ": compilation error, missing field "
|
||||
<< arg->first << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
arg_expected = state->heap[*expected_field];
|
||||
}
|
||||
auto arg_res =
|
||||
TypeCheckExp(arg->second, new_types, values, arg_expected, context);
|
||||
new_types = arg_res.types;
|
||||
new_args->push_back(std::make_pair(arg->first, arg_res.exp));
|
||||
arg_types->push_back(std::make_pair(arg->first, arg_res.type));
|
||||
arg_types->push_back({arg->first, AllocateValue(arg_res.type)});
|
||||
}
|
||||
auto tuple_e = MakeTuple(e->line_num, new_args);
|
||||
auto tuple_t = MakeTupleTypeVal(arg_types);
|
||||
auto tuple_t = MakeTupleVal(arg_types);
|
||||
return TCResult(tuple_e, tuple_t, new_types);
|
||||
}
|
||||
case ExpressionKind::GetField: {
|
||||
@@ -247,12 +201,12 @@ auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
|
||||
<< *t->u.struct_type.name << " does not have a field named "
|
||||
<< *e->u.get_field.field << std::endl;
|
||||
exit(-1);
|
||||
case ValKind::TupleTV:
|
||||
for (auto& field : *t->u.tuple_type.fields) {
|
||||
case ValKind::TupleV:
|
||||
for (auto& field : *t->u.tuple.elts) {
|
||||
if (*e->u.get_field.field == field.first) {
|
||||
auto new_e =
|
||||
MakeGetField(e->line_num, res.exp, *e->u.get_field.field);
|
||||
return TCResult(new_e, field.second, res.types);
|
||||
return TCResult(new_e, state->heap[field.second], res.types);
|
||||
}
|
||||
}
|
||||
std::cerr << e->line_num << ": compilation error, struct "
|
||||
@@ -364,10 +318,8 @@ auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
|
||||
switch (context) {
|
||||
case TCContext::ValueContext:
|
||||
case TCContext::TypeContext: {
|
||||
auto pt = ToType(e->line_num,
|
||||
InterpExp(values, e->u.function_type.parameter));
|
||||
auto rt = ToType(e->line_num,
|
||||
InterpExp(values, e->u.function_type.return_type));
|
||||
auto pt = InterpExp(values, e->u.function_type.parameter);
|
||||
auto rt = InterpExp(values, e->u.function_type.return_type);
|
||||
auto new_e = MakeFunType(e->line_num, ReifyType(pt, e->line_num),
|
||||
ReifyType(rt, e->line_num));
|
||||
return TCResult(new_e, MakeTypeTypeVal(), types);
|
||||
@@ -610,7 +562,7 @@ auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, Env values)
|
||||
-> struct FunctionDefinition* {
|
||||
auto param_res = TypeCheckExp(f->param_pattern, types, values, nullptr,
|
||||
TCContext::PatternContext);
|
||||
auto return_type = ToType(f->line_num, InterpExp(values, f->return_type));
|
||||
auto return_type = InterpExp(values, f->return_type);
|
||||
if (f->name == "main") {
|
||||
ExpectType(f->line_num, "return type of `main`", MakeIntTypeVal(),
|
||||
return_type);
|
||||
@@ -627,13 +579,12 @@ auto TypeOfFunDef(TypeEnv types, Env values, const FunctionDefinition* fun_def)
|
||||
-> const Value* {
|
||||
auto param_res = TypeCheckExp(fun_def->param_pattern, types, values, nullptr,
|
||||
TCContext::PatternContext);
|
||||
auto param_type = ToType(fun_def->line_num, param_res.type);
|
||||
auto ret = InterpExp(values, fun_def->return_type);
|
||||
if (ret->tag == ValKind::AutoTV) {
|
||||
auto f = TypeCheckFunDef(fun_def, types, values);
|
||||
ret = InterpExp(values, f->return_type);
|
||||
}
|
||||
return MakeFunTypeVal(param_type, ret);
|
||||
return MakeFunTypeVal(param_res.type, ret);
|
||||
}
|
||||
|
||||
auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*types*/, Env ct_top)
|
||||
@@ -642,7 +593,7 @@ auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*types*/, Env ct_top)
|
||||
auto methods = new VarValues();
|
||||
for (auto m = sd->members->begin(); m != sd->members->end(); ++m) {
|
||||
if ((*m)->tag == MemberKind::FieldMember) {
|
||||
auto t = ToType(sd->line_num, InterpExp(ct_top, (*m)->u.field.type));
|
||||
auto t = InterpExp(ct_top, (*m)->u.field.type);
|
||||
fields->push_back(std::make_pair(*(*m)->u.field.name, t));
|
||||
}
|
||||
}
|
||||
@@ -689,7 +640,7 @@ auto VariableDeclaration::TypeChecked(TypeEnv types, Env values) const
|
||||
-> Declaration {
|
||||
TCResult type_checked_initializer = TypeCheckExp(
|
||||
initializer, types, values, nullptr, TCContext::ValueContext);
|
||||
const Value* declared_type = ToType(source_location, InterpExp(values, type));
|
||||
const Value* declared_type = InterpExp(values, type);
|
||||
ExpectType(source_location, "initializer of variable", declared_type,
|
||||
type_checked_initializer.type);
|
||||
return *this;
|
||||
@@ -723,15 +674,18 @@ auto StructDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
|
||||
auto st = TypeOfStructDef(&definition, tops.types, tops.values);
|
||||
Address a = AllocateValue(st);
|
||||
tops.values.Set(Name(), a); // Is this obsolete?
|
||||
auto params = MakeTupleTypeVal(st->u.struct_type.fields);
|
||||
auto fun_ty = MakeFunTypeVal(params, st);
|
||||
auto field_types = new std::vector<std::pair<std::string, Address>>();
|
||||
for (const auto& [field_name, field_value] : *st->u.struct_type.fields) {
|
||||
field_types->push_back({field_name, AllocateValue(field_value)});
|
||||
}
|
||||
auto fun_ty = MakeFunTypeVal(MakeTupleVal(field_types), st);
|
||||
tops.types.Set(Name(), fun_ty);
|
||||
}
|
||||
|
||||
auto ChoiceDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
|
||||
auto alts = new VarValues();
|
||||
for (auto a : alternatives) {
|
||||
auto t = ToType(line_num, InterpExp(tops.values, a.second));
|
||||
auto t = InterpExp(tops.values, a.second);
|
||||
alts->push_back(std::make_pair(a.first, t));
|
||||
}
|
||||
auto ct = MakeChoiceTypeVal(name, alts);
|
||||
@@ -743,8 +697,7 @@ auto ChoiceDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
|
||||
// Associate the variable name with it's declared type in the
|
||||
// compile-time symbol table.
|
||||
auto VariableDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
|
||||
const Value* declared_type =
|
||||
ToType(source_location, InterpExp(tops.values, type));
|
||||
const Value* declared_type = InterpExp(tops.values, type);
|
||||
tops.types.Set(Name(), declared_type);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@ struct TCStatement {
|
||||
TypeEnv types;
|
||||
};
|
||||
|
||||
auto ToType(int line_num, const Value* val) -> const Value*;
|
||||
|
||||
auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
|
||||
const Value* expected, TCContext context) -> TCResult;
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define EXECUTABLE_SEMANTICS_INTERPRETER_VALUE_H_
|
||||
|
||||
#include <list>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "executable_semantics/ast/statement.h"
|
||||
@@ -21,6 +22,11 @@ auto FindInVarValues(const std::string& field, VarValues* inits)
|
||||
-> const Value*;
|
||||
auto FieldsEqual(VarValues* ts1, VarValues* ts2) -> bool;
|
||||
|
||||
// Finds the field in `*tuple` named `name`, and returns its address, or
|
||||
// nullopt if there is no such field. `*tuple` must be a tuple value.
|
||||
auto FindTupleField(const std::string& name, const Value* tuple)
|
||||
-> std::optional<Address>;
|
||||
|
||||
enum class ValKind {
|
||||
IntV,
|
||||
FunV,
|
||||
@@ -36,7 +42,6 @@ enum class ValKind {
|
||||
FunctionTV,
|
||||
PointerTV,
|
||||
AutoTV,
|
||||
TupleTV,
|
||||
StructTV,
|
||||
ChoiceTV,
|
||||
ContinuationTV, // The type of a continuation.
|
||||
@@ -102,11 +107,6 @@ struct Value {
|
||||
VarValues* methods;
|
||||
} struct_type;
|
||||
|
||||
struct {
|
||||
std::string* name;
|
||||
VarValues* fields;
|
||||
} tuple_type;
|
||||
|
||||
struct {
|
||||
std::string* name;
|
||||
VarValues* alternatives;
|
||||
@@ -151,7 +151,6 @@ auto MakeFunTypeVal(const Value* param, const Value* ret) -> const Value*;
|
||||
auto MakePtrTypeVal(const Value* type) -> const Value*;
|
||||
auto MakeStructTypeVal(std::string name, VarValues* fields, VarValues* methods)
|
||||
-> const Value*;
|
||||
auto MakeTupleTypeVal(VarValues* fields) -> const Value*;
|
||||
auto MakeVoidTypeVal() -> const Value*;
|
||||
auto MakeChoiceTypeVal(std::string name, VarValues* alts) -> const Value*;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user