node_id_traversal.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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. explicit NodeIdTraversal(Context& context, llvm::raw_ostream* vlog_stream);
  17. // Finds the next `NodeId` to type-check. Returns nullopt if the traversal is
  18. // complete.
  19. auto Next() -> std::optional<Parse::NodeId>;
  20. // Performs any processing necessary after we type-check a node.
  21. auto Handle(Parse::NodeKind parse_kind) -> void;
  22. private:
  23. // State used to track the next deferred function definition that we will
  24. // encounter and need to reorder.
  25. class NextDeferredDefinitionCache {
  26. public:
  27. explicit NextDeferredDefinitionCache(const Parse::Tree* tree);
  28. // Set the specified deferred definition index as being the next one that
  29. // will be encountered.
  30. auto SkipTo(Parse::DeferredDefinitionIndex next_index) -> void;
  31. // Returns the index of the next deferred definition to be encountered.
  32. auto index() const -> Parse::DeferredDefinitionIndex { return index_; }
  33. // Returns the ID of the start node of the next deferred definition.
  34. auto start_id() const -> Parse::NodeId { return start_id_; }
  35. private:
  36. const Parse::Tree* tree_;
  37. Parse::DeferredDefinitionIndex index_ =
  38. Parse::DeferredDefinitionIndex::None;
  39. Parse::NodeId start_id_ = Parse::NodeId::None;
  40. };
  41. // A chunk of the parse tree that we need to type-check.
  42. struct Chunk {
  43. Parse::Tree::PostorderIterator it;
  44. Parse::Tree::PostorderIterator end;
  45. // The next definition that will be encountered after this chunk completes.
  46. Parse::DeferredDefinitionIndex next_definition;
  47. // Whether we are currently checking deferred definitions, rather than the
  48. // tokens of this chunk. If so, we'll pull tasks off `worklist` and execute
  49. // them until we're done with this batch of deferred definitions. Otherwise,
  50. // we'll pull node IDs from `*it` until it reaches `end`.
  51. bool checking_deferred_definitions = false;
  52. };
  53. // Re-enter a nested deferred definition scope.
  54. auto PerformTask(
  55. DeferredDefinitionWorklist::EnterDeferredDefinitionScope&& enter) -> void;
  56. // Leave a nested or top-level deferred definition scope.
  57. auto PerformTask(
  58. DeferredDefinitionWorklist::LeaveDeferredDefinitionScope&& leave) -> void;
  59. // Resume checking a deferred definition.
  60. auto PerformTask(
  61. DeferredDefinitionWorklist::CheckSkippedDefinition&& parse_definition)
  62. -> void;
  63. Context& context_;
  64. NextDeferredDefinitionCache next_deferred_definition_;
  65. DeferredDefinitionWorklist worklist_;
  66. llvm::SmallVector<Chunk> chunks_;
  67. };
  68. } // namespace Carbon::Check
  69. #endif // CARBON_TOOLCHAIN_CHECK_NODE_ID_TRAVERSAL_H_