Explorer: Support class extension (#1946)

Support class extension with `extends`
Relates to #1881 

Add support for:
* Class extension with `extends`
* Using base class methods and members
This commit is contained in:
Adrien Leravat
2022-10-21 08:08:07 -07:00
committed by GitHub
parent d76835bed4
commit 7c19ef5be3
14 changed files with 353 additions and 56 deletions
+18 -4
View File
@@ -7,6 +7,7 @@
#include <algorithm>
#include "common/check.h"
#include "explorer/ast/declaration.h"
#include "explorer/common/arena.h"
#include "explorer/common/error_builders.h"
#include "explorer/interpreter/action.h"
@@ -98,7 +99,7 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
// Look for a method in the object's class
const auto& class_type = cast<NominalClassType>(object.type());
std::optional<Nonnull<const FunctionValue*>> func =
class_type.FindFunction(f);
FindFunctionWithParents(f, class_type.declaration());
if (!func) {
return ProgramError(source_loc) << "member " << f << " not in " << *v
<< " or its " << class_type;
@@ -127,7 +128,7 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
// Access a class function.
const auto& class_type = cast<NominalClassType>(*v);
std::optional<Nonnull<const FunctionValue*>> fun =
class_type.FindFunction(f);
FindFunctionWithParents(f, class_type.declaration());
if (fun == std::nullopt) {
return ProgramError(source_loc)
<< "class function " << f << " not in " << *v;
@@ -979,9 +980,10 @@ auto ChoiceType::FindAlternative(std::string_view name) const
return std::nullopt;
}
auto NominalClassType::FindFunction(std::string_view name) const
auto FindFunction(std::string_view name,
llvm::ArrayRef<Nonnull<Declaration*>> members)
-> std::optional<Nonnull<const FunctionValue*>> {
for (const auto& member : declaration().members()) {
for (const auto& member : members) {
switch (member->kind()) {
case DeclarationKind::MixDeclaration: {
const auto& mix_decl = cast<MixDeclaration>(*member);
@@ -1034,6 +1036,18 @@ auto MixinPseudoType::FindFunction(const std::string_view& name) const
return std::nullopt;
}
auto FindFunctionWithParents(std::string_view name,
const ClassDeclaration& class_decl)
-> std::optional<Nonnull<const FunctionValue*>> {
if (auto fun = FindFunction(name, class_decl.members()); fun.has_value()) {
return fun;
}
if (class_decl.base().has_value()) {
return FindFunctionWithParents(name, *class_decl.base().value());
}
return std::nullopt;
}
auto FindMember(std::string_view name,
llvm::ArrayRef<Nonnull<Declaration*>> members)
-> std::optional<Nonnull<const Declaration*>> {