Parameterized impl declarations (#1189)

* parameterized impls, first step

* bug fixes, comments, etc.

* added another test case, fix a bug in impl lookup

* simplify tests, removing tuple stuff

* don't create impl bindings for -bound implicit parameters

* remove a redundant 'private'

* CamelCase

* add missing backtick

* add a comment
This commit is contained in:
Jeremy G. Siek
2022-04-20 10:18:01 -04:00
committed by GitHub
parent 958fb8e529
commit b784458aef
20 changed files with 893 additions and 386 deletions
+36 -9
View File
@@ -364,6 +364,8 @@ class GenericBinding;
using BindingMap =
std::map<Nonnull<const GenericBinding*>, Nonnull<const Value*>>;
using ImplExpMap = std::map<Nonnull<const ImplBinding*>, Nonnull<Expression*>>;
class CallExpression : public Expression {
public:
explicit CallExpression(SourceLocation source_loc,
@@ -382,18 +384,14 @@ class CallExpression : public Expression {
auto argument() const -> const Expression& { return *argument_; }
auto argument() -> Expression& { return *argument_; }
// Maps each of `function`'s generic parameters to the AST node
// that identifies the witness table for the corresponding argument.
// Maps each of `function`'s impl bindings to an expression
// that constructs a witness table.
// Should not be called before typechecking, or if `function` is not
// a generic function.
auto impls() const
-> const std::map<Nonnull<const ImplBinding*>, ValueNodeView>& {
return impls_;
}
auto impls() const -> const ImplExpMap& { return impls_; }
// Can only be called once, during typechecking.
void set_impls(
const std::map<Nonnull<const ImplBinding*>, ValueNodeView>& impls) {
void set_impls(const ImplExpMap& impls) {
CHECK(impls_.empty());
impls_ = impls;
}
@@ -407,7 +405,7 @@ class CallExpression : public Expression {
private:
Nonnull<Expression*> function_;
Nonnull<Expression*> argument_;
std::map<Nonnull<const ImplBinding*>, ValueNodeView> impls_;
ImplExpMap impls_;
BindingMap deduced_args_;
};
@@ -538,6 +536,35 @@ class IfExpression : public Expression {
Nonnull<Expression*> else_expression_;
};
// Instantiate a generic impl.
class InstantiateImpl : public Expression {
public:
using ImplementsCarbonValueNode = void;
explicit InstantiateImpl(SourceLocation source_loc,
Nonnull<Expression*> generic_impl,
const BindingMap& type_args, const ImplExpMap& impls)
: Expression(AstNodeKind::InstantiateImpl, source_loc),
generic_impl_(generic_impl),
type_args_(type_args),
impls_(impls) {}
static auto classof(const AstNode* node) -> bool {
return InheritsFromInstantiateImpl(node->kind());
}
auto generic_impl() const -> Nonnull<Expression*> { return generic_impl_; }
auto type_args() const -> const BindingMap& { return type_args_; }
// Maps each of the impl bindings to an expression that constructs
// the witness table for that impl.
auto impls() const -> const ImplExpMap& { return impls_; }
private:
Nonnull<Expression*> generic_impl_;
BindingMap type_args_;
ImplExpMap impls_;
};
// An expression whose semantics have not been implemented. This can be used
// as a placeholder during development, in order to implement and test parsing
// of a new expression syntax without having to implement its semantics.