Track a resolved Member on each member access expression. (#1333)

Type checking now stores information on a member access identifying the member that was accessed, not only its name. This parallels what we do for other similar constructs whose meaning is resolved by name lookup or type-checking, and will allow us to avoid redoing lookups in some cases during interpretation.
This commit is contained in:
Richard Smith
2022-06-16 17:22:31 -07:00
committed by GitHub
parent 4113ec8a67
commit 17ee3ed9b7
16 changed files with 222 additions and 115 deletions
+26
View File
@@ -9,6 +9,7 @@ cc_library(
hdrs = ["ast.h"],
deps = [
":declaration",
":member_impl",
":library_name",
"//explorer/common:nonnull",
],
@@ -109,6 +110,30 @@ cc_library(
],
)
cc_library(
name = "member",
hdrs = [
"member.h",
],
deps = [
"//explorer/common:nonnull",
"@llvm-project//llvm:Support",
],
)
# TODO: This is split out to resolve a cyclic implementation dependency between
# this and :declaration. Consider folding all of the "ast" target together.
cc_library(
name = "member_impl",
srcs = ["member.cpp"],
deps = [
":declaration",
":member",
"//explorer/common:nonnull",
"@llvm-project//llvm:Support",
],
)
cc_library(
name = "return_term",
hdrs = ["return_term.h"],
@@ -128,6 +153,7 @@ cc_library(
hdrs = ["expression.h", "pattern.h"],
deps = [
":ast_node",
":member",
":paren_contents",
":static_scope",
":value_category",
+2 -1
View File
@@ -143,7 +143,8 @@ void Declaration::PrintID(llvm::raw_ostream& out) const {
}
}
auto GetName(const Declaration& declaration) -> std::optional<std::string> {
auto GetName(const Declaration& declaration)
-> std::optional<std::string_view> {
switch (declaration.kind()) {
case DeclarationKind::FunctionDeclaration:
return cast<FunctionDeclaration>(declaration).name();
+4 -3
View File
@@ -6,6 +6,7 @@
#define CARBON_EXPLORER_AST_DECLARATION_H_
#include <string>
#include <string_view>
#include <utility>
#include <vector>
@@ -174,7 +175,7 @@ class SelfDeclaration : public Declaration {
return InheritsFromSelfDeclaration(node->kind());
}
auto name() const -> const std::string { return "Self"; }
static auto name() -> std::string_view { return "Self"; }
auto value_category() const -> ValueCategory { return ValueCategory::Let; }
};
@@ -437,7 +438,7 @@ class AliasDeclaration : public Declaration {
return InheritsFromAliasDeclaration(node->kind());
}
auto name() const -> const std::string { return name_; }
auto name() const -> const std::string& { return name_; }
auto target() const -> const Expression& { return *target_; }
auto target() -> Expression& { return *target_; }
auto value_category() const -> ValueCategory { return ValueCategory::Let; }
@@ -448,7 +449,7 @@ class AliasDeclaration : public Declaration {
};
// Return the name of a declaration, if it has one.
auto GetName(const Declaration&) -> std::optional<std::string>;
auto GetName(const Declaration&) -> std::optional<std::string_view>;
} // namespace Carbon
+1 -1
View File
@@ -96,7 +96,7 @@ void Expression::Print(llvm::raw_ostream& out) const {
}
case ExpressionKind::SimpleMemberAccessExpression: {
const auto& access = cast<SimpleMemberAccessExpression>(*this);
out << access.object() << "." << access.member();
out << access.object() << "." << access.member_name();
break;
}
case ExpressionKind::CompoundMemberAccessExpression: {
+19 -4
View File
@@ -13,6 +13,7 @@
#include "common/ostream.h"
#include "explorer/ast/ast_node.h"
#include "explorer/ast/member.h"
#include "explorer/ast/paren_contents.h"
#include "explorer/ast/static_scope.h"
#include "explorer/ast/value_category.h"
@@ -193,10 +194,10 @@ class SimpleMemberAccessExpression : public Expression {
public:
explicit SimpleMemberAccessExpression(SourceLocation source_loc,
Nonnull<Expression*> object,
std::string member)
std::string member_name)
: Expression(AstNodeKind::SimpleMemberAccessExpression, source_loc),
object_(object),
member_(std::move(member)) {}
member_name_(std::move(member_name)) {}
static auto classof(const AstNode* node) -> bool {
return InheritsFromSimpleMemberAccessExpression(node->kind());
@@ -204,7 +205,20 @@ class SimpleMemberAccessExpression : public Expression {
auto object() const -> const Expression& { return *object_; }
auto object() -> Expression& { return *object_; }
auto member() const -> const std::string& { return member_; }
auto member_name() const -> const std::string& { return member_name_; }
// Returns the `Member` that the member name resolved to.
// Should not be called before typechecking.
auto member() const -> const Member& {
CARBON_CHECK(member_.has_value());
return *member_;
}
// Can only be called once, during typechecking.
void set_member(Member member) {
CARBON_CHECK(!member_.has_value());
member_ = member;
}
// Returns true if the field is a method that has a "me" declaration in an
// AddrPattern.
@@ -244,7 +258,8 @@ class SimpleMemberAccessExpression : public Expression {
private:
Nonnull<Expression*> object_;
std::string member_;
std::string member_name_;
std::optional<Member> member_;
bool is_field_addr_me_method_ = false;
std::optional<Nonnull<const Expression*>> impl_;
std::optional<Nonnull<const InterfaceType*>> found_in_interface_;
+40
View File
@@ -0,0 +1,40 @@
// 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/member.h"
#include "explorer/ast/declaration.h"
namespace Carbon {
Member::Member(Nonnull<const Declaration*> declaration)
: member_(declaration) {}
Member::Member(Nonnull<const NamedValue*> struct_member)
: member_(struct_member) {}
auto Member::name() const -> std::string_view {
if (const Declaration* decl = member_.dyn_cast<const Declaration*>()) {
return GetName(*decl).value();
} else {
return member_.get<const NamedValue*>()->name;
}
}
auto Member::type() const -> const Value& {
if (const Declaration* decl = member_.dyn_cast<const Declaration*>()) {
return decl->static_type();
} else {
return *member_.get<const NamedValue*>()->value;
}
}
auto Member::declaration() const -> std::optional<Nonnull<const Declaration*>> {
if (const Declaration* decl = member_.dyn_cast<const Declaration*>()) {
return decl;
}
return std::nullopt;
}
} // namespace Carbon
+51
View File
@@ -0,0 +1,51 @@
// 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_MEMBER_H_
#define CARBON_EXPLORER_AST_MEMBER_H_
#include <optional>
#include <string>
#include "explorer/common/nonnull.h"
#include "llvm/ADT/PointerUnion.h"
namespace Carbon {
class Declaration;
class Value;
// A NamedValue represents a value with a name, such as a single struct field.
struct NamedValue {
// The field name.
std::string name;
// The field's value.
Nonnull<const Value*> value;
};
// A member of a type.
//
// This is either a declared member of a class, interface, or similar, or a
// member of a struct with no declaration.
class Member {
public:
explicit Member(Nonnull<const Declaration*> declaration);
explicit Member(Nonnull<const NamedValue*> struct_member);
// The name of the member.
auto name() const -> std::string_view;
// The declared type of the member, which might include type variables.
auto type() const -> const Value&;
// A declaration of the member, if any exists.
auto declaration() const -> std::optional<Nonnull<const Declaration*>>;
private:
llvm::PointerUnion<Nonnull<const Declaration*>, Nonnull<const NamedValue*>>
member_;
};
} // namespace Carbon
#endif // CARBON_EXPLORER_AST_MEMBER_H_
+2 -1
View File
@@ -334,7 +334,8 @@ class AlternativePattern : public Pattern {
Nonnull<SimpleMemberAccessExpression*> member_access,
RequireSimpleMemberAccess(alternative));
return arena->New<AlternativePattern>(source_loc, &member_access->object(),
member_access->member(), arguments);
member_access->member_name(),
arguments);
}
// Constructs an AlternativePattern that matches a value of the type
+2 -2
View File
@@ -113,12 +113,12 @@ static auto ExpressionToProto(const Expression& expression)
// The parser rewrites `.Foo` into `.Self.Foo`. Undo this
// transformation.
auto* designator_proto = expression_proto.mutable_designator();
designator_proto->set_name(simple_member_access.member());
designator_proto->set_name(simple_member_access.member_name());
break;
}
auto* simple_member_access_proto =
expression_proto.mutable_simple_member_access();
simple_member_access_proto->set_field(simple_member_access.member());
simple_member_access_proto->set_field(simple_member_access.member_name());
*simple_member_access_proto->mutable_object() =
ExpressionToProto(simple_member_access.object());
break;
+2
View File
@@ -26,6 +26,7 @@ cc_library(
"//common:ostream",
"//explorer/ast:declaration",
"//explorer/ast:expression",
"//explorer/ast:member",
"//explorer/ast:statement",
"//explorer/common:arena",
"//explorer/common:error_builders",
@@ -90,6 +91,7 @@ cc_library(
deps = [
"//common:ostream",
"//explorer/ast",
"//explorer/ast:member",
"//explorer/ast:static_scope",
"@llvm-project//llvm:Support",
],
+2 -2
View File
@@ -66,9 +66,9 @@ class Address {
// If *this represents the address of an object with a field named
// `field_name`, this method returns the address of that field.
auto SubobjectAddress(std::string field_name) const -> Address {
auto SubobjectAddress(Member member) const -> Address {
Address result = *this;
result.field_path_.Append(std::move(field_name));
result.field_path_.Append(member);
return result;
}
+13 -11
View File
@@ -9,6 +9,7 @@
#include <vector>
#include "common/ostream.h"
#include "explorer/ast/member.h"
#include "explorer/ast/static_scope.h"
#include "llvm/Support/Compiler.h"
@@ -38,26 +39,27 @@ class FieldPath {
// need `witness`, a pointer to the witness table containing that field.
class Component {
public:
explicit Component(std::string name) : name_(std::move(name)) {}
Component(std::string name, std::optional<Nonnull<const Witness*>> witness)
: name_(std::move(name)), witness_(witness) {}
explicit Component(Member member) : member_(member) {}
Component(Member member, std::optional<Nonnull<const Witness*>> witness)
: member_(member), witness_(witness) {}
auto name() const -> const std::string& { return name_; }
auto member() const -> Member { return member_; }
auto name() const -> std::string_view { return member_.name(); }
auto witness() const -> std::optional<Nonnull<const Witness*>> {
return witness_;
}
void Print(llvm::raw_ostream& out) const { out << name_; }
void Print(llvm::raw_ostream& out) const { out << name(); }
private:
std::string name_;
Member member_;
std::optional<Nonnull<const Witness*>> witness_;
};
// Constructs a FieldPath consisting of a single step.
explicit FieldPath(std::string name)
: components_({Component(std::move(name))}) {}
explicit FieldPath(Member member) : components_({Component(member)}) {}
explicit FieldPath(const Component& f) : components_({f}) {}
FieldPath(const FieldPath&) = default;
@@ -68,9 +70,9 @@ class FieldPath {
// Returns whether *this is empty.
auto IsEmpty() const -> bool { return components_.empty(); }
// Appends `name` to the end of *this.
auto Append(std::string name) -> void {
components_.push_back(Component(std::move(name)));
// Appends `member` to the end of *this.
auto Append(Member member) -> void {
components_.push_back(Component(member));
}
void Print(llvm::raw_ostream& out) const {
+8 -3
View File
@@ -352,7 +352,7 @@ auto Interpreter::StepLvalue() -> ErrorOr<Success> {
Convert(act.results()[0], *access.member().base_type(),
exp.source_loc()));
Address object = cast<LValue>(*val).address();
Address field = object.SubobjectAddress(access.member().name());
Address field = object.SubobjectAddress(access.member().member());
return todo_.FinishAction(arena_->New<LValue>(field));
}
}
@@ -370,9 +370,14 @@ auto Interpreter::StepLvalue() -> ErrorOr<Success> {
// { v :: [][i] :: C, E, F} :: S, H}
// -> { { &v[i] :: C, E, F} :: S, H }
Address object = cast<LValue>(*act.results()[0]).address();
// TODO: Add support to `Member` for naming tuple fields rather than
// pretending we have struct fields with numerical names.
std::string f =
std::to_string(cast<IntValue>(*act.results()[1]).value());
Address field = object.SubobjectAddress(f);
auto* tuple_field_as_struct_field =
arena_->New<NamedValue>(NamedValue{f, &exp.static_type()});
Address field =
object.SubobjectAddress(Member(tuple_field_as_struct_field));
return todo_.FinishAction(arena_->New<LValue>(field));
}
}
@@ -907,7 +912,7 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
object, Convert(object, *access.member().base_type(),
exp.source_loc()));
}
FieldPath::Component field(access.member().name(), witness);
FieldPath::Component field(access.member().member(), witness);
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> member,
object->GetMember(arena_, FieldPath(field),
exp.source_loc(), object));
+34 -21
View File
@@ -1434,16 +1434,17 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
switch (object_type.kind()) {
case Value::Kind::StructType: {
const auto& struct_type = cast<StructType>(object_type);
for (const auto& [field_name, field_type] : struct_type.fields()) {
if (access.member() == field_name) {
access.set_static_type(field_type);
for (const auto& field : struct_type.fields()) {
if (access.member_name() == field.name) {
access.set_member(Member(&field));
access.set_static_type(field.value);
access.set_value_category(access.object().value_category());
return Success();
}
}
return CompilationError(access.source_loc())
<< "struct " << struct_type << " does not have a field named "
<< access.member();
<< access.member_name();
}
case Value::Kind::TypeType: {
CARBON_ASSIGN_OR_RETURN(
@@ -1451,7 +1452,8 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
InterpExp(&access.object(), arena_, trace_stream_));
if (const auto* struct_type = dyn_cast<StructType>(type)) {
for (const auto& field : struct_type->fields()) {
if (access.member() == field.name) {
if (access.member_name() == field.name) {
access.set_member(Member(&field));
access.set_static_type(
arena_->New<TypeOfMemberName>(Member(&field)));
access.set_value_category(ValueCategory::Let);
@@ -1460,7 +1462,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
}
return CompilationError(access.source_loc())
<< "struct " << *struct_type
<< " does not have a field named " << access.member();
<< " does not have a field named " << access.member_name();
}
// TODO: We should handle all types here, not only structs. For
// example:
@@ -1476,11 +1478,12 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
}
case Value::Kind::NominalClassType: {
const auto& t_class = cast<NominalClassType>(object_type);
if (std::optional<Nonnull<const Declaration*>> member =
FindMember(access.member(), t_class.declaration().members());
if (std::optional<Nonnull<const Declaration*>> member = FindMember(
access.member_name(), t_class.declaration().members());
member.has_value()) {
Nonnull<const Value*> field_type =
Substitute(t_class.type_args(), &(*member)->static_type());
access.set_member(Member(member.value()));
access.set_static_type(field_type);
switch ((*member)->kind()) {
case DeclarationKind::VariableDeclaration:
@@ -1499,7 +1502,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
&access.object().static_type(), &impl_scope));
if (access.object().value_category() != ValueCategory::Var) {
return CompilationError(e->source_loc())
<< "method " << access.member()
<< "method " << access.member_name()
<< " requires its receiver to be an lvalue";
}
}
@@ -1507,7 +1510,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
break;
}
default:
CARBON_FATAL() << "member " << access.member()
CARBON_FATAL() << "member " << access.member_name()
<< " is not a field or method";
break;
}
@@ -1515,21 +1518,27 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
} else {
return CompilationError(e->source_loc())
<< "class " << t_class.declaration().name()
<< " does not have a field named " << access.member();
<< " does not have a field named " << access.member_name();
}
}
case Value::Kind::TypeOfChoiceType: {
const ChoiceType& choice =
cast<TypeOfChoiceType>(object_type).choice_type();
std::optional<Nonnull<const Value*>> parameter_types =
choice.FindAlternative(access.member());
choice.FindAlternative(access.member_name());
if (!parameter_types.has_value()) {
return CompilationError(e->source_loc())
<< "choice " << choice.name()
<< " does not have an alternative named " << access.member();
<< " does not have an alternative named "
<< access.member_name();
}
access.set_static_type(arena_->New<FunctionType>(
*parameter_types, llvm::None, &choice, llvm::None, llvm::None));
Nonnull<const Value*> type = arena_->New<FunctionType>(
*parameter_types, llvm::None, &choice, llvm::None, llvm::None);
// TODO: Should there be a Declaration corresponding to each choice
// type alternative?
access.set_member(Member(
arena_->New<NamedValue>(NamedValue{access.member_name(), type})));
access.set_static_type(type);
access.set_value_category(ValueCategory::Let);
return Success();
}
@@ -1537,8 +1546,9 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
const NominalClassType& class_type =
cast<TypeOfClassType>(object_type).class_type();
if (std::optional<Nonnull<const Declaration*>> member = FindMember(
access.member(), class_type.declaration().members());
access.member_name(), class_type.declaration().members());
member.has_value()) {
access.set_member(Member(member.value()));
switch ((*member)->kind()) {
case DeclarationKind::FunctionDeclaration: {
const auto& func = cast<FunctionDeclaration>(*member);
@@ -1561,7 +1571,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
} else {
return CompilationError(access.source_loc())
<< class_type << " does not have a member named "
<< access.member();
<< access.member_name();
}
}
case Value::Kind::TypeOfInterfaceType:
@@ -1574,7 +1584,8 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
}
CARBON_ASSIGN_OR_RETURN(
ConstraintLookupResult result,
LookupInConstraint(e->source_loc(), type, access.member()));
LookupInConstraint(e->source_loc(), type, access.member_name()));
access.set_member(Member(result.member));
access.set_found_in_interface(result.interface);
access.set_static_type(
arena_->New<TypeOfMemberName>(Member(result.member)));
@@ -1591,13 +1602,14 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
CARBON_ASSIGN_OR_RETURN(
ConstraintLookupResult result,
LookupInConstraint(e->source_loc(), &typeof_var,
access.member()));
access.member_name()));
const Value& member_type = result.member->static_type();
BindingMap binding_map = result.interface->args();
binding_map[result.interface->declaration().self()] = &object_type;
Nonnull<const Value*> inst_member_type =
Substitute(binding_map, &member_type);
access.set_member(Member(result.member));
access.set_found_in_interface(result.interface);
access.set_static_type(inst_member_type);
@@ -1620,10 +1632,11 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
CARBON_ASSIGN_OR_RETURN(
ConstraintLookupResult result,
LookupInConstraint(e->source_loc(), &object_type,
access.member()));
access.member_name()));
CARBON_ASSIGN_OR_RETURN(Nonnull<Expression*> impl,
impl_scope.Resolve(result.interface, type,
e->source_loc(), *this));
access.set_member(Member(result.member));
access.set_impl(impl);
access.set_found_in_interface(result.interface);
@@ -3035,7 +3048,7 @@ auto TypeChecker::CheckImplIsComplete(Nonnull<const InterfaceType*> iface_type,
-> ErrorOr<Success> {
const auto& iface_decl = iface_type->declaration();
for (Nonnull<Declaration*> m : iface_decl.members()) {
std::optional<std::string> mem_name = GetName(*m);
std::optional<std::string_view> mem_name = GetName(*m);
CARBON_CHECK(mem_name.has_value()) << "unnamed interface member " << *m;
std::optional<Nonnull<const Declaration*>> mem =
+8 -24
View File
@@ -19,7 +19,7 @@ namespace Carbon {
using llvm::cast;
using llvm::dyn_cast;
auto StructValue::FindField(const std::string& name) const
auto StructValue::FindField(std::string_view name) const
-> std::optional<Nonnull<const Value*>> {
for (const NamedValue& element : elements_) {
if (element.name == name) {
@@ -33,7 +33,7 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
const FieldPath::Component& field,
SourceLocation source_loc, Nonnull<const Value*> me_value)
-> ErrorOr<Nonnull<const Value*>> {
const std::string& f = field.name();
std::string_view f = field.name();
if (field.witness().has_value()) {
Nonnull<const Witness*> witness = cast<Witness>(*field.witness());
@@ -185,7 +185,7 @@ static auto SetFieldImpl(
std::vector<Nonnull<const Value*>> elements =
cast<TupleValue>(*value).elements();
// TODO(geoffromer): update FieldPath to hold integers as well as strings.
int index = std::stoi((*path_begin).name());
int index = std::stoi(std::string((*path_begin).name()));
if (index < 0 || static_cast<size_t>(index) >= elements.size()) {
return RuntimeError(source_loc) << "index " << (*path_begin).name()
<< " out of range in " << *value;
@@ -770,9 +770,9 @@ auto ValueEqual(Nonnull<const Value*> v1, Nonnull<const Value*> v2) -> bool {
case Value::Kind::StringValue:
return cast<StringValue>(*v1).value() == cast<StringValue>(*v2).value();
case Value::Kind::ParameterizedEntityName: {
std::optional<std::string> name1 =
std::optional<std::string_view> name1 =
GetName(cast<ParameterizedEntityName>(v1)->declaration());
std::optional<std::string> name2 =
std::optional<std::string_view> name2 =
GetName(cast<ParameterizedEntityName>(v2)->declaration());
CARBON_CHECK(name1.has_value() && name2.has_value())
<< "parameterized name refers to unnamed declaration";
@@ -828,7 +828,7 @@ auto ChoiceType::FindAlternative(std::string_view name) const
return std::nullopt;
}
auto NominalClassType::FindFunction(const std::string& name) const
auto NominalClassType::FindFunction(std::string_view name) const
-> std::optional<Nonnull<const FunctionValue*>> {
for (const auto& member : declaration().members()) {
switch (member->kind()) {
@@ -846,11 +846,11 @@ auto NominalClassType::FindFunction(const std::string& name) const
return std::nullopt;
}
auto FindMember(const std::string& name,
auto FindMember(std::string_view name,
llvm::ArrayRef<Nonnull<Declaration*>> members)
-> std::optional<Nonnull<const Declaration*>> {
for (Nonnull<const Declaration*> member : members) {
if (std::optional<std::string> mem_name = GetName(*member);
if (std::optional<std::string_view> mem_name = GetName(*member);
mem_name.has_value()) {
if (*mem_name == name) {
return member;
@@ -860,22 +860,6 @@ auto FindMember(const std::string& name,
return std::nullopt;
}
auto Member::name() const -> std::string {
if (const Declaration* decl = member_.dyn_cast<const Declaration*>()) {
return GetName(*decl).value();
} else {
return member_.get<const NamedValue*>()->name;
}
}
auto Member::type() const -> const Value& {
if (const Declaration* decl = member_.dyn_cast<const Declaration*>()) {
return decl->static_type();
} else {
return *member_.get<const NamedValue*>()->value;
}
}
void ImplBinding::Print(llvm::raw_ostream& out) const {
out << "impl binding " << *type_var_ << " as " << *iface_;
}
+8 -42
View File
@@ -12,12 +12,12 @@
#include "common/ostream.h"
#include "explorer/ast/declaration.h"
#include "explorer/ast/member.h"
#include "explorer/ast/statement.h"
#include "explorer/common/nonnull.h"
#include "explorer/interpreter/address.h"
#include "explorer/interpreter/field_path.h"
#include "explorer/interpreter/stack.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Compiler.h"
namespace Carbon {
@@ -112,15 +112,6 @@ class Value {
const Kind kind_;
};
// A NamedValue represents a value with a name, such as a single struct field.
struct NamedValue {
// The field name.
std::string name;
// The field's value.
Nonnull<const Value*> value;
};
// An integer value.
class IntValue : public Value {
public:
@@ -281,7 +272,7 @@ class StructValue : public Value {
// Returns the value of the field named `name` in this struct, or
// nullopt if there is no such field.
auto FindField(const std::string& name) const
auto FindField(std::string_view name) const
-> std::optional<Nonnull<const Value*>>;
private:
@@ -309,7 +300,8 @@ class NominalClassValue : public Value {
// An alternative constructor value.
class AlternativeConstructorValue : public Value {
public:
AlternativeConstructorValue(std::string alt_name, std::string choice_name)
AlternativeConstructorValue(std::string_view alt_name,
std::string_view choice_name)
: Value(Kind::AlternativeConstructorValue),
alt_name_(std::move(alt_name)),
choice_name_(std::move(choice_name)) {}
@@ -329,7 +321,7 @@ class AlternativeConstructorValue : public Value {
// An alternative value.
class AlternativeValue : public Value {
public:
AlternativeValue(std::string alt_name, std::string choice_name,
AlternativeValue(std::string_view alt_name, std::string_view choice_name,
Nonnull<const Value*> argument)
: Value(Kind::AlternativeValue),
alt_name_(std::move(alt_name)),
@@ -595,7 +587,7 @@ class NominalClassType : public Value {
// Returns the value of the function named `name` in this class, or
// nullopt if there is no such function.
auto FindFunction(const std::string& name) const
auto FindFunction(std::string_view name) const
-> std::optional<Nonnull<const FunctionValue*>>;
private:
@@ -605,7 +597,7 @@ class NominalClassType : public Value {
};
// Return the declaration of the member with the given name.
auto FindMember(const std::string& name,
auto FindMember(std::string_view name,
llvm::ArrayRef<Nonnull<Declaration*>> members)
-> std::optional<Nonnull<const Declaration*>>;
@@ -855,32 +847,6 @@ class ParameterizedEntityName : public Value {
Nonnull<const TuplePattern*> params_;
};
// A member of a type.
//
// This is either a declared member of a class, interface, or similar, or a
// member of a struct with no declaration.
class Member {
public:
explicit Member(const Declaration* declaration) : member_(declaration) {}
explicit Member(const NamedValue* struct_member) : member_(struct_member) {}
// The name of the member.
auto name() const -> std::string;
// The declared type of the member, which might include type variables.
auto type() const -> const Value&;
// A declaration of the member, if any exists.
auto declaration() const -> std::optional<Nonnull<const Declaration*>> {
if (const Declaration* decl = member_.dyn_cast<const Declaration*>()) {
return decl;
}
return std::nullopt;
}
private:
llvm::PointerUnion<Nonnull<const Declaration*>, Nonnull<const NamedValue*>>
member_;
};
// The name of a member of a class or interface.
//
// These values are used to represent the second operand of a compound member
@@ -914,7 +880,7 @@ class MemberName : public Value {
// The member.
auto member() const -> Member { return member_; }
// The name of the member.
auto name() const -> std::string { return member().name(); }
auto name() const -> std::string_view { return member().name(); }
private:
std::optional<Nonnull<const Value*>> base_type_;