action_stack.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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/interpreter/action_stack.h"
  5. #include "explorer/interpreter/action.h"
  6. #include "llvm/ADT/StringExtras.h"
  7. #include "llvm/Support/Casting.h"
  8. #include "llvm/Support/Error.h"
  9. namespace Carbon {
  10. void ActionStack::Print(llvm::raw_ostream& out) const {
  11. llvm::ListSeparator sep(" ## ");
  12. for (const std::unique_ptr<Action>& action : todo_) {
  13. out << sep << *action;
  14. }
  15. }
  16. // OBSOLETE
  17. void ActionStack::PrintScopes(llvm::raw_ostream& out) const {
  18. llvm::ListSeparator sep(" ## ");
  19. for (const std::unique_ptr<Action>& action : todo_) {
  20. if (action->scope().has_value()) {
  21. out << sep << *action->scope();
  22. }
  23. }
  24. if (globals_.has_value()) {
  25. out << sep << *globals_;
  26. }
  27. // TODO: should we print constants as well?
  28. }
  29. void ActionStack::Start(std::unique_ptr<Action> action) {
  30. result_ = std::nullopt;
  31. CARBON_CHECK(todo_.IsEmpty());
  32. todo_.Push(std::move(action));
  33. }
  34. void ActionStack::Initialize(ValueNodeView value_node,
  35. Nonnull<const Value*> value) {
  36. for (const std::unique_ptr<Action>& action : todo_) {
  37. if (action->scope().has_value()) {
  38. action->scope()->Initialize(value_node, value);
  39. return;
  40. }
  41. }
  42. globals_->Initialize(value_node, value);
  43. }
  44. auto ActionStack::ValueOfNode(ValueNodeView value_node,
  45. SourceLocation source_loc) const
  46. -> ErrorOr<Nonnull<const Value*>> {
  47. std::optional<const Value*> constant_value = value_node.constant_value();
  48. if (constant_value.has_value()) {
  49. return *constant_value;
  50. }
  51. for (const std::unique_ptr<Action>& action : todo_) {
  52. // TODO: have static name resolution identify the scope of value_node
  53. // as an AstNode, and then perform lookup _only_ on the Action associated
  54. // with that node. This will help keep unwanted dynamic-scoping behavior
  55. // from sneaking in.
  56. if (action->scope().has_value()) {
  57. std::optional<Nonnull<const Value*>> result =
  58. action->scope()->Get(value_node);
  59. if (result.has_value()) {
  60. return *result;
  61. }
  62. }
  63. }
  64. if (globals_.has_value()) {
  65. std::optional<Nonnull<const Value*>> result = globals_->Get(value_node);
  66. if (result.has_value()) {
  67. return *result;
  68. }
  69. }
  70. // We don't know the value of this node, but at compile time we may still be
  71. // able to form a symbolic value for it. For example, in
  72. //
  73. // fn F[T:! Type](x: T) {}
  74. //
  75. // ... we don't know the value of `T` but can still symbolically evaluate it
  76. // to a `VariableType`. At runtime we need actual values.
  77. if (phase_ == Phase::CompileTime) {
  78. std::optional<const Value*> symbolic_identity =
  79. value_node.symbolic_identity();
  80. if (symbolic_identity.has_value()) {
  81. return *symbolic_identity;
  82. }
  83. }
  84. // TODO: Move these errors to compile time and explain them more clearly.
  85. return RuntimeError(source_loc)
  86. << "could not find `" << value_node.base() << "`";
  87. }
  88. void ActionStack::MergeScope(RuntimeScope scope) {
  89. for (const std::unique_ptr<Action>& action : todo_) {
  90. if (action->scope().has_value()) {
  91. action->scope()->Merge(std::move(scope));
  92. return;
  93. }
  94. }
  95. if (globals_.has_value()) {
  96. globals_->Merge(std::move(scope));
  97. return;
  98. }
  99. CARBON_FATAL() << "No current scope";
  100. }
  101. void ActionStack::InitializeFragment(ContinuationValue::StackFragment& fragment,
  102. Nonnull<const Statement*> body) {
  103. std::vector<Nonnull<const RuntimeScope*>> scopes;
  104. for (const std::unique_ptr<Action>& action : todo_) {
  105. if (action->scope().has_value()) {
  106. scopes.push_back(&*action->scope());
  107. }
  108. }
  109. // We don't capture globals_ or constants_ because they're global.
  110. std::vector<std::unique_ptr<Action>> reversed_todo;
  111. reversed_todo.push_back(std::make_unique<StatementAction>(body));
  112. reversed_todo.push_back(
  113. std::make_unique<ScopeAction>(RuntimeScope::Capture(scopes)));
  114. fragment.StoreReversed(std::move(reversed_todo));
  115. }
  116. auto ActionStack::FinishAction() -> ErrorOr<Success> {
  117. std::unique_ptr<Action> act = todo_.Pop();
  118. switch (act->kind()) {
  119. case Action::Kind::ExpressionAction:
  120. case Action::Kind::LValAction:
  121. case Action::Kind::PatternAction:
  122. case Action::Kind::ScopeAction:
  123. CARBON_FATAL() << "ScopeAction at top of stack";
  124. case Action::Kind::StatementAction:
  125. case Action::Kind::DeclarationAction:
  126. case Action::Kind::RecursiveAction:
  127. PopScopes();
  128. }
  129. return Success();
  130. }
  131. auto ActionStack::FinishAction(Nonnull<const Value*> result)
  132. -> ErrorOr<Success> {
  133. std::unique_ptr<Action> act = todo_.Pop();
  134. switch (act->kind()) {
  135. case Action::Kind::StatementAction:
  136. case Action::Kind::DeclarationAction:
  137. case Action::Kind::RecursiveAction:
  138. CARBON_FATAL() << "This kind of Action cannot produce results: " << *act;
  139. case Action::Kind::ScopeAction:
  140. CARBON_FATAL() << "ScopeAction at top of stack";
  141. case Action::Kind::ExpressionAction:
  142. case Action::Kind::LValAction:
  143. case Action::Kind::PatternAction:
  144. PopScopes();
  145. SetResult(result);
  146. }
  147. return Success();
  148. }
  149. auto ActionStack::Spawn(std::unique_ptr<Action> child) -> ErrorOr<Success> {
  150. Action& action = *todo_.Top();
  151. action.set_pos(action.pos() + 1);
  152. todo_.Push(std::move(child));
  153. return Success();
  154. }
  155. auto ActionStack::Spawn(std::unique_ptr<Action> child, RuntimeScope scope)
  156. -> ErrorOr<Success> {
  157. Action& action = *todo_.Top();
  158. action.set_pos(action.pos() + 1);
  159. todo_.Push(std::make_unique<ScopeAction>(std::move(scope)));
  160. todo_.Push(std::move(child));
  161. return Success();
  162. }
  163. auto ActionStack::ReplaceWith(std::unique_ptr<Action> replacement)
  164. -> ErrorOr<Success> {
  165. std::unique_ptr<Action> old = todo_.Pop();
  166. CARBON_CHECK(replacement->kind() == old->kind())
  167. << "ReplaceWith can't change action kind";
  168. todo_.Push(std::move(replacement));
  169. return Success();
  170. }
  171. auto ActionStack::RunAgain() -> ErrorOr<Success> {
  172. Action& action = *todo_.Top();
  173. action.set_pos(action.pos() + 1);
  174. return Success();
  175. }
  176. auto ActionStack::UnwindTo(Nonnull<const Statement*> ast_node)
  177. -> ErrorOr<Success> {
  178. while (true) {
  179. if (const auto* statement_action =
  180. llvm::dyn_cast<StatementAction>(todo_.Top().get());
  181. statement_action != nullptr &&
  182. &statement_action->statement() == ast_node) {
  183. break;
  184. }
  185. todo_.Pop();
  186. }
  187. return Success();
  188. }
  189. auto ActionStack::UnwindPast(Nonnull<const Statement*> ast_node)
  190. -> ErrorOr<Success> {
  191. CARBON_RETURN_IF_ERROR(UnwindTo(ast_node));
  192. todo_.Pop();
  193. PopScopes();
  194. return Success();
  195. }
  196. auto ActionStack::UnwindPast(Nonnull<const Statement*> ast_node,
  197. Nonnull<const Value*> result) -> ErrorOr<Success> {
  198. CARBON_RETURN_IF_ERROR(UnwindPast(ast_node));
  199. SetResult(result);
  200. return Success();
  201. }
  202. auto ActionStack::Resume(Nonnull<const ContinuationValue*> continuation)
  203. -> ErrorOr<Success> {
  204. Action& action = *todo_.Top();
  205. action.set_pos(action.pos() + 1);
  206. continuation->stack().RestoreTo(todo_);
  207. return Success();
  208. }
  209. static auto IsRunAction(const Action& action) -> bool {
  210. const auto* statement = llvm::dyn_cast<StatementAction>(&action);
  211. return statement != nullptr && llvm::isa<Run>(statement->statement());
  212. }
  213. auto ActionStack::Suspend() -> ErrorOr<Success> {
  214. // Pause the current continuation
  215. todo_.Pop();
  216. std::vector<std::unique_ptr<Action>> paused;
  217. while (!IsRunAction(*todo_.Top())) {
  218. paused.push_back(todo_.Pop());
  219. }
  220. const auto& continuation =
  221. llvm::cast<const ContinuationValue>(*todo_.Top()->results()[0]);
  222. // Update the continuation with the paused stack.
  223. continuation.stack().StoreReversed(std::move(paused));
  224. return Success();
  225. }
  226. void ActionStack::PopScopes() {
  227. while (!todo_.IsEmpty() && llvm::isa<ScopeAction>(*todo_.Top())) {
  228. todo_.Pop();
  229. }
  230. }
  231. void ActionStack::SetResult(Nonnull<const Value*> result) {
  232. if (todo_.IsEmpty()) {
  233. result_ = result;
  234. } else {
  235. todo_.Top()->AddResult(result);
  236. }
  237. }
  238. } // namespace Carbon