Browse Source

Switch Member to variant in anticipation of more kinds. (#656)

Note this overlaps a little with #644's Member changes, but not too badly.
Jon Meow 4 năm trước cách đây
mục cha
commit
ada2be2d16

+ 1 - 1
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;
 }

+ 12 - 9
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<FieldMember>(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;
   }

+ 20 - 12
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*;
+
+  auto GetFieldMember() const -> const FieldMember&;
+
+  void Print();
 
-void PrintMember(Member* m);
+  inline auto tag() const -> MemberKind {
+    return std::visit([](const auto& t) { return t.Kind; }, value);
+  }
+
+  int line_num;
+
+ private:
+  std::variant<FieldMember> value;
+};
 
 }  // namespace Carbon
 

+ 5 - 5
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;
       }
     }

+ 13 - 8
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<Member*>();
-  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);

+ 3 - 2
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: