From d157d96338accb408dfd7ad4b78b77df297c7f65 Mon Sep 17 00:00:00 2001 From: Jon Meow <46229924+jonmeow@users.noreply.github.com> Date: Wed, 29 Sep 2021 14:38:18 -0700 Subject: [PATCH] Migrate Declaration to newer property style, class-ify ClassDefinition (#859) --- executable_semantics/ast/class_definition.h | 20 ++++- executable_semantics/ast/declaration.cpp | 16 ++-- executable_semantics/ast/declaration.h | 84 +++++++++---------- executable_semantics/ast/expression.h | 6 +- executable_semantics/ast/member.h | 6 +- executable_semantics/ast/pattern.h | 6 +- executable_semantics/ast/statement.h | 6 +- executable_semantics/interpreter/action.h | 6 +- .../interpreter/interpreter.cpp | 22 ++--- .../interpreter/type_checker.cpp | 64 +++++++------- executable_semantics/interpreter/value.h | 6 +- 11 files changed, 127 insertions(+), 115 deletions(-) diff --git a/executable_semantics/ast/class_definition.h b/executable_semantics/ast/class_definition.h index 2716e1b8a33e..9a28da7dad49 100644 --- a/executable_semantics/ast/class_definition.h +++ b/executable_semantics/ast/class_definition.h @@ -13,10 +13,22 @@ namespace Carbon { -struct ClassDefinition { - SourceLocation loc; - std::string name; - std::vector> members; +class ClassDefinition { + public: + ClassDefinition(SourceLocation source_loc, std::string name, + std::vector> members) + : source_loc_(source_loc), + name_(std::move(name)), + members_(std::move(members)) {} + + auto source_loc() const -> SourceLocation { return source_loc_; } + auto name() const -> const std::string& { return name_; } + auto members() const -> llvm::ArrayRef> { return members_; } + + private: + SourceLocation source_loc_; + std::string name_; + std::vector> members_; }; } // namespace Carbon diff --git a/executable_semantics/ast/declaration.cpp b/executable_semantics/ast/declaration.cpp index e90bf84231e5..bfd5f37de530 100644 --- a/executable_semantics/ast/declaration.cpp +++ b/executable_semantics/ast/declaration.cpp @@ -11,16 +11,16 @@ namespace Carbon { using llvm::cast; void Declaration::Print(llvm::raw_ostream& out) const { - switch (Tag()) { + switch (kind()) { case Kind::FunctionDeclaration: - out << cast(*this).Definition(); + out << cast(*this).definition(); break; case Kind::ClassDeclaration: { const ClassDefinition& class_def = - cast(*this).Definition(); - out << "class " << class_def.name << " {\n"; - for (Nonnull m : class_def.members) { + cast(*this).definition(); + out << "class " << class_def.name() << " {\n"; + for (Nonnull m : class_def.members()) { out << *m; } out << "}\n"; @@ -29,8 +29,8 @@ void Declaration::Print(llvm::raw_ostream& out) const { case Kind::ChoiceDeclaration: { const auto& choice = cast(*this); - out << "choice " << choice.Name() << " {\n"; - for (const auto& alt : choice.Alternatives()) { + out << "choice " << choice.name() << " {\n"; + for (const auto& alt : choice.alternatives()) { out << "alt " << alt.name() << " " << alt.signature() << ";\n"; } out << "}\n"; @@ -39,7 +39,7 @@ void Declaration::Print(llvm::raw_ostream& out) const { case Kind::VariableDeclaration: { const auto& var = cast(*this); - out << "var " << *var.Binding() << " = " << *var.Initializer() << "\n"; + out << "var " << var.binding() << " = " << var.initializer() << "\n"; break; } } diff --git a/executable_semantics/ast/declaration.h b/executable_semantics/ast/declaration.h index 2c3a0d7451e7..5de3d9ee9c61 100644 --- a/executable_semantics/ast/declaration.h +++ b/executable_semantics/ast/declaration.h @@ -40,60 +40,59 @@ class Declaration { Declaration(const Member&) = delete; Declaration& operator=(const Member&) = delete; + void Print(llvm::raw_ostream& out) const; + // Returns the enumerator corresponding to the most-derived type of this // object. - auto Tag() const -> Kind { return tag; } + auto kind() const -> Kind { return kind_; } - auto SourceLoc() const -> SourceLocation { return loc; } - - void Print(llvm::raw_ostream& out) const; + auto source_loc() const -> SourceLocation { return source_loc_; } protected: // Constructs a Declaration representing syntax at the given line number. // `tag` must be the enumerator corresponding to the most-derived type being // constructed. - Declaration(Kind tag, SourceLocation loc) : tag(tag), loc(loc) {} + Declaration(Kind kind, SourceLocation source_loc) + : kind_(kind), source_loc_(source_loc) {} private: - const Kind tag; - SourceLocation loc; + const Kind kind_; + SourceLocation source_loc_; }; class FunctionDeclaration : public Declaration { public: FunctionDeclaration(Nonnull definition) : Declaration(Kind::FunctionDeclaration, definition->source_loc()), - definition(definition) {} + definition_(definition) {} static auto classof(const Declaration* decl) -> bool { - return decl->Tag() == Kind::FunctionDeclaration; + return decl->kind() == Kind::FunctionDeclaration; } - auto Definition() const -> const FunctionDefinition& { return *definition; } - auto Definition() -> FunctionDefinition& { return *definition; } + auto definition() const -> const FunctionDefinition& { return *definition_; } + auto definition() -> FunctionDefinition& { return *definition_; } private: - Nonnull definition; + Nonnull definition_; }; class ClassDeclaration : public Declaration { public: - ClassDeclaration(SourceLocation loc, std::string name, + ClassDeclaration(SourceLocation source_loc, std::string name, std::vector> members) - : Declaration(Kind::ClassDeclaration, loc), - definition({.loc = loc, - .name = std::move(name), - .members = std::move(members)}) {} + : Declaration(Kind::ClassDeclaration, source_loc), + definition_(source_loc, std::move(name), std::move(members)) {} static auto classof(const Declaration* decl) -> bool { - return decl->Tag() == Kind::ClassDeclaration; + return decl->kind() == Kind::ClassDeclaration; } - auto Definition() const -> const ClassDefinition& { return definition; } - auto Definition() -> ClassDefinition& { return definition; } + auto definition() const -> const ClassDefinition& { return definition_; } + auto definition() -> ClassDefinition& { return definition_; } private: - ClassDefinition definition; + ClassDefinition definition_; }; class ChoiceDeclaration : public Declaration { @@ -111,50 +110,51 @@ class ChoiceDeclaration : public Declaration { Nonnull signature_; }; - ChoiceDeclaration(SourceLocation loc, std::string name, + ChoiceDeclaration(SourceLocation source_loc, std::string name, std::vector alternatives) - : Declaration(Kind::ChoiceDeclaration, loc), - name(std::move(name)), - alternatives(std::move(alternatives)) {} + : Declaration(Kind::ChoiceDeclaration, source_loc), + name_(std::move(name)), + alternatives_(std::move(alternatives)) {} static auto classof(const Declaration* decl) -> bool { - return decl->Tag() == Kind::ChoiceDeclaration; + return decl->kind() == Kind::ChoiceDeclaration; } - auto Name() const -> const std::string& { return name; } - auto Alternatives() const -> const std::vector& { - return alternatives; + auto name() const -> const std::string& { return name_; } + auto alternatives() const -> llvm::ArrayRef { + return alternatives_; } private: - std::string name; - std::vector alternatives; + std::string name_; + std::vector alternatives_; }; // Global variable definition implements the Declaration concept. class VariableDeclaration : public Declaration { public: - VariableDeclaration(SourceLocation loc, Nonnull binding, + VariableDeclaration(SourceLocation source_loc, + Nonnull binding, Nonnull initializer) - : Declaration(Kind::VariableDeclaration, loc), - binding(binding), - initializer(initializer) {} + : Declaration(Kind::VariableDeclaration, source_loc), + binding_(binding), + initializer_(initializer) {} static auto classof(const Declaration* decl) -> bool { - return decl->Tag() == Kind::VariableDeclaration; + return decl->kind() == Kind::VariableDeclaration; } - auto Binding() const -> Nonnull { return binding; } - auto Binding() -> Nonnull { return binding; } - auto Initializer() const -> Nonnull { return initializer; } - auto Initializer() -> Nonnull { return initializer; } + auto binding() const -> const BindingPattern& { return *binding_; } + auto binding() -> BindingPattern& { return *binding_; } + auto initializer() const -> const Expression& { return *initializer_; } + auto initializer() -> Expression& { return *initializer_; } private: // TODO: split this into a non-optional name and a type, initialized by // a constructor that takes a BindingPattern and handles errors like a // missing name. - Nonnull binding; - Nonnull initializer; + Nonnull binding_; + Nonnull initializer_; }; } // namespace Carbon diff --git a/executable_semantics/ast/expression.h b/executable_semantics/ast/expression.h index 701c18b94745..ffe0a747849a 100644 --- a/executable_semantics/ast/expression.h +++ b/executable_semantics/ast/expression.h @@ -42,7 +42,7 @@ class Expression { // Returns the enumerator corresponding to the most-derived type of this // object. - auto Tag() const -> Kind { return tag; } + auto Tag() const -> Kind { return kind; } auto SourceLoc() const -> SourceLocation { return loc; } @@ -53,10 +53,10 @@ class Expression { // Constructs an Expression representing syntax at the given line number. // `tag` must be the enumerator corresponding to the most-derived type being // constructed. - Expression(Kind tag, SourceLocation loc) : tag(tag), loc(loc) {} + Expression(Kind kind, SourceLocation loc) : kind(kind), loc(loc) {} private: - const Kind tag; + const Kind kind; SourceLocation loc; }; diff --git a/executable_semantics/ast/member.h b/executable_semantics/ast/member.h index 660ebbeb616f..c52da9404640 100644 --- a/executable_semantics/ast/member.h +++ b/executable_semantics/ast/member.h @@ -32,7 +32,7 @@ class Member { // Returns the enumerator corresponding to the most-derived type of this // object. - auto Tag() const -> Kind { return tag; } + auto Tag() const -> Kind { return kind; } auto SourceLoc() const -> SourceLocation { return loc; } @@ -42,10 +42,10 @@ class Member { // Constructs a Member representing syntax at the given line number. // `tag` must be the enumerator corresponding to the most-derived type being // constructed. - Member(Kind tag, SourceLocation loc) : tag(tag), loc(loc) {} + Member(Kind kind, SourceLocation loc) : kind(kind), loc(loc) {} private: - const Kind tag; + const Kind kind; SourceLocation loc; }; diff --git a/executable_semantics/ast/pattern.h b/executable_semantics/ast/pattern.h index 7e2a5a1eadef..737f663e3399 100644 --- a/executable_semantics/ast/pattern.h +++ b/executable_semantics/ast/pattern.h @@ -39,7 +39,7 @@ class Pattern { // Returns the enumerator corresponding to the most-derived type of this // object. - auto Tag() const -> Kind { return tag; } + auto Tag() const -> Kind { return kind; } auto SourceLoc() const -> SourceLocation { return loc; } @@ -50,10 +50,10 @@ class Pattern { // Constructs a Pattern representing syntax at the given line number. // `tag` must be the enumerator corresponding to the most-derived type being // constructed. - Pattern(Kind tag, SourceLocation loc) : tag(tag), loc(loc) {} + Pattern(Kind kind, SourceLocation loc) : kind(kind), loc(loc) {} private: - const Kind tag; + const Kind kind; SourceLocation loc; }; diff --git a/executable_semantics/ast/statement.h b/executable_semantics/ast/statement.h index 44ee96720ef8..99feea087692 100644 --- a/executable_semantics/ast/statement.h +++ b/executable_semantics/ast/statement.h @@ -38,7 +38,7 @@ class Statement { // Returns the enumerator corresponding to the most-derived type of this // object. - auto Tag() const -> Kind { return tag; } + auto Tag() const -> Kind { return kind; } auto SourceLoc() const -> SourceLocation { return loc; } @@ -50,10 +50,10 @@ class Statement { // Constructs an Statement representing syntax at the given line number. // `tag` must be the enumerator corresponding to the most-derived type being // constructed. - Statement(Kind tag, SourceLocation loc) : tag(tag), loc(loc) {} + Statement(Kind kind, SourceLocation loc) : kind(kind), loc(loc) {} private: - const Kind tag; + const Kind kind; SourceLocation loc; }; diff --git a/executable_semantics/interpreter/action.h b/executable_semantics/interpreter/action.h index 79078ba388cf..70909175c286 100644 --- a/executable_semantics/interpreter/action.h +++ b/executable_semantics/interpreter/action.h @@ -53,7 +53,7 @@ class Action { // Returns the enumerator corresponding to the most-derived type of this // object. - auto Tag() const -> Kind { return tag; } + auto Tag() const -> Kind { return kind; } static void PrintList(const Stack>& ls, llvm::raw_ostream& out); @@ -64,13 +64,13 @@ class Action { protected: // Constructs an Action. `tag` must be the enumerator corresponding to the // most-derived type being constructed. - explicit Action(Kind tag) : tag(tag) {} + explicit Action(Kind kind) : kind(kind) {} private: int pos = 0; std::vector> results; - const Kind tag; + const Kind kind; }; class LValAction : public Action { diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index d23abcc9e445..2cd6279ba092 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -107,10 +107,10 @@ auto Interpreter::EvalPrim(Operator op, } void Interpreter::InitEnv(const Declaration& d, Env* env) { - switch (d.Tag()) { + switch (d.kind()) { case Declaration::Kind::FunctionDeclaration: { const FunctionDefinition& func_def = - cast(d).Definition(); + cast(d).definition(); Env new_env = *env; // Bring the deduced parameters into scope. for (const auto& deduced : func_def.deduced_parameters()) { @@ -125,10 +125,10 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) { } case Declaration::Kind::ClassDeclaration: { - const ClassDefinition& class_def = cast(d).Definition(); + const ClassDefinition& class_def = cast(d).definition(); VarValues fields; VarValues methods; - for (Nonnull m : class_def.members) { + for (Nonnull m : class_def.members()) { switch (m->Tag()) { case Member::Kind::FieldMember: { Nonnull binding = @@ -141,23 +141,23 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) { } } } - auto st = arena->New(class_def.name, std::move(fields), + auto st = arena->New(class_def.name(), std::move(fields), std::move(methods)); auto a = heap.AllocateValue(st); - env->Set(class_def.name, a); + env->Set(class_def.name(), a); break; } case Declaration::Kind::ChoiceDeclaration: { const auto& choice = cast(d); VarValues alts; - for (const auto& alternative : choice.Alternatives()) { + for (const auto& alternative : choice.alternatives()) { auto t = InterpExp(Env(arena), &alternative.signature()); alts.push_back(make_pair(alternative.name(), t)); } - auto ct = arena->New(choice.Name(), std::move(alts)); + auto ct = arena->New(choice.name(), std::move(alts)); auto a = heap.AllocateValue(ct); - env->Set(choice.Name(), a); + env->Set(choice.name(), a); break; } @@ -165,9 +165,9 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) { const auto& var = cast(d); // Adds an entry in `globals` mapping the variable's name to the // result of evaluating the initializer. - auto v = InterpExp(*env, var.Initializer()); + auto v = InterpExp(*env, &var.initializer()); Address a = heap.AllocateValue(v); - env->Set(*var.Binding()->Name(), a); + env->Set(*var.binding().Name(), a); break; } } diff --git a/executable_semantics/interpreter/type_checker.cpp b/executable_semantics/interpreter/type_checker.cpp index 0a906378ce87..477b217ce299 100644 --- a/executable_semantics/interpreter/type_checker.cpp +++ b/executable_semantics/interpreter/type_checker.cpp @@ -931,7 +931,7 @@ auto TypeChecker::TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/, Env ct_top) -> Nonnull { VarValues fields; VarValues methods; - for (Nonnull m : sd->members) { + for (Nonnull m : sd->members()) { switch (m->Tag()) { case Member::Kind::FieldMember: { Nonnull binding = @@ -951,41 +951,41 @@ auto TypeChecker::TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/, } } } - return arena->New(sd->name, std::move(fields), std::move(methods)); + return arena->New(sd->name(), std::move(fields), + std::move(methods)); } static auto GetName(const Declaration& d) -> const std::string& { - switch (d.Tag()) { + switch (d.kind()) { case Declaration::Kind::FunctionDeclaration: - return cast(d).Definition().name(); + return cast(d).definition().name(); case Declaration::Kind::ClassDeclaration: - return cast(d).Definition().name; + return cast(d).definition().name(); case Declaration::Kind::ChoiceDeclaration: - return cast(d).Name(); + return cast(d).name(); case Declaration::Kind::VariableDeclaration: { - Nonnull binding = - cast(d).Binding(); - if (!binding->Name().has_value()) { - FATAL_COMPILATION_ERROR(binding->SourceLoc()) + const BindingPattern& binding = cast(d).binding(); + if (!binding.Name().has_value()) { + FATAL_COMPILATION_ERROR(binding.SourceLoc()) << "Top-level variable declarations must have names"; } - return *binding->Name(); + return *binding.Name(); } } } auto TypeChecker::MakeTypeChecked(Nonnull d, const TypeEnv& types, const Env& values) -> Nonnull { - switch (d->Tag()) { + switch (d->kind()) { case Declaration::Kind::FunctionDeclaration: return arena->New(TypeCheckFunDef( - &cast(*d).Definition(), types, values)); + &cast(*d).definition(), types, values)); case Declaration::Kind::ClassDeclaration: { const ClassDefinition& class_def = - cast(*d).Definition(); + cast(*d).definition(); std::vector> fields; - for (Nonnull m : class_def.members) { + for (Nonnull m : class_def.members()) { switch (m->Tag()) { case Member::Kind::FieldMember: // TODO: Interpret the type expression and store the result. @@ -993,8 +993,8 @@ auto TypeChecker::MakeTypeChecked(Nonnull d, const TypeEnv& types, break; } } - return arena->New(class_def.loc, class_def.name, - std::move(fields)); + return arena->New(class_def.source_loc(), + class_def.name(), std::move(fields)); } case Declaration::Kind::ChoiceDeclaration: @@ -1007,17 +1007,17 @@ auto TypeChecker::MakeTypeChecked(Nonnull d, const TypeEnv& types, // the declared type of the variable, otherwise returns this // declaration with annotated types. TCExpression type_checked_initializer = - TypeCheckExp(var.Initializer(), types, values); + TypeCheckExp(&var.initializer(), types, values); const auto* binding_type = - dyn_cast(var.Binding()->Type()); + dyn_cast(var.binding().Type()); if (binding_type == nullptr) { // TODO: consider adding support for `auto` - FATAL_COMPILATION_ERROR(var.SourceLoc()) + FATAL_COMPILATION_ERROR(var.source_loc()) << "Type of a top-level variable must be an expression."; } Nonnull declared_type = interpreter.InterpExp(values, binding_type->Expression()); - ExpectType(var.SourceLoc(), "initializer of variable", declared_type, + ExpectType(var.source_loc(), "initializer of variable", declared_type, type_checked_initializer.type); return d; } @@ -1025,9 +1025,9 @@ auto TypeChecker::MakeTypeChecked(Nonnull d, const TypeEnv& types, } void TypeChecker::TopLevel(Nonnull d, TypeCheckContext* tops) { - switch (d->Tag()) { + switch (d->kind()) { case Declaration::Kind::FunctionDeclaration: { - FunctionDefinition& func_def = cast(*d).Definition(); + FunctionDefinition& func_def = cast(*d).definition(); auto t = TypeOfFunDef(tops->types, tops->values, &func_def); tops->types.Set(func_def.name(), t); interpreter.InitEnv(*d, &tops->values); @@ -1036,10 +1036,10 @@ void TypeChecker::TopLevel(Nonnull d, TypeCheckContext* tops) { case Declaration::Kind::ClassDeclaration: { const ClassDefinition& class_def = - cast(*d).Definition(); + cast(*d).definition(); auto st = TypeOfClassDef(&class_def, tops->types, tops->values); Address a = interpreter.AllocateValue(st); - tops->values.Set(class_def.name, a); // Is this obsolete? + tops->values.Set(class_def.name(), a); // Is this obsolete? std::vector field_types; for (const auto& [field_name, field_value] : cast(*st).Fields()) { @@ -1048,21 +1048,21 @@ void TypeChecker::TopLevel(Nonnull d, TypeCheckContext* tops) { auto fun_ty = arena->New( std::vector(), arena->New(std::move(field_types)), st); - tops->types.Set(class_def.name, fun_ty); + tops->types.Set(class_def.name(), fun_ty); break; } case Declaration::Kind::ChoiceDeclaration: { const auto& choice = cast(*d); VarValues alts; - for (const auto& alternative : choice.Alternatives()) { + for (const auto& alternative : choice.alternatives()) { auto t = interpreter.InterpExp(tops->values, &alternative.signature()); alts.push_back(std::make_pair(alternative.name(), t)); } - auto ct = arena->New(choice.Name(), std::move(alts)); + auto ct = arena->New(choice.name(), std::move(alts)); Address a = interpreter.AllocateValue(ct); - tops->values.Set(choice.Name(), a); // Is this obsolete? - tops->types.Set(choice.Name(), ct); + tops->values.Set(choice.name(), a); // Is this obsolete? + tops->types.Set(choice.name(), ct); break; } @@ -1071,10 +1071,10 @@ void TypeChecker::TopLevel(Nonnull d, TypeCheckContext* tops) { // Associate the variable name with it's declared type in the // compile-time symbol table. Nonnull type = - cast(*var.Binding()->Type()).Expression(); + cast(*var.binding().Type()).Expression(); Nonnull declared_type = interpreter.InterpExp(tops->values, type); - tops->types.Set(*var.Binding()->Name(), declared_type); + tops->types.Set(*var.binding().Name(), declared_type); break; } } diff --git a/executable_semantics/interpreter/value.h b/executable_semantics/interpreter/value.h index 859a4a5f6a0d..4c63aa62b838 100644 --- a/executable_semantics/interpreter/value.h +++ b/executable_semantics/interpreter/value.h @@ -61,7 +61,7 @@ class Value { // Returns the enumerator corresponding to the most-derived type of this // object. - auto Tag() const -> Kind { return tag; } + auto Tag() const -> Kind { return kind; } void Print(llvm::raw_ostream& out) const; LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); } @@ -80,10 +80,10 @@ class Value { protected: // Constructs a Value. `tag` must be the enumerator corresponding to the // most-derived type being constructed. - explicit Value(Kind tag) : tag(tag) {} + explicit Value(Kind kind) : kind(kind) {} private: - const Kind tag; + const Kind kind; }; using VarValues = std::vector>>;