|
|
@@ -14,6 +14,7 @@
|
|
|
#include "explorer/common/arena.h"
|
|
|
#include "explorer/common/error_builders.h"
|
|
|
#include "explorer/interpreter/action.h"
|
|
|
+#include "explorer/interpreter/field_path.h"
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
@@ -48,12 +49,32 @@ static auto FindClassField(Nonnull<const NominalClassValue*> object,
|
|
|
return std::nullopt;
|
|
|
}
|
|
|
|
|
|
-static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
|
|
|
- const FieldPath::Component& field,
|
|
|
- SourceLocation source_loc, Nonnull<const Value*> me_value)
|
|
|
+static auto GetPositionalMember(Nonnull<const Value*> v,
|
|
|
+ const FieldPath::Component& field,
|
|
|
+ SourceLocation source_loc)
|
|
|
-> ErrorOr<Nonnull<const Value*>> {
|
|
|
- std::string_view f = field.name();
|
|
|
+ switch (v->kind()) {
|
|
|
+ case Value::Kind::TupleValue: {
|
|
|
+ const auto& tuple = cast<TupleValue>(*v);
|
|
|
+ const auto index = field.member().index();
|
|
|
+ if (index < 0 || index >= static_cast<int>(tuple.elements().size())) {
|
|
|
+ return ProgramError(source_loc)
|
|
|
+ << "index " << index << " out of range for " << *v;
|
|
|
+ }
|
|
|
+ return tuple.elements()[index];
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ return ProgramError(source_loc)
|
|
|
+ << "Invalid positional argument for value " << *v;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
+static auto GetNamedMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
|
|
|
+ const FieldPath::Component& field,
|
|
|
+ SourceLocation source_loc,
|
|
|
+ Nonnull<const Value*> me_value)
|
|
|
+ -> ErrorOr<Nonnull<const Value*>> {
|
|
|
+ const auto f = field.member().name();
|
|
|
if (field.witness().has_value()) {
|
|
|
const auto* witness = cast<Witness>(*field.witness());
|
|
|
|
|
|
@@ -152,6 +173,15 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+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*>> {
|
|
|
+ return field.member().HasPosition()
|
|
|
+ ? GetPositionalMember(v, field, source_loc)
|
|
|
+ : GetNamedMember(arena, v, field, source_loc, me_value);
|
|
|
+}
|
|
|
+
|
|
|
auto Value::GetMember(Nonnull<Arena*> arena, const FieldPath& path,
|
|
|
SourceLocation source_loc,
|
|
|
Nonnull<const Value*> me_value) const
|
|
|
@@ -178,11 +208,11 @@ static auto SetFieldImpl(
|
|
|
std::vector<NamedValue> elements = cast<StructValue>(*value).elements();
|
|
|
auto it =
|
|
|
llvm::find_if(elements, [path_begin](const NamedValue& element) {
|
|
|
- return element.name == (*path_begin).name();
|
|
|
+ return (*path_begin).IsNamed(element.name);
|
|
|
});
|
|
|
if (it == elements.end()) {
|
|
|
return ProgramError(source_loc)
|
|
|
- << "field " << (*path_begin).name() << " not in " << *value;
|
|
|
+ << "field " << *path_begin << " not in " << *value;
|
|
|
}
|
|
|
CARBON_ASSIGN_OR_RETURN(
|
|
|
it->value, SetFieldImpl(arena, it->value, path_begin + 1, path_end,
|
|
|
@@ -207,17 +237,16 @@ static auto SetFieldImpl(
|
|
|
}
|
|
|
// Failed to match, show full object content
|
|
|
return ProgramError(source_loc)
|
|
|
- << "field " << (*path_begin).name() << " not in " << *value;
|
|
|
+ << "field " << *path_begin << " not in " << *value;
|
|
|
}
|
|
|
case Value::Kind::TupleType:
|
|
|
case Value::Kind::TupleValue: {
|
|
|
std::vector<Nonnull<const Value*>> elements =
|
|
|
cast<TupleValueBase>(*value).elements();
|
|
|
- // TODO(geoffromer): update FieldPath to hold integers as well as strings.
|
|
|
- int index = std::stoi(std::string((*path_begin).name()));
|
|
|
- if (index < 0 || static_cast<size_t>(index) >= elements.size()) {
|
|
|
- return ProgramError(source_loc) << "index " << (*path_begin).name()
|
|
|
- << " out of range in " << *value;
|
|
|
+ const auto index = (*path_begin).member().index();
|
|
|
+ if (index < 0 || index >= static_cast<int>(elements.size())) {
|
|
|
+ return ProgramError(source_loc)
|
|
|
+ << "index " << index << " out of range in " << *value;
|
|
|
}
|
|
|
CARBON_ASSIGN_OR_RETURN(
|
|
|
elements[index], SetFieldImpl(arena, elements[index], path_begin + 1,
|
|
|
@@ -541,7 +570,7 @@ void Value::Print(llvm::raw_ostream& out) const {
|
|
|
if (member_name.interface().has_value()) {
|
|
|
out << *member_name.interface().value();
|
|
|
}
|
|
|
- out << "." << member_name.name();
|
|
|
+ out << "." << member_name;
|
|
|
if (member_name.base_type().has_value() &&
|
|
|
member_name.interface().has_value()) {
|
|
|
out << ")";
|
|
|
@@ -587,7 +616,7 @@ void Value::Print(llvm::raw_ostream& out) const {
|
|
|
<< cast<TypeOfParameterizedEntityName>(*this).name();
|
|
|
break;
|
|
|
case Value::Kind::TypeOfMemberName: {
|
|
|
- out << "member name " << cast<TypeOfMemberName>(*this).member().name();
|
|
|
+ out << "member name " << cast<TypeOfMemberName>(*this).member();
|
|
|
break;
|
|
|
}
|
|
|
case Value::Kind::StaticArrayType: {
|