mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 18:21:16 +01:00
Track the arguments and witnesses on values indirectly. (#1335)
This avoids the need to make copies of potentially large maps when the same bindings are used in multiple values, such as when forming a bound method value.
This commit is contained in:
@@ -89,6 +89,15 @@ cc_library(
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "bindings",
|
||||
srcs = ["bindings.cpp"],
|
||||
hdrs = ["bindings.h"],
|
||||
deps = [
|
||||
"//explorer/common:nonnull",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "declaration",
|
||||
srcs = ["declaration.cpp"],
|
||||
@@ -153,6 +162,7 @@ cc_library(
|
||||
hdrs = ["expression.h", "pattern.h"],
|
||||
deps = [
|
||||
":ast_node",
|
||||
":bindings",
|
||||
":member",
|
||||
":paren_contents",
|
||||
":static_scope",
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include "explorer/ast/bindings.h"
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
auto Bindings::None() -> Nonnull<const Bindings*> {
|
||||
static Nonnull<const Bindings*> bindings = new Bindings({}, {});
|
||||
return bindings;
|
||||
}
|
||||
|
||||
} // namespace Carbon
|
||||
@@ -0,0 +1,57 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#ifndef CARBON_EXPLORER_AST_BINDINGS_H_
|
||||
#define CARBON_EXPLORER_AST_BINDINGS_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "explorer/common/nonnull.h"
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
class ImplBinding;
|
||||
class GenericBinding;
|
||||
class Value;
|
||||
|
||||
using BindingMap =
|
||||
std::map<Nonnull<const GenericBinding*>, Nonnull<const Value*>>;
|
||||
using ImplWitnessMap =
|
||||
std::map<Nonnull<const ImplBinding*>, Nonnull<const Value*>>;
|
||||
|
||||
// A set of evaluated bindings in some context, such as a function or class.
|
||||
//
|
||||
// These are shared by a context and all unparameterized entities within that
|
||||
// context. For example, a class and the name of a method within that class
|
||||
// will have the same set of bindings.
|
||||
class Bindings {
|
||||
public:
|
||||
// Create an instantiated set of bindings for use during evaluation,
|
||||
// containing both arguments and witnesses.
|
||||
Bindings(BindingMap args, ImplWitnessMap witnesses)
|
||||
: args_(args), witnesses_(witnesses) {}
|
||||
|
||||
enum NoWitnessesTag { NoWitnesses };
|
||||
|
||||
// Create a set of bindings for use during type-checking, containing only the
|
||||
// arguments but not the corresponding witnesses.
|
||||
Bindings(BindingMap args, NoWitnessesTag) : args_(args), witnesses_() {}
|
||||
|
||||
// Argument values corresponding to generic bindings.
|
||||
auto args() const -> const BindingMap& { return args_; }
|
||||
|
||||
// Witnesses corresponding to impl bindings.
|
||||
auto witnesses() const -> const ImplWitnessMap& { return witnesses_; }
|
||||
|
||||
// An empty set of bindings.
|
||||
static auto None() -> Nonnull<const Bindings*>;
|
||||
|
||||
private:
|
||||
BindingMap args_;
|
||||
ImplWitnessMap witnesses_;
|
||||
};
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
#endif // CARBON_EXPLORER_AST_BINDINGS_H_
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "common/ostream.h"
|
||||
#include "explorer/ast/ast_node.h"
|
||||
#include "explorer/ast/bindings.h"
|
||||
#include "explorer/ast/member.h"
|
||||
#include "explorer/ast/paren_contents.h"
|
||||
#include "explorer/ast/static_scope.h"
|
||||
@@ -510,11 +511,6 @@ class PrimitiveOperatorExpression : public Expression {
|
||||
std::vector<Nonnull<Expression*>> arguments_;
|
||||
};
|
||||
|
||||
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 {
|
||||
|
||||
@@ -24,6 +24,7 @@ cc_library(
|
||||
":stack",
|
||||
"//common:check",
|
||||
"//common:ostream",
|
||||
"//explorer/ast:bindings",
|
||||
"//explorer/ast:declaration",
|
||||
"//explorer/ast:expression",
|
||||
"//explorer/ast:member",
|
||||
|
||||
@@ -109,10 +109,16 @@ class Interpreter {
|
||||
auto InstantiateType(Nonnull<const Value*> type, SourceLocation source_loc)
|
||||
-> ErrorOr<Nonnull<const Value*>>;
|
||||
|
||||
// Instantiate a set of bindings by replacing all type variables that occur
|
||||
// within it by the current values of those variables.
|
||||
auto InstantiateBindings(Nonnull<const Bindings*> bindings,
|
||||
SourceLocation source_loc)
|
||||
-> ErrorOr<Nonnull<const Bindings*>>;
|
||||
|
||||
// Call the function `fun` with the given `arg` and the `witnesses`
|
||||
// for the function's impl bindings.
|
||||
auto CallFunction(const CallExpression& call, Nonnull<const Value*> fun,
|
||||
Nonnull<const Value*> arg, const ImplWitnessMap& witnesses)
|
||||
Nonnull<const Value*> arg, ImplWitnessMap&& witnesses)
|
||||
-> ErrorOr<Success>;
|
||||
|
||||
void PrintState(llvm::raw_ostream& out);
|
||||
@@ -464,26 +470,38 @@ auto Interpreter::InstantiateType(Nonnull<const Value*> type,
|
||||
}
|
||||
case Value::Kind::NominalClassType: {
|
||||
const auto& class_type = cast<NominalClassType>(*type);
|
||||
BindingMap inst_type_args;
|
||||
for (const auto& [ty_var, ty_arg] : class_type.type_args()) {
|
||||
CARBON_ASSIGN_OR_RETURN(inst_type_args[ty_var],
|
||||
InstantiateType(ty_arg, source_loc));
|
||||
}
|
||||
ImplWitnessMap witnesses = class_type.witnesses();
|
||||
for (auto& [bind, witness] : witnesses) {
|
||||
if (auto* sym = dyn_cast<SymbolicWitness>(witness)) {
|
||||
CARBON_ASSIGN_OR_RETURN(witness,
|
||||
EvalExpRecursively(&sym->impl_expression()));
|
||||
}
|
||||
}
|
||||
return arena_->New<NominalClassType>(&class_type.declaration(),
|
||||
inst_type_args, witnesses);
|
||||
CARBON_ASSIGN_OR_RETURN(
|
||||
Nonnull<const Bindings*> bindings,
|
||||
InstantiateBindings(&class_type.bindings(), source_loc));
|
||||
return arena_->New<NominalClassType>(&class_type.declaration(), bindings);
|
||||
}
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
auto Interpreter::InstantiateBindings(Nonnull<const Bindings*> bindings,
|
||||
SourceLocation source_loc)
|
||||
-> ErrorOr<Nonnull<const Bindings*>> {
|
||||
BindingMap args = bindings->args();
|
||||
for (auto& [var, arg] : args) {
|
||||
CARBON_ASSIGN_OR_RETURN(arg, InstantiateType(arg, source_loc));
|
||||
}
|
||||
|
||||
ImplWitnessMap witnesses = bindings->witnesses();
|
||||
for (auto& [bind, witness] : witnesses) {
|
||||
if (auto* sym = dyn_cast<SymbolicWitness>(witness)) {
|
||||
CARBON_ASSIGN_OR_RETURN(witness,
|
||||
EvalExpRecursively(&sym->impl_expression()));
|
||||
}
|
||||
}
|
||||
|
||||
if (args == bindings->args() && witnesses == bindings->witnesses()) {
|
||||
return bindings;
|
||||
}
|
||||
return arena_->New<Bindings>(std::move(args), std::move(witnesses));
|
||||
}
|
||||
|
||||
auto Interpreter::Convert(Nonnull<const Value*> value,
|
||||
Nonnull<const Value*> destination_type,
|
||||
SourceLocation source_loc)
|
||||
@@ -609,8 +627,7 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
|
||||
auto Interpreter::CallFunction(const CallExpression& call,
|
||||
Nonnull<const Value*> fun,
|
||||
Nonnull<const Value*> arg,
|
||||
const ImplWitnessMap& witnesses)
|
||||
-> ErrorOr<Success> {
|
||||
ImplWitnessMap&& witnesses) -> ErrorOr<Success> {
|
||||
if (trace_stream_) {
|
||||
**trace_stream_ << "calling function: " << *fun << "\n";
|
||||
}
|
||||
@@ -703,13 +720,15 @@ auto Interpreter::CallFunction(const CallExpression& call,
|
||||
CARBON_CHECK(PatternMatch(&name.params().value(), arg, call.source_loc(),
|
||||
¶ms_scope, generic_args, trace_stream_,
|
||||
this->arena_));
|
||||
Nonnull<const Bindings*> bindings =
|
||||
arena_->New<Bindings>(std::move(generic_args), std::move(witnesses));
|
||||
switch (decl.kind()) {
|
||||
case DeclarationKind::ClassDeclaration:
|
||||
return todo_.FinishAction(arena_->New<NominalClassType>(
|
||||
&cast<ClassDeclaration>(decl), generic_args, witnesses));
|
||||
&cast<ClassDeclaration>(decl), bindings));
|
||||
case DeclarationKind::InterfaceDeclaration:
|
||||
return todo_.FinishAction(arena_->New<InterfaceType>(
|
||||
&cast<InterfaceDeclaration>(decl), generic_args, witnesses));
|
||||
&cast<InterfaceDeclaration>(decl), bindings));
|
||||
default:
|
||||
CARBON_FATAL() << "unknown kind of ParameterizedEntityName " << decl;
|
||||
}
|
||||
@@ -751,7 +770,9 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
|
||||
++i;
|
||||
}
|
||||
return todo_.FinishAction(arena_->New<ImplWitness>(
|
||||
&generic_witness->declaration(), inst_impl.type_args(), witnesses));
|
||||
&generic_witness->declaration(),
|
||||
arena_->New<Bindings>(inst_impl.type_args(),
|
||||
std::move(witnesses))));
|
||||
}
|
||||
}
|
||||
case ExpressionKind::IndexExpression: {
|
||||
@@ -1000,7 +1021,7 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
|
||||
}
|
||||
}
|
||||
return CallFunction(call, act.results()[0], act.results()[1],
|
||||
witnesses);
|
||||
std::move(witnesses));
|
||||
} else if (act.pos() == 3 + int(num_impls)) {
|
||||
if (act.results().size() < 3 + num_impls) {
|
||||
// Control fell through without explicit return.
|
||||
|
||||
@@ -448,14 +448,17 @@ auto TypeChecker::GetBuiltinInterfaceType(SourceLocation source_loc,
|
||||
if (has_parameters != has_arguments) {
|
||||
return bad_builtin();
|
||||
}
|
||||
BindingMap bindings;
|
||||
BindingMap binding_args;
|
||||
if (has_arguments) {
|
||||
TupleValue args(interface.arguments);
|
||||
if (!PatternMatch(&iface_decl->params().value()->value(), &args, source_loc,
|
||||
std::nullopt, bindings, trace_stream_, this->arena_)) {
|
||||
std::nullopt, binding_args, trace_stream_,
|
||||
this->arena_)) {
|
||||
return bad_builtin();
|
||||
}
|
||||
}
|
||||
Nonnull<const Bindings*> bindings =
|
||||
arena_->New<Bindings>(std::move(binding_args), Bindings::NoWitnesses);
|
||||
return arena_->New<InterfaceType>(iface_decl, bindings);
|
||||
}
|
||||
|
||||
@@ -875,12 +878,13 @@ class ConstraintTypeBuilder {
|
||||
auto TypeChecker::Substitute(
|
||||
const std::map<Nonnull<const GenericBinding*>, Nonnull<const Value*>>& dict,
|
||||
Nonnull<const Value*> type) const -> Nonnull<const Value*> {
|
||||
auto SubstituteIntoBindingMap = [&](const BindingMap& map) -> BindingMap {
|
||||
auto SubstituteIntoBindings =
|
||||
[&](const Bindings& bindings) -> Nonnull<const Bindings*> {
|
||||
BindingMap result;
|
||||
for (const auto& [name, value] : map) {
|
||||
for (const auto& [name, value] : bindings.args()) {
|
||||
result[name] = Substitute(dict, value);
|
||||
}
|
||||
return result;
|
||||
return arena_->New<Bindings>(std::move(result), Bindings::NoWitnesses);
|
||||
};
|
||||
|
||||
switch (type->kind()) {
|
||||
@@ -971,14 +975,14 @@ auto TypeChecker::Substitute(
|
||||
Nonnull<const NominalClassType*> new_class_type =
|
||||
arena_->New<NominalClassType>(
|
||||
&class_type.declaration(),
|
||||
SubstituteIntoBindingMap(class_type.type_args()));
|
||||
SubstituteIntoBindings(class_type.bindings()));
|
||||
return new_class_type;
|
||||
}
|
||||
case Value::Kind::InterfaceType: {
|
||||
const auto& iface_type = cast<InterfaceType>(*type);
|
||||
Nonnull<const InterfaceType*> new_iface_type = arena_->New<InterfaceType>(
|
||||
&iface_type.declaration(),
|
||||
SubstituteIntoBindingMap(iface_type.args()));
|
||||
SubstituteIntoBindings(iface_type.bindings()));
|
||||
return new_iface_type;
|
||||
}
|
||||
case Value::Kind::ConstraintType: {
|
||||
@@ -1975,13 +1979,15 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
|
||||
CARBON_RETURN_IF_ERROR(DeduceCallBindings(
|
||||
call, ¶m_name.params().static_type(), generic_parameters,
|
||||
/*deduced_bindings=*/llvm::None, impl_bindings, impl_scope));
|
||||
Nonnull<const Bindings*> bindings =
|
||||
arena_->New<Bindings>(call.deduced_args(), Bindings::NoWitnesses);
|
||||
|
||||
const Declaration& decl = param_name.declaration();
|
||||
switch (decl.kind()) {
|
||||
case DeclarationKind::ClassDeclaration: {
|
||||
Nonnull<NominalClassType*> inst_class_type =
|
||||
arena_->New<NominalClassType>(&cast<ClassDeclaration>(decl),
|
||||
call.deduced_args());
|
||||
bindings);
|
||||
call.set_static_type(
|
||||
arena_->New<TypeOfClassType>(inst_class_type));
|
||||
call.set_value_category(ValueCategory::Let);
|
||||
@@ -1990,7 +1996,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
|
||||
case DeclarationKind::InterfaceDeclaration: {
|
||||
Nonnull<InterfaceType*> inst_iface_type =
|
||||
arena_->New<InterfaceType>(&cast<InterfaceDeclaration>(decl),
|
||||
call.deduced_args());
|
||||
bindings);
|
||||
call.set_static_type(
|
||||
arena_->New<TypeOfInterfaceType>(inst_iface_type));
|
||||
call.set_value_category(ValueCategory::Let);
|
||||
@@ -2892,8 +2898,9 @@ auto TypeChecker::DeclareClassDeclaration(Nonnull<ClassDeclaration*> class_decl,
|
||||
// above and/or by any enclosing generic classes.
|
||||
generic_args[binding] = *binding->symbolic_identity();
|
||||
}
|
||||
Nonnull<NominalClassType*> self_type =
|
||||
arena_->New<NominalClassType>(class_decl, generic_args);
|
||||
Nonnull<NominalClassType*> self_type = arena_->New<NominalClassType>(
|
||||
class_decl,
|
||||
arena_->New<Bindings>(std::move(generic_args), Bindings::NoWitnesses));
|
||||
SetConstantValue(self, self_type);
|
||||
self->set_static_type(arena_->New<TypeOfClassType>(self_type));
|
||||
|
||||
|
||||
@@ -46,14 +46,12 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
|
||||
const auto& fun_decl = cast<FunctionDeclaration>(**mem_decl);
|
||||
if (fun_decl.is_method()) {
|
||||
return arena->New<BoundMethodValue>(&fun_decl, v,
|
||||
impl_witness->type_args(),
|
||||
impl_witness->witnesses());
|
||||
&impl_witness->bindings());
|
||||
} else {
|
||||
// Class function.
|
||||
auto* fun = cast<FunctionValue>(*fun_decl.constant_value());
|
||||
return arena->New<FunctionValue>(&fun->declaration(),
|
||||
impl_witness->type_args(),
|
||||
impl_witness->witnesses());
|
||||
&impl_witness->bindings());
|
||||
}
|
||||
} else {
|
||||
return CompilationError(source_loc)
|
||||
@@ -101,13 +99,11 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
|
||||
// Found a method. Turn it into a bound method.
|
||||
const FunctionValue& m = cast<FunctionValue>(**func);
|
||||
return arena->New<BoundMethodValue>(&m.declaration(), me_value,
|
||||
class_type.type_args(),
|
||||
class_type.witnesses());
|
||||
&class_type.bindings());
|
||||
} else {
|
||||
// Found a class function
|
||||
return arena->New<FunctionValue>(&(*func)->declaration(),
|
||||
class_type.type_args(),
|
||||
class_type.witnesses());
|
||||
&class_type.bindings());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,8 +125,7 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
|
||||
<< "class function " << f << " not in " << *v;
|
||||
}
|
||||
return arena->New<FunctionValue>(&(*fun)->declaration(),
|
||||
class_type.type_args(),
|
||||
class_type.witnesses());
|
||||
&class_type.bindings());
|
||||
}
|
||||
default:
|
||||
CARBON_FATAL() << "field access not allowed for value " << *v;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "common/ostream.h"
|
||||
#include "explorer/ast/bindings.h"
|
||||
#include "explorer/ast/declaration.h"
|
||||
#include "explorer/ast/member.h"
|
||||
#include "explorer/ast/statement.h"
|
||||
@@ -127,9 +128,6 @@ class IntValue : public Value {
|
||||
int value_;
|
||||
};
|
||||
|
||||
using ImplWitnessMap =
|
||||
std::map<Nonnull<const ImplBinding*>, Nonnull<const Value*>>;
|
||||
|
||||
// A function value.
|
||||
class FunctionValue : public Value {
|
||||
public:
|
||||
@@ -137,12 +135,10 @@ class FunctionValue : public Value {
|
||||
: Value(Kind::FunctionValue), declaration_(declaration) {}
|
||||
|
||||
explicit FunctionValue(Nonnull<const FunctionDeclaration*> declaration,
|
||||
const BindingMap& type_args,
|
||||
const ImplWitnessMap& wits)
|
||||
Nonnull<const Bindings*> bindings)
|
||||
: Value(Kind::FunctionValue),
|
||||
declaration_(declaration),
|
||||
type_args_(type_args),
|
||||
witnesses_(wits) {}
|
||||
bindings_(bindings) {}
|
||||
|
||||
static auto classof(const Value* value) -> bool {
|
||||
return value->kind() == Kind::FunctionValue;
|
||||
@@ -152,14 +148,17 @@ class FunctionValue : public Value {
|
||||
return *declaration_;
|
||||
}
|
||||
|
||||
auto type_args() const -> const BindingMap& { return type_args_; }
|
||||
auto bindings() const -> const Bindings& { return *bindings_; }
|
||||
|
||||
auto witnesses() const -> const ImplWitnessMap& { return witnesses_; }
|
||||
auto type_args() const -> const BindingMap& { return bindings_->args(); }
|
||||
|
||||
auto witnesses() const -> const ImplWitnessMap& {
|
||||
return bindings_->witnesses();
|
||||
}
|
||||
|
||||
private:
|
||||
Nonnull<const FunctionDeclaration*> declaration_;
|
||||
BindingMap type_args_;
|
||||
ImplWitnessMap witnesses_;
|
||||
Nonnull<const Bindings*> bindings_ = Bindings::None();
|
||||
};
|
||||
|
||||
// A bound method value. It includes the receiver object.
|
||||
@@ -173,13 +172,11 @@ class BoundMethodValue : public Value {
|
||||
|
||||
explicit BoundMethodValue(Nonnull<const FunctionDeclaration*> declaration,
|
||||
Nonnull<const Value*> receiver,
|
||||
const BindingMap& type_args,
|
||||
const ImplWitnessMap& wits)
|
||||
Nonnull<const Bindings*> bindings)
|
||||
: Value(Kind::BoundMethodValue),
|
||||
declaration_(declaration),
|
||||
receiver_(receiver),
|
||||
type_args_(type_args),
|
||||
witnesses_(wits) {}
|
||||
bindings_(bindings) {}
|
||||
|
||||
static auto classof(const Value* value) -> bool {
|
||||
return value->kind() == Kind::BoundMethodValue;
|
||||
@@ -191,15 +188,18 @@ class BoundMethodValue : public Value {
|
||||
|
||||
auto receiver() const -> Nonnull<const Value*> { return receiver_; }
|
||||
|
||||
auto type_args() const -> const BindingMap& { return type_args_; }
|
||||
auto bindings() const -> const Bindings& { return *bindings_; }
|
||||
|
||||
auto witnesses() const -> const ImplWitnessMap& { return witnesses_; }
|
||||
auto type_args() const -> const BindingMap& { return bindings_->args(); }
|
||||
|
||||
auto witnesses() const -> const ImplWitnessMap& {
|
||||
return bindings_->witnesses();
|
||||
}
|
||||
|
||||
private:
|
||||
Nonnull<const FunctionDeclaration*> declaration_;
|
||||
Nonnull<const Value*> receiver_;
|
||||
BindingMap type_args_;
|
||||
ImplWitnessMap witnesses_;
|
||||
Nonnull<const Bindings*> bindings_ = Bindings::None();
|
||||
};
|
||||
|
||||
// The value of a location in memory.
|
||||
@@ -549,40 +549,36 @@ class NominalClassType : public Value {
|
||||
<< "missing arguments for parameterized class type";
|
||||
}
|
||||
|
||||
// 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 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 ImplWitnessMap& wits)
|
||||
Nonnull<const Bindings*> bindings)
|
||||
: Value(Kind::NominalClassType),
|
||||
declaration_(declaration),
|
||||
type_args_(type_args),
|
||||
witnesses_(wits) {}
|
||||
bindings_(bindings) {}
|
||||
|
||||
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 impl bindings 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 ImplWitnessMap& { return witnesses_; }
|
||||
auto bindings() const -> const Bindings& { return *bindings_; }
|
||||
|
||||
auto type_args() const -> const BindingMap& { return bindings_->args(); }
|
||||
|
||||
// Witnesses for each of the class's impl bindings. These will not in general
|
||||
// be set for class types that are only intended to be used within
|
||||
// type-checking and not at runtime, such as in the static_type() of an
|
||||
// expression or the type in a TypeOfClassType.
|
||||
auto witnesses() const -> const ImplWitnessMap& {
|
||||
return bindings_->witnesses();
|
||||
}
|
||||
|
||||
// Returns whether this a parameterized class. That is, a class with
|
||||
// parameters and no corresponding arguments.
|
||||
auto IsParameterized() const -> bool {
|
||||
return declaration_->type_params().has_value() && type_args_.empty();
|
||||
return declaration_->type_params().has_value() && type_args().empty();
|
||||
}
|
||||
|
||||
// Returns the value of the function named `name` in this class, or
|
||||
@@ -592,8 +588,7 @@ class NominalClassType : public Value {
|
||||
|
||||
private:
|
||||
Nonnull<const ClassDeclaration*> declaration_;
|
||||
BindingMap type_args_;
|
||||
ImplWitnessMap witnesses_;
|
||||
Nonnull<const Bindings*> bindings_ = Bindings::None();
|
||||
};
|
||||
|
||||
// Return the declaration of the member with the given name.
|
||||
@@ -602,7 +597,6 @@ auto FindMember(std::string_view name,
|
||||
-> std::optional<Nonnull<const Declaration*>>;
|
||||
|
||||
// An interface type.
|
||||
// TODO: Consider removing this once ConstraintType is ready.
|
||||
class InterfaceType : public Value {
|
||||
public:
|
||||
explicit InterfaceType(Nonnull<const InterfaceDeclaration*> declaration)
|
||||
@@ -611,14 +605,10 @@ class InterfaceType : public Value {
|
||||
<< "missing arguments for parameterized interface type";
|
||||
}
|
||||
explicit InterfaceType(Nonnull<const InterfaceDeclaration*> declaration,
|
||||
const BindingMap& args)
|
||||
: Value(Kind::InterfaceType), declaration_(declaration), args_(args) {}
|
||||
explicit InterfaceType(Nonnull<const InterfaceDeclaration*> declaration,
|
||||
const BindingMap& args, const ImplWitnessMap& wits)
|
||||
Nonnull<const Bindings*> bindings)
|
||||
: Value(Kind::InterfaceType),
|
||||
declaration_(declaration),
|
||||
args_(args),
|
||||
witnesses_(wits) {}
|
||||
bindings_(bindings) {}
|
||||
|
||||
static auto classof(const Value* value) -> bool {
|
||||
return value->kind() == Kind::InterfaceType;
|
||||
@@ -627,15 +617,18 @@ class InterfaceType : public Value {
|
||||
auto declaration() const -> const InterfaceDeclaration& {
|
||||
return *declaration_;
|
||||
}
|
||||
auto args() const -> const BindingMap& { return args_; }
|
||||
|
||||
// TODO: These aren't used for anything yet.
|
||||
auto witnesses() const -> const ImplWitnessMap& { return witnesses_; }
|
||||
auto bindings() const -> const Bindings& { return *bindings_; }
|
||||
|
||||
auto args() const -> const BindingMap& { return bindings_->args(); }
|
||||
|
||||
auto witnesses() const -> const ImplWitnessMap& {
|
||||
return bindings_->witnesses();
|
||||
}
|
||||
|
||||
private:
|
||||
Nonnull<const InterfaceDeclaration*> declaration_;
|
||||
BindingMap args_;
|
||||
ImplWitnessMap witnesses_;
|
||||
Nonnull<const Bindings*> bindings_ = Bindings::None();
|
||||
};
|
||||
|
||||
// A type-of-type for an unknown constrained type.
|
||||
@@ -733,26 +726,27 @@ class ImplWitness : public Witness {
|
||||
|
||||
// Construct an instantiated generic impl.
|
||||
explicit ImplWitness(Nonnull<const ImplDeclaration*> declaration,
|
||||
const BindingMap& type_args, const ImplWitnessMap& wits)
|
||||
Nonnull<const Bindings*> bindings)
|
||||
: Witness(Kind::ImplWitness),
|
||||
declaration_(declaration),
|
||||
type_args_(type_args),
|
||||
witnesses_(wits) {}
|
||||
bindings_(bindings) {}
|
||||
|
||||
static auto classof(const Value* value) -> bool {
|
||||
return value->kind() == Kind::ImplWitness;
|
||||
}
|
||||
auto declaration() const -> const ImplDeclaration& { return *declaration_; }
|
||||
auto type_args() const -> const BindingMap& { return type_args_; }
|
||||
// Maps each of the impl's impl bindings 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 ImplWitnessMap& { return witnesses_; }
|
||||
|
||||
auto bindings() const -> const Bindings& { return *bindings_; }
|
||||
|
||||
auto type_args() const -> const BindingMap& { return bindings_->args(); }
|
||||
|
||||
auto witnesses() const -> const ImplWitnessMap& {
|
||||
return bindings_->witnesses();
|
||||
}
|
||||
|
||||
private:
|
||||
Nonnull<const ImplDeclaration*> declaration_;
|
||||
BindingMap type_args_;
|
||||
ImplWitnessMap witnesses_;
|
||||
Nonnull<const Bindings*> bindings_ = Bindings::None();
|
||||
};
|
||||
|
||||
// A witness table whose concrete value cannot be determined yet.
|
||||
|
||||
Reference in New Issue
Block a user