Files
carbon-lang/explorer/ast/impl_binding.h
T
Adrien Leravat d0645c6a85 Explorer: rename value categories to expression categories (#2744)
Rename value categories to expression categories based on [Discord discussion](https://discord.com/channels/655572317891461132/753021843459538996/1092924035517665332) regarding naming and behavior.

>* let expression -> value expression
>* var expression -> reference expression
>* located expression -> initializing expression
>So:
>- "value expressions" produce values (with no associated location). "reference expressions" produce a location of an existing value. "initializing expressions" take a location and initialize it.
>- A let binding is initialized by a value expression, because lets represent values (with category conversions performed as needed, but if a conversion is performed from a different category of expression, the value of the object is pinned for the lifetime of the let).
>- A var binding is initialized by an initializing expression, without performing a copy (with category conversions performed as needed, calling a copy constructor if the initializer is a different expression category).
>- The & operator requires a reference expression, and it's an error to give it other kinds.
>- The left-hand side of . requires a value expression when calling a function with a non-addr receiver, and requires a reference expression when calling a function with an addr receiver (it's an error to give it a value expression, and for an initializing expression, a temporary is materialized).

Changes
* Rename "value category" to "expression category"
* Rename Var and Let value categories to Value, Reference, and Initializing expression
* Rename `lvalue` to `location` (most of the time)
2023-04-05 16:16:10 -07:00

106 lines
3.4 KiB
C++

// 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_IMPL_BINDING_H_
#define CARBON_EXPLORER_AST_IMPL_BINDING_H_
#include <map>
#include "common/check.h"
#include "common/ostream.h"
#include "explorer/ast/ast_node.h"
#include "explorer/ast/expression_category.h"
namespace Carbon {
class Value;
class Expression;
class GenericBinding;
// `ImplBinding` plays the role of the parameter for passing witness
// tables to a generic. However, unlike regular parameters
// (`BindingPattern`) there is no explicit syntax that corresponds to
// an `ImplBinding`, so they are not created during parsing. Instances
// of `ImplBinding` are created during type checking, when processing
// a type parameter (a `GenericBinding`), or an `impls` requirement in
// a `where` clause.
class ImplBinding : public AstNode {
public:
using ImplementsCarbonValueNode = void;
ImplBinding(SourceLocation source_loc,
Nonnull<const GenericBinding*> type_var,
std::optional<Nonnull<const Value*>> iface)
: AstNode(AstNodeKind::ImplBinding, source_loc),
type_var_(type_var),
iface_(iface) {}
explicit ImplBinding(CloneContext& context, const ImplBinding& other);
static auto classof(const AstNode* node) -> bool {
return InheritsFromImplBinding(node->kind());
}
void Print(llvm::raw_ostream& out) const override;
void PrintID(llvm::raw_ostream& out) const override;
// The binding for the type variable.
auto type_var() const -> Nonnull<const GenericBinding*> { return type_var_; }
// The constraint being implemented.
// TODO: Rename this to `constraint`.
auto interface() const -> Nonnull<const Value*> {
CARBON_CHECK(iface_) << "interface has not been set yet";
return *iface_;
}
// Set the interface being implemented, if not set by the constructor. Should
// only be called by typechecking.
void set_interface(Nonnull<const Value*> iface) {
CARBON_CHECK(!iface_) << "interface set twice";
iface_ = iface;
}
// Required for the ValueNode interface
auto constant_value() const -> std::optional<Nonnull<const Value*>> {
return std::nullopt;
}
auto symbolic_identity() const -> std::optional<Nonnull<const Value*>> {
return symbolic_identity_;
}
void set_symbolic_identity(Nonnull<const Value*> value) {
CARBON_CHECK(!symbolic_identity_.has_value());
symbolic_identity_ = value;
}
// These functions exist only so that an `ImplBinding` can be used as a
// `ValueNodeView` as a key in a `StaticScope`.
auto static_type() const -> const Value& {
CARBON_FATAL() << "an ImplBinding has no type";
}
auto expression_category() const -> ExpressionCategory {
return ExpressionCategory::Value;
}
// Return the original impl binding.
auto original() const -> Nonnull<const ImplBinding*> {
if (original_.has_value()) {
return *original_;
} else {
return this;
}
}
// Set the original impl binding.
void set_original(Nonnull<const ImplBinding*> orig) { original_ = orig; }
private:
Nonnull<const GenericBinding*> type_var_;
std::optional<Nonnull<const Value*>> iface_;
std::optional<Nonnull<const Value*>> symbolic_identity_;
std::optional<Nonnull<const ImplBinding*>> original_;
};
} // namespace Carbon
#endif // CARBON_EXPLORER_AST_IMPL_BINDING_H_