diff --git a/executable_semantics/ast/declaration.cpp b/executable_semantics/ast/declaration.cpp index 817cc447ee8b..65d528b77fc2 100644 --- a/executable_semantics/ast/declaration.cpp +++ b/executable_semantics/ast/declaration.cpp @@ -13,7 +13,7 @@ void FunctionDeclaration::Print() const { definition.Print(); } void StructDeclaration::Print() const { std::cout << "struct " << *definition.name << " {" << std::endl; for (auto& member : *definition.members) { - PrintMember(member); + member->Print(); } std::cout << "}" << std::endl; } diff --git a/executable_semantics/ast/member.cpp b/executable_semantics/ast/member.cpp index 5504c39162ef..a38d67975e5f 100644 --- a/executable_semantics/ast/member.cpp +++ b/executable_semantics/ast/member.cpp @@ -8,21 +8,24 @@ namespace Carbon { -auto MakeField(int line_num, std::string name, const Expression* type) - -> Member* { +auto Member::MakeFieldMember(int line_num, std::string name, + const Expression* type) -> Member* { auto m = new Member(); m->line_num = line_num; - m->tag = MemberKind::FieldMember; - m->u.field.name = new std::string(std::move(name)); - m->u.field.type = type; + m->value = FieldMember({.name = std::move(name), .type = type}); return m; } -void PrintMember(Member* m) { - switch (m->tag) { +auto Member::GetFieldMember() const -> const FieldMember& { + return std::get(value); +} + +void Member::Print() { + switch (tag()) { case MemberKind::FieldMember: - std::cout << "var " << *m->u.field.name << " : "; - PrintExp(m->u.field.type); + const auto& field = GetFieldMember(); + std::cout << "var " << field.name << " : "; + PrintExp(field.type); std::cout << ";" << std::endl; break; } diff --git a/executable_semantics/ast/member.h b/executable_semantics/ast/member.h index 68088e10113c..82a783b3b8cf 100644 --- a/executable_semantics/ast/member.h +++ b/executable_semantics/ast/member.h @@ -13,21 +13,29 @@ namespace Carbon { enum class MemberKind { FieldMember }; -struct Member { - int line_num; - MemberKind tag; - union { - struct { - std::string* name; - const Expression* type; - } field; - } u; +struct FieldMember { + static constexpr MemberKind Kind = MemberKind::FieldMember; + std::string name; + const Expression* type; }; -auto MakeField(int line_num, std::string name, const Expression* type) - -> Member*; +struct Member { + static auto MakeFieldMember(int line_num, std::string name, + const Expression* type) -> Member*; -void PrintMember(Member* m); + auto GetFieldMember() const -> const FieldMember&; + + void Print(); + + inline auto tag() const -> MemberKind { + return std::visit([](const auto& t) { return t.Kind; }, value); + } + + int line_num; + + private: + std::variant value; +}; } // namespace Carbon diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index f5bf744483ea..351786efec9a 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -300,12 +300,12 @@ auto ChoiceDeclaration::InitGlobals(Env& globals) const -> void { auto StructDeclaration::InitGlobals(Env& globals) const -> void { VarValues fields; VarValues methods; - for (auto i = definition.members->begin(); i != definition.members->end(); - ++i) { - switch ((*i)->tag) { + for (Member* m : *definition.members) { + switch (m->tag()) { case MemberKind::FieldMember: { - auto t = InterpExp(Env(), (*i)->u.field.type); - fields.push_back(make_pair(*(*i)->u.field.name, t)); + const auto& field = m->GetFieldMember(); + auto t = InterpExp(Env(), field.type); + fields.push_back({field.name, t}); break; } } diff --git a/executable_semantics/interpreter/typecheck.cpp b/executable_semantics/interpreter/typecheck.cpp index d1563a9de430..7a6c9aea1ccf 100644 --- a/executable_semantics/interpreter/typecheck.cpp +++ b/executable_semantics/interpreter/typecheck.cpp @@ -681,10 +681,13 @@ auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*types*/, Env ct_top) -> const Value* { VarValues fields; VarValues methods; - for (auto m = sd->members->begin(); m != sd->members->end(); ++m) { - if ((*m)->tag == MemberKind::FieldMember) { - auto t = InterpExp(ct_top, (*m)->u.field.type); - fields.push_back(std::make_pair(*(*m)->u.field.name, t)); + for (Member* m : *sd->members) { + switch (m->tag()) { + case MemberKind::FieldMember: + const auto& field = m->GetFieldMember(); + auto t = InterpExp(ct_top, field.type); + fields.push_back(std::make_pair(field.name, t)); + break; } } return Value::MakeStructType(*sd->name, std::move(fields), @@ -705,10 +708,12 @@ auto VariableDeclaration::Name() const -> std::string { return name; } auto StructDeclaration::TypeChecked(TypeEnv types, Env values) const -> Declaration { auto fields = new std::list(); - for (auto& m : *definition.members) { - if (m->tag == MemberKind::FieldMember) { - // TODO: Interpret the type expression and store the result. - fields->push_back(m); + for (Member* m : *definition.members) { + switch (m->tag()) { + case MemberKind::FieldMember: + // TODO: Interpret the type expression and store the result. + fields->push_back(m); + break; } } return StructDeclaration(definition.line_num, *definition.name, fields); diff --git a/executable_semantics/syntax/parser.ypp b/executable_semantics/syntax/parser.ypp index a8968f8941b5..e3b91197a607 100644 --- a/executable_semantics/syntax/parser.ypp +++ b/executable_semantics/syntax/parser.ypp @@ -384,7 +384,7 @@ function_declaration: { $$ = Carbon::FunctionDefinition(yylineno, $2, $3, $4, 0); } ; variable_declaration: identifier ":" expression - { $$ = MakeField(yylineno, $1, $3); } + { $$ = Carbon::Member::MakeFieldMember(yylineno, $1, $3); } ; member: VAR variable_declaration ";" { $$ = $2; } @@ -433,7 +433,8 @@ declaration: | VAR variable_declaration "=" expression ";" { $$ = Carbon::Declaration( - Carbon::VariableDeclaration(yylineno, *$2->u.field.name, $2->u.field.type, $4)); + Carbon::VariableDeclaration(yylineno, $2->GetFieldMember().name, + $2->GetFieldMember().type, $4)); } ; declaration_list: