Generic classes (#1124)

* start of generic classes

* fix regressions

* class functions in interfaces

* access to class function on interface from class parameter

* more stuff working for generic classes

* fixing bugs

* update TypeEqual for generic classes

* fixing bugs and finding new ones

* disable unqualified access to members from other members for now

* minor edits

* bug fixes

* introduce compile_time_value to use in type checker instead of constant_value

* cleanup

* put a CHECK back in

* failure test cases for the new FATAL_COMPILATION_ERROR

* change a runtime FATAL into a FATAL_COMPILATION_ERROR

* Update executable_semantics/ast/declaration.h

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/action_stack.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/interpreter.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/value.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/value.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/interpreter.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/value.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/value.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/resolve_names.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/type_checker.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/type_checker.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/type_checker.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* responses to reviews

* Update executable_semantics/interpreter/type_checker.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* rename compile_time_value to symbolic_identity

* Update executable_semantics/interpreter/type_checker.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/type_checker.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/type_checker.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/type_checker.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/type_checker.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/type_checker.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/value.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/value.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* Update executable_semantics/interpreter/value.cpp

Co-authored-by: Jon Meow <jperkins@google.com>

* more edits from review

* Apply suggestions from code review

Co-authored-by: Geoff Romer <gromer@google.com>

* review responses

* Update executable_semantics/interpreter/interpreter.cpp

Co-authored-by: Geoff Romer <gromer@google.com>

* const impl_scope for TypeCheckChoiceDeclaration

* add some const

Co-authored-by: Jon Meow <jperkins@google.com>
Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
Jeremy G. Siek
2022-03-29 13:09:41 -04:00
committed by GitHub
co-authored by Jon Meow Geoff Romer
parent 37a0e35b31
commit 210856dd57
41 changed files with 1597 additions and 401 deletions
+93 -1
View File
@@ -129,6 +129,15 @@ class FunctionValue : public Value {
explicit FunctionValue(Nonnull<const FunctionDeclaration*> declaration)
: Value(Kind::FunctionValue), declaration_(declaration) {}
explicit FunctionValue(Nonnull<const FunctionDeclaration*> declaration,
const BindingMap& type_args,
const std::map<Nonnull<const ImplBinding*>,
Nonnull<const Witness*>>& wits)
: Value(Kind::FunctionValue),
declaration_(declaration),
type_args_(type_args),
witnesses_(wits) {}
static auto classof(const Value* value) -> bool {
return value->kind() == Kind::FunctionValue;
}
@@ -137,8 +146,17 @@ class FunctionValue : public Value {
return *declaration_;
}
auto type_args() const -> const BindingMap& { return type_args_; }
auto witnesses() const
-> const std::map<Nonnull<const ImplBinding*>, const Witness*>& {
return witnesses_;
}
private:
Nonnull<const FunctionDeclaration*> declaration_;
BindingMap type_args_;
std::map<Nonnull<const ImplBinding*>, Nonnull<const Witness*>> witnesses_;
};
// A bound method value. It includes the receiver object.
@@ -150,6 +168,17 @@ class BoundMethodValue : public Value {
declaration_(declaration),
receiver_(receiver) {}
explicit BoundMethodValue(Nonnull<const FunctionDeclaration*> declaration,
Nonnull<const Value*> receiver,
const BindingMap& type_args,
const std::map<Nonnull<const ImplBinding*>,
Nonnull<const Witness*>>& wits)
: Value(Kind::BoundMethodValue),
declaration_(declaration),
receiver_(receiver),
type_args_(type_args),
witnesses_(wits) {}
static auto classof(const Value* value) -> bool {
return value->kind() == Kind::BoundMethodValue;
}
@@ -160,9 +189,18 @@ class BoundMethodValue : public Value {
auto receiver() const -> Nonnull<const Value*> { return receiver_; }
auto type_args() const -> const BindingMap& { return type_args_; }
auto witnesses() const
-> const std::map<Nonnull<const ImplBinding*>, Nonnull<const Witness*>>& {
return witnesses_;
}
private:
Nonnull<const FunctionDeclaration*> declaration_;
Nonnull<const Value*> receiver_;
BindingMap type_args_;
std::map<Nonnull<const ImplBinding*>, Nonnull<const Witness*>> witnesses_;
};
// The value of a location in memory.
@@ -465,16 +503,68 @@ class StructType : public Value {
};
// A class type.
// TODO: Consider splitting this class into several classes.
class NominalClassType : public Value {
public:
// Construct a non-generic class type or a generic class type that has
// not yet been applied to type arguments.
explicit NominalClassType(Nonnull<const ClassDeclaration*> declaration)
: Value(Kind::NominalClassType), declaration_(declaration) {}
// Construct a class type that represents the result of applying the
// given generic class to the `type_args`.
explicit NominalClassType(Nonnull<const ClassDeclaration*> declaration,
const BindingMap& type_args)
: Value(Kind::NominalClassType),
declaration_(declaration),
type_args_(type_args) {}
// Construct a class type that represents the result of applying the
// given generic class to the `type_args` and that records the result of the
// compile-time search for any required impls.
explicit NominalClassType(
Nonnull<const ClassDeclaration*> declaration, const BindingMap& type_args,
const std::map<Nonnull<const ImplBinding*>, ValueNodeView>& impls)
: Value(Kind::NominalClassType),
declaration_(declaration),
type_args_(type_args),
impls_(impls) {}
// Construct a fully instantiated generic class type to represent the
// run-time type of an object.
explicit NominalClassType(Nonnull<const ClassDeclaration*> declaration,
const BindingMap& type_args,
const std::map<Nonnull<const ImplBinding*>,
Nonnull<const Witness*>>& wits)
: Value(Kind::NominalClassType),
declaration_(declaration),
type_args_(type_args),
witnesses_(wits) {}
static auto classof(const Value* value) -> bool {
return value->kind() == Kind::NominalClassType;
}
auto declaration() const -> const ClassDeclaration& { return *declaration_; }
auto type_args() const -> const BindingMap& { return type_args_; }
// Maps each of the class's generic parameters to the AST node that
// identifies the witness table for the corresponding argument.
// Should not be called on 1) a non-generic class, 2) a generic-class
// that is not instantiated, or 3) a fully instantiated runtime type
// of a generic class.
auto impls() const
-> const std::map<Nonnull<const ImplBinding*>, ValueNodeView>& {
return impls_;
}
// Maps each of the class's generic parameters to the witness table
// for the corresponding argument. Should only be called on a fully
// instantiated runtime type of a generic class.
auto witnesses() const
-> const std::map<Nonnull<const ImplBinding*>, Nonnull<const Witness*>>& {
return witnesses_;
}
// Returns the value of the function named `name` in this class, or
// nullopt if there is no such function.
@@ -483,9 +573,11 @@ class NominalClassType : public Value {
private:
Nonnull<const ClassDeclaration*> declaration_;
BindingMap type_args_;
std::map<Nonnull<const ImplBinding*>, ValueNodeView> impls_;
std::map<Nonnull<const ImplBinding*>, Nonnull<const Witness*>> witnesses_;
};
auto FieldTypes(const NominalClassType&) -> std::vector<NamedValue>;
// Return the declaration of the member with the given name.
auto FindMember(const std::string& name,
llvm::ArrayRef<Nonnull<Declaration*>> members)