node_id_traversal.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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, llvm::raw_ostream* vlog_stream);
  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. // Re-enter a nested deferred definition scope.
  61. auto PerformTask(
  62. DeferredDefinitionWorklist::EnterNestedDeferredDefinitionScope&& enter)
  63. -> void;
  64. // Leave a nested deferred definition scope.
  65. auto PerformTask(
  66. DeferredDefinitionWorklist::LeaveNestedDeferredDefinitionScope&& leave)
  67. -> void;
  68. // Resume checking a deferred definition.
  69. auto PerformTask(
  70. DeferredDefinitionWorklist::CheckSkippedDefinition&& parse_definition)
  71. -> void;
  72. Context* context_;
  73. NextDeferredDefinitionCache next_deferred_definition_;
  74. DeferredDefinitionWorklist worklist_;
  75. llvm::SmallVector<Chunk> chunks_;
  76. };
  77. } // namespace Carbon::Check
  78. #endif // CARBON_TOOLCHAIN_CHECK_NODE_ID_TRAVERSAL_H_