mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-25 16:00:09 +01:00
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)
106 lines
3.4 KiB
C++
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_
|