From 6ab2bff69c33dfef90c7b03f542ab9b2f18860c7 Mon Sep 17 00:00:00 2001 From: Jon Meow <46229924+jonmeow@users.noreply.github.com> Date: Mon, 27 Sep 2021 09:05:04 -0700 Subject: [PATCH] Switch FunctionDefinition to a class (#852) Splitting out the task from #849 --- executable_semantics/ast/declaration.h | 2 +- .../ast/function_definition.cpp | 16 +++--- .../ast/function_definition.h | 49 +++++++++++++------ .../interpreter/interpreter.cpp | 8 +-- .../interpreter/type_checker.cpp | 40 +++++++-------- 5 files changed, 66 insertions(+), 49 deletions(-) diff --git a/executable_semantics/ast/declaration.h b/executable_semantics/ast/declaration.h index 4db1063b1ff0..90ab7d428bc9 100644 --- a/executable_semantics/ast/declaration.h +++ b/executable_semantics/ast/declaration.h @@ -61,7 +61,7 @@ class Declaration { class FunctionDeclaration : public Declaration { public: FunctionDeclaration(Nonnull definition) - : Declaration(Kind::FunctionDeclaration, definition->source_location), + : Declaration(Kind::FunctionDeclaration, definition->source_loc()), definition(definition) {} static auto classof(const Declaration* decl) -> bool { diff --git a/executable_semantics/ast/function_definition.cpp b/executable_semantics/ast/function_definition.cpp index b7759f62cd25..7a7b45b448b9 100644 --- a/executable_semantics/ast/function_definition.cpp +++ b/executable_semantics/ast/function_definition.cpp @@ -7,11 +7,11 @@ namespace Carbon { void FunctionDefinition::PrintDepth(int depth, llvm::raw_ostream& out) const { - out << "fn " << name << " "; - if (deduced_parameters.size() > 0) { + out << "fn " << name_ << " "; + if (!deduced_parameters_.empty()) { out << "["; unsigned int i = 0; - for (const auto& deduced : deduced_parameters) { + for (const auto& deduced : deduced_parameters_) { if (i != 0) { out << ", "; } @@ -21,13 +21,13 @@ void FunctionDefinition::PrintDepth(int depth, llvm::raw_ostream& out) const { } out << "]"; } - out << *param_pattern; - if (!is_omitted_return_type) { - out << " -> " << *return_type; + out << *param_pattern_; + if (!is_omitted_return_type_) { + out << " -> " << *return_type_; } - if (body) { + if (body_) { out << " {\n"; - (*body)->PrintDepth(depth, out); + (*body_)->PrintDepth(depth, out); out << "\n}\n"; } else { out << ";\n"; diff --git a/executable_semantics/ast/function_definition.h b/executable_semantics/ast/function_definition.h index 81d4fb22714f..00de202e27ff 100644 --- a/executable_semantics/ast/function_definition.h +++ b/executable_semantics/ast/function_definition.h @@ -10,6 +10,7 @@ #include "executable_semantics/ast/pattern.h" #include "executable_semantics/ast/source_location.h" #include "executable_semantics/ast/statement.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Compiler.h" namespace Carbon { @@ -21,32 +22,48 @@ struct GenericBinding { Nonnull type; }; -struct FunctionDefinition { - FunctionDefinition(SourceLocation source_location, std::string name, +class FunctionDefinition { + public: + FunctionDefinition(SourceLocation source_loc, std::string name, std::vector deduced_params, Nonnull param_pattern, Nonnull return_type, bool is_omitted_return_type, std::optional> body) - : source_location(source_location), - name(std::move(name)), - deduced_parameters(deduced_params), - param_pattern(param_pattern), - return_type(return_type), - is_omitted_return_type(is_omitted_return_type), - body(body) {} + : source_loc_(source_loc), + name_(std::move(name)), + deduced_parameters_(deduced_params), + param_pattern_(param_pattern), + return_type_(return_type), + is_omitted_return_type_(is_omitted_return_type), + body_(body) {} void Print(llvm::raw_ostream& out) const { PrintDepth(-1, out); } void PrintDepth(int depth, llvm::raw_ostream& out) const; LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); } - SourceLocation source_location; - std::string name; - std::vector deduced_parameters; - Nonnull param_pattern; - Nonnull return_type; - bool is_omitted_return_type; - std::optional> body; + auto source_loc() const -> SourceLocation { return source_loc_; } + auto name() const -> const std::string& { return name_; } + auto deduced_parameters() const -> llvm::ArrayRef { + return deduced_parameters_; + } + auto param_pattern() const -> const TuplePattern& { return *param_pattern_; } + auto return_type() const -> const Pattern& { return *return_type_; } + auto is_omitted_return_type() const -> bool { + return is_omitted_return_type_; + } + auto body() const -> std::optional> { + return body_; + } + + private: + SourceLocation source_loc_; + std::string name_; + std::vector deduced_parameters_; + Nonnull param_pattern_; + Nonnull return_type_; + bool is_omitted_return_type_; + std::optional> body_; }; } // namespace Carbon diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index 8f636fe5a2a5..dd1daef4bb01 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -113,14 +113,14 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) { cast(d).Definition(); Env new_env = *env; // Bring the deduced parameters into scope. - for (const auto& deduced : func_def.deduced_parameters) { + for (const auto& deduced : func_def.deduced_parameters()) { Address a = heap.AllocateValue(arena->New(deduced.name)); new_env.Set(deduced.name, a); } - auto pt = InterpPattern(new_env, func_def.param_pattern); - auto f = arena->New(func_def.name, pt, func_def.body); + auto pt = InterpPattern(new_env, &func_def.param_pattern()); + auto f = arena->New(func_def.name(), pt, func_def.body()); Address a = heap.AllocateValue(f); - env->Set(func_def.name, a); + env->Set(func_def.name(), a); break; } diff --git a/executable_semantics/interpreter/type_checker.cpp b/executable_semantics/interpreter/type_checker.cpp index df56f5418e7d..8ecc68d5437f 100644 --- a/executable_semantics/interpreter/type_checker.cpp +++ b/executable_semantics/interpreter/type_checker.cpp @@ -861,7 +861,7 @@ auto TypeChecker::TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, Env values) -> Nonnull { // Bring the deduced parameters into scope - for (const auto& deduced : f->deduced_parameters) { + for (const auto& deduced : f->deduced_parameters()) { // auto t = interpreter.InterpExp(values, deduced.type); types.Set(deduced.name, arena->New(deduced.name)); Address a = interpreter.AllocateValue(*types.Get(deduced.name)); @@ -869,25 +869,25 @@ auto TypeChecker::TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, } // Type check the parameter pattern auto param_res = - TypeCheckPattern(f->param_pattern, types, values, std::nullopt); + TypeCheckPattern(&f->param_pattern(), types, values, std::nullopt); // Evaluate the return type expression - auto return_type = interpreter.InterpPattern(values, f->return_type); - if (f->name == "main") { - ExpectType(f->source_location, "return type of `main`", - arena->New(), return_type); + auto return_type = interpreter.InterpPattern(values, &f->return_type()); + if (f->name() == "main") { + ExpectType(f->source_loc(), "return type of `main`", arena->New(), + return_type); // TODO: Check that main doesn't have any parameters. } std::optional> body_stmt; - if (f->body) { - auto res = TypeCheckStmt(*f->body, param_res.types, values, return_type, - f->is_omitted_return_type); + if (f->body()) { + auto res = TypeCheckStmt(*f->body(), param_res.types, values, return_type, + f->is_omitted_return_type()); body_stmt = res.stmt; } - auto body = CheckOrEnsureReturn(body_stmt, f->is_omitted_return_type, - f->source_location); + auto body = CheckOrEnsureReturn(body_stmt, f->is_omitted_return_type(), + f->source_loc()); return arena->New( - f->source_location, f->name, f->deduced_parameters, f->param_pattern, - arena->New(ReifyType(return_type, f->source_location)), + f->source_loc(), f->name(), f->deduced_parameters(), &f->param_pattern(), + arena->New(ReifyType(return_type, f->source_loc())), /*is_omitted_return_type=*/false, body); } @@ -895,7 +895,7 @@ auto TypeChecker::TypeOfFunDef(TypeEnv types, Env values, const FunctionDefinition* fun_def) -> Nonnull { // Bring the deduced parameters into scope - for (const auto& deduced : fun_def->deduced_parameters) { + for (const auto& deduced : fun_def->deduced_parameters()) { // auto t = interpreter.InterpExp(values, deduced.type); types.Set(deduced.name, arena->New(deduced.name)); Address a = interpreter.AllocateValue(*types.Get(deduced.name)); @@ -903,14 +903,14 @@ auto TypeChecker::TypeOfFunDef(TypeEnv types, Env values, } // Type check the parameter pattern auto param_res = - TypeCheckPattern(fun_def->param_pattern, types, values, std::nullopt); + TypeCheckPattern(&fun_def->param_pattern(), types, values, std::nullopt); // Evaluate the return type expression - auto ret = interpreter.InterpPattern(values, fun_def->return_type); + auto ret = interpreter.InterpPattern(values, &fun_def->return_type()); if (ret->Tag() == Value::Kind::AutoType) { auto f = TypeCheckFunDef(fun_def, types, values); - ret = interpreter.InterpPattern(values, f->return_type); + ret = interpreter.InterpPattern(values, &f->return_type()); } - return arena->New(fun_def->deduced_parameters, param_res.type, + return arena->New(fun_def->deduced_parameters(), param_res.type, ret); } @@ -944,7 +944,7 @@ auto TypeChecker::TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/, static auto GetName(const Declaration& d) -> const std::string& { switch (d.Tag()) { case Declaration::Kind::FunctionDeclaration: - return cast(d).Definition().name; + return cast(d).Definition().name(); case Declaration::Kind::ClassDeclaration: return cast(d).Definition().name; case Declaration::Kind::ChoiceDeclaration: @@ -1018,7 +1018,7 @@ void TypeChecker::TopLevel(const Declaration& d, TypeCheckContext* tops) { const FunctionDefinition& func_def = cast(d).Definition(); auto t = TypeOfFunDef(tops->types, tops->values, &func_def); - tops->types.Set(func_def.name, t); + tops->types.Set(func_def.name(), t); interpreter.InitEnv(d, &tops->values); break; }