action_stack.h 4.1 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. #ifndef EXECUTABLE_SEMANTICS_INTERPRETER_ACTION_STACK_H_
  5. #define EXECUTABLE_SEMANTICS_INTERPRETER_ACTION_STACK_H_
  6. #include <memory>
  7. #include <optional>
  8. #include "common/ostream.h"
  9. #include "executable_semantics/ast/statement.h"
  10. #include "executable_semantics/interpreter/action.h"
  11. #include "executable_semantics/interpreter/value.h"
  12. namespace Carbon {
  13. // The stack of Actions currently being executed by the interpreter.
  14. class ActionStack {
  15. public:
  16. // Constructs an empty ActionStack
  17. ActionStack() = default;
  18. void Print(llvm::raw_ostream& out) const;
  19. LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
  20. // Starts execution with `action` at the top of the stack, in the given scope.
  21. // `action` must be an `ExpressionAction` or `PatternAction`.
  22. void Start(std::unique_ptr<Action> action, Scope scope);
  23. // True if the stack is empty.
  24. auto IsEmpty() const -> bool { return todo_.IsEmpty(); }
  25. // The Action currently at the top of the stack. This will never be a
  26. // ScopeAction.
  27. auto CurrentAction() -> Action& { return *todo_.Top(); }
  28. // The scope that should be used to resolve name lookups in the current
  29. // action.
  30. auto CurrentScope() const -> Scope&;
  31. // The result produced by the `action` argument of the most recent
  32. // `Start` call. *this must be empty, signifying that the action has been
  33. // fully executed.
  34. auto result() const -> Nonnull<const Value*> { return *result_; }
  35. // The following methods, called "transition methods", update the state of
  36. // the ActionStack and/or the current Action to reflect the effects of
  37. // executing a step of that Action. Execution of an Action step should always
  38. // invoke exactly one transition method, as the very last operation. This is a
  39. // matter of safety as well as convention: most transition methods modify the
  40. // state of the current action, and some of them destroy it. To help enforce
  41. // this requirement, we have a convention of calling these methods as part of
  42. // return statements, e.g. `return todo_.FinishAction()`, even though they
  43. // return void.
  44. // Finishes execution of the current Action. If `result` is specified, it
  45. // represents the result of that Action.
  46. void FinishAction();
  47. void FinishAction(Nonnull<const Value*> result);
  48. // Advances the current action one step, and push `child` onto the stack.
  49. // If `scope` is specified, `child` will be executed in that scope.
  50. void Spawn(std::unique_ptr<Action> child);
  51. void Spawn(std::unique_ptr<Action> child, Scope scope);
  52. // Advances the current action one step.
  53. void RunAgain();
  54. // Unwinds Actions from the stack until the StatementAction associated with
  55. // `ast_node` is at the top of the stack.
  56. void UnwindTo(Nonnull<const Statement*> ast_node);
  57. // Unwinds Actions from the stack until the StatementAction associated with
  58. // `ast_node` has been removed from the stack. If `result` is specified,
  59. // it represents the result of that Action (StatementActions normally cannot
  60. // produce results, but the body of a function can).
  61. void UnwindPast(Nonnull<const Statement*> ast_node);
  62. void UnwindPast(Nonnull<const Statement*> ast_node,
  63. Nonnull<const Value*> result);
  64. // Resumes execution of a suspended continuation.
  65. void Resume(Nonnull<const ContinuationValue*> continuation);
  66. // Suspends execution of the currently-executing continuation.
  67. void Suspend();
  68. private:
  69. // Pop any ScopeActions from the top of the stack, propagating results as
  70. // needed, to restore the invariant that todo_.Top() is not a ScopeAction.
  71. void PopScopes();
  72. // Set `result` as the result of the Action most recently removed from the
  73. // stack.
  74. void SetResult(Nonnull<const Value*> result);
  75. // TODO: consider defining a non-nullable unique_ptr-like type to use here.
  76. Stack<std::unique_ptr<Action>> todo_;
  77. std::optional<Nonnull<const Value*>> result_;
  78. };
  79. } // namespace Carbon
  80. #endif // EXECUTABLE_SEMANTICS_INTERPRETER_ACTION_STACK_H_