field_path.h 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef EXECUTABLE_SEMANTICS_INTERPRETER_FIELD_PATH_H_
  5. #define EXECUTABLE_SEMANTICS_INTERPRETER_FIELD_PATH_H_
  6. #include <string>
  7. #include <vector>
  8. #include "common/ostream.h"
  9. #include "executable_semantics/ast/static_scope.h"
  10. #include "llvm/Support/Compiler.h"
  11. namespace Carbon {
  12. class Witness;
  13. // Given some initial Value, a FieldPath identifies a sub-Value within it,
  14. // in much the same way that a file path identifies a file within some
  15. // directory. FieldPaths are relative rather than absolute: the initial
  16. // Value is specified by the context in which the FieldPath is used, not
  17. // by the FieldPath itself.
  18. //
  19. // A FieldPath consists of a series of steps, which specify how to
  20. // incrementally navigate from a Value to one of its fields. Currently
  21. // there is only one kind of step, a string specifying a child field by name,
  22. // but that may change as Carbon develops. Note that an empty FieldPath
  23. // refers to the initial Value itself.
  24. class FieldPath {
  25. public:
  26. // Constructs an empty FieldPath.
  27. FieldPath() = default;
  28. // A single component of the FieldPath, which is typically the name
  29. // of a field. However, inside a generic, when there is a field
  30. // access on something of a generic type, e.g., `T`, then we also
  31. // need `witness`, a pointer to the witness table containing that field.
  32. class Component {
  33. public:
  34. explicit Component(std::string name) : name_(std::move(name)) {}
  35. Component(std::string name, std::optional<Nonnull<const Witness*>> witness)
  36. : name_(std::move(name)), witness_(witness) {}
  37. auto name() const -> const std::string& { return name_; }
  38. auto witness() const -> std::optional<Nonnull<const Witness*>> {
  39. return witness_;
  40. }
  41. void Print(llvm::raw_ostream& out) const { out << name_; }
  42. private:
  43. std::string name_;
  44. std::optional<Nonnull<const Witness*>> witness_;
  45. };
  46. // Constructs a FieldPath consisting of a single step.
  47. explicit FieldPath(std::string name)
  48. : components_({Component(std::move(name))}) {}
  49. explicit FieldPath(const Component& f) : components_({f}) {}
  50. FieldPath(const FieldPath&) = default;
  51. FieldPath(FieldPath&&) = default;
  52. auto operator=(const FieldPath&) -> FieldPath& = default;
  53. auto operator=(FieldPath&&) -> FieldPath& = default;
  54. // Returns whether *this is empty.
  55. auto IsEmpty() const -> bool { return components_.empty(); }
  56. // Appends `name` to the end of *this.
  57. auto Append(std::string name) -> void {
  58. components_.push_back(Component(std::move(name)));
  59. }
  60. void Print(llvm::raw_ostream& out) const {
  61. for (const Component& component : components_) {
  62. out << "." << component;
  63. }
  64. }
  65. LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
  66. private:
  67. // The representation of FieldPath describes how to locate a Value within
  68. // another Value, so its implementation details are tied to the implementation
  69. // details of Value.
  70. friend class Value;
  71. std::vector<Component> components_;
  72. };
  73. } // namespace Carbon
  74. #endif // EXECUTABLE_SEMANTICS_INTERPRETER_FIELD_PATH_H_