node_id_traversal.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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 CARBON_TOOLCHAIN_CHECK_NODE_ID_TRAVERSAL_H_
  5. #define CARBON_TOOLCHAIN_CHECK_NODE_ID_TRAVERSAL_H_
  6. #include "common/ostream.h"
  7. #include "llvm/ADT/SmallVector.h"
  8. #include "toolchain/check/context.h"
  9. #include "toolchain/check/deferred_definition_worklist.h"
  10. #include "toolchain/parse/tree.h"
  11. namespace Carbon::Check {
  12. // A traversal of the node IDs in the parse tree, in the order in which we need
  13. // to check them.
  14. class NodeIdTraversal {
  15. public:
  16. // `context` must not be null.
  17. explicit NodeIdTraversal(Context* context);
  18. // Finds the next `NodeId` to type-check. Returns nullopt if the traversal is
  19. // complete.
  20. auto Next() -> std::optional<Parse::NodeId>;
  21. // Performs any processing necessary after we type-check a node.
  22. auto Handle(Parse::NodeKind parse_kind) -> void;
  23. private:
  24. // State used to track the next deferred function definition that we will
  25. // encounter and need to reorder.
  26. class NextDeferredDefinitionCache {
  27. public:
  28. explicit NextDeferredDefinitionCache(const Parse::Tree* tree);
  29. // Set the specified deferred definition index as being the next one that
  30. // will be encountered.
  31. auto SkipTo(Parse::DeferredDefinitionIndex next_index) -> void;
  32. // Returns the index of the next deferred definition to be encountered.
  33. auto index() const -> Parse::DeferredDefinitionIndex { return index_; }
  34. // Returns the ID of the start node of the next deferred definition.
  35. auto start_id() const -> Parse::NodeId { return start_id_; }
  36. private:
  37. const Parse::Tree* tree_;
  38. Parse::DeferredDefinitionIndex index_ =
  39. Parse::DeferredDefinitionIndex::None;
  40. Parse::NodeId start_id_ = Parse::NodeId::None;
  41. };
  42. // A chunk of the parse tree that we need to type-check.
  43. struct Chunk {
  44. Parse::Tree::PostorderIterator it;
  45. Parse::Tree::PostorderIterator end;
  46. // The next definition that will be encountered after this chunk completes.
  47. Parse::DeferredDefinitionIndex next_definition;
  48. // Whether we are currently checking deferred definitions, rather than the
  49. // tokens of this chunk. If so, we'll pull tasks off `worklist` and execute
  50. // them until we're done with this batch of deferred definitions. Otherwise,
  51. // we'll pull node IDs from `*it` until it reaches `end`.
  52. bool checking_deferred_definitions = false;
  53. // If we're checking deferred definitions, the index of the first task to
  54. // execute from `worklist`.
  55. size_t first_worklist_index;
  56. // If we're checking deferred definitions, the index of the next task to
  57. // execute from `worklist`.
  58. size_t next_worklist_index;
  59. };
  60. auto worklist() -> DeferredDefinitionWorklist& { return *worklist_; }
  61. // Re-enter a nested deferred definition scope.
  62. auto PerformTask(
  63. DeferredDefinitionWorklist::EnterNestedDeferredDefinitionScope&& enter)
  64. -> void;
  65. // Leave a nested deferred definition scope.
  66. auto PerformTask(
  67. DeferredDefinitionWorklist::LeaveNestedDeferredDefinitionScope&& leave)
  68. -> void;
  69. // Resume checking a deferred definition.
  70. auto PerformTask(
  71. DeferredDefinitionWorklist::CheckSkippedDefinition&& parse_definition)
  72. -> void;
  73. // Define a thunk.
  74. auto PerformTask(DeferredDefinitionWorklist::DefineThunk&& define_thunk)
  75. -> void;
  76. Context* context_;
  77. NextDeferredDefinitionCache next_deferred_definition_;
  78. DeferredDefinitionWorklist* worklist_;
  79. llvm::SmallVector<Chunk> chunks_;
  80. };
  81. } // namespace Carbon::Check
  82. #endif // CARBON_TOOLCHAIN_CHECK_NODE_ID_TRAVERSAL_H_