clone_context.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. #include "explorer/ast/clone_context.h"
  5. #include "explorer/ast/ast_kinds.h"
  6. #include "explorer/ast/ast_node.h"
  7. #include "explorer/ast/value_transform.h"
  8. namespace Carbon {
  9. auto CloneContext::CloneBase(Nonnull<const AstNode*> node)
  10. -> Nonnull<AstNode*> {
  11. auto [it, added] = nodes_.insert({node, nullptr});
  12. CARBON_CHECK(added) << (it->second
  13. ? "node was cloned multiple times: "
  14. : "node was remapped before it was cloned: ")
  15. << *node;
  16. // TODO: Generate a Visit member on AstNode and use it here to avoid these
  17. // macros.
  18. switch (node->kind()) {
  19. #define IGNORE(C)
  20. #define CLONE_CASE(C) \
  21. case AstNodeKind::C: \
  22. arena_->New<C>(Arena::WriteAddressTo{&it->second}, *this, \
  23. static_cast<const C&>(*node)); \
  24. break;
  25. CARBON_AstNode_KINDS(IGNORE, CLONE_CASE)
  26. #undef CLONE_CASE
  27. #undef IGNORE
  28. }
  29. // Cloning may have invalidated our iterator; redo lookup.
  30. auto* result = nodes_[node];
  31. CARBON_CHECK(result) << "CloneImpl didn't set the result pointer";
  32. return result;
  33. }
  34. class CloneContext::CloneValueTransform
  35. : public ValueTransform<CloneValueTransform, NoOpUnwrapper> {
  36. public:
  37. CloneValueTransform(Nonnull<CloneContext*> context, Nonnull<Arena*> arena)
  38. : ValueTransform(arena), context_(context) {}
  39. using ValueTransform::operator();
  40. // Transforming a pointer to an AstNode should remap the node. Values do not
  41. // own the nodes they point to, apart from the exceptions handled below.
  42. template <typename NodeT>
  43. auto operator()(Nonnull<const NodeT*> node, int /*unused*/ = 0)
  44. -> std::enable_if_t<std::is_base_of_v<AstNode, NodeT>,
  45. Nonnull<const NodeT*>> {
  46. return context_->Remap(node);
  47. }
  48. // Transforming a value node view should clone it. The value node view does
  49. // not itself own the node it points to, so this is a shallow clone.
  50. auto operator()(ValueNodeView value_node) -> ValueNodeView {
  51. return context_->Clone(value_node);
  52. }
  53. // A FunctionType may or may not own its bindings.
  54. auto operator()(Nonnull<const FunctionType*> fn_type)
  55. -> Nonnull<const FunctionType*> {
  56. for (const auto* binding : fn_type->deduced_bindings()) {
  57. context_->MaybeCloneBase(binding);
  58. }
  59. for (auto [index, binding] : fn_type->generic_parameters()) {
  60. context_->MaybeCloneBase(binding);
  61. }
  62. return ValueTransform::operator()(fn_type);
  63. }
  64. // A ConstraintType owns its self binding, so we need to clone it.
  65. auto operator()(Nonnull<const ConstraintType*> constraint)
  66. -> Nonnull<const Value*> {
  67. context_->Clone(constraint->self_binding());
  68. return ValueTransform::operator()(constraint);
  69. }
  70. private:
  71. Nonnull<CloneContext*> context_;
  72. };
  73. auto CloneContext::CloneBase(Nonnull<const Value*> value) -> Nonnull<Value*> {
  74. return const_cast<Value*>(CloneValueTransform(this, arena_).Transform(value));
  75. }
  76. auto CloneContext::CloneBase(Nonnull<const Element*> elem)
  77. -> Nonnull<Element*> {
  78. return const_cast<Element*>(
  79. CloneValueTransform(this, arena_).Transform(elem));
  80. }
  81. void CloneContext::MaybeCloneBase(Nonnull<const AstNode*> node) {
  82. auto it = nodes_.find(node);
  83. if (it == nodes_.end()) {
  84. Clone(node);
  85. }
  86. }
  87. } // namespace Carbon