mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-29 22:02:42 +01:00
Merge UnwindTo and UnwindPast logic (#926)
Also shifts the DeallocateScope concept into UnwindTodoTop since that's how it's used.
This commit is contained in:
@@ -181,14 +181,18 @@ void Interpreter::InitGlobals(llvm::ArrayRef<Nonnull<Declaration*>> fs) {
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::DeallocateScope(Scope& scope) {
|
||||
CHECK(!scope.deallocated);
|
||||
for (const auto& l : scope.locals) {
|
||||
std::optional<AllocationId> a = scope.values.Get(l);
|
||||
CHECK(a);
|
||||
heap_.Deallocate(*a);
|
||||
auto Interpreter::UnwindTodoTop() -> Nonnull<Action*> {
|
||||
Nonnull<Action*> act = todo_.Pop();
|
||||
if (act->scope().has_value()) {
|
||||
CHECK(!act->scope()->deallocated);
|
||||
for (const auto& l : act->scope()->locals) {
|
||||
std::optional<AllocationId> a = act->scope()->values.Get(l);
|
||||
CHECK(a);
|
||||
heap_.Deallocate(*a);
|
||||
}
|
||||
act->scope()->deallocated = true;
|
||||
}
|
||||
scope.deallocated = true;
|
||||
return act;
|
||||
}
|
||||
|
||||
auto Interpreter::CreateTuple(Nonnull<Action*> act,
|
||||
@@ -848,13 +852,13 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
CHECK(act->pos() == 0);
|
||||
// { { break; :: ... :: (while (e) s) :: C, E, F} :: S, H}
|
||||
// -> { { C, E', F} :: S, H}
|
||||
return UnwindPast{&cast<Break>(stmt).loop()};
|
||||
return UnwindPast{.ast_node = &cast<Break>(stmt).loop()};
|
||||
}
|
||||
case Statement::Kind::Continue: {
|
||||
CHECK(act->pos() == 0);
|
||||
// { { continue; :: ... :: (while (e) s) :: C, E, F} :: S, H}
|
||||
// -> { { (while (e) s) :: C, E', F} :: S, H}
|
||||
return UnwindTo{&cast<Continue>(stmt).loop()};
|
||||
return UnwindTo{.ast_node = &cast<Continue>(stmt).loop()};
|
||||
}
|
||||
case Statement::Kind::Block: {
|
||||
const auto& block = cast<Block>(stmt);
|
||||
@@ -963,7 +967,8 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
// TODO(geoffromer): convert the result to the function's return type,
|
||||
// once #880 gives us a way to find that type.
|
||||
const FunctionDeclaration& function = cast<Return>(stmt).function();
|
||||
return UnwindPast{*function.body(), act->results()[0]};
|
||||
return UnwindPast{.ast_node = *function.body(),
|
||||
.result = act->results()[0]};
|
||||
}
|
||||
case Statement::Kind::Continuation: {
|
||||
CHECK(act->pos() == 0);
|
||||
@@ -1024,10 +1029,7 @@ class Interpreter::DoTransition {
|
||||
explicit DoTransition(Interpreter* interpreter) : interpreter(interpreter) {}
|
||||
|
||||
void operator()(const Done& done) {
|
||||
Nonnull<Action*> act = interpreter->todo_.Pop();
|
||||
if (act->scope().has_value()) {
|
||||
interpreter->DeallocateScope(*act->scope());
|
||||
}
|
||||
Nonnull<Action*> act = interpreter->UnwindTodoTop();
|
||||
switch (act->kind()) {
|
||||
case Action::Kind::ExpressionAction:
|
||||
case Action::Kind::LValAction:
|
||||
@@ -1065,33 +1067,12 @@ class Interpreter::DoTransition {
|
||||
action->set_pos(action->pos() + 1);
|
||||
}
|
||||
|
||||
void operator()(const UnwindTo& unwind_to) {
|
||||
while (true) {
|
||||
if (const auto* statement_action =
|
||||
dyn_cast<StatementAction>(interpreter->todo_.Top());
|
||||
statement_action != nullptr &&
|
||||
&statement_action->statement() == unwind_to.ast_node) {
|
||||
break;
|
||||
}
|
||||
Nonnull<Action*> action = interpreter->todo_.Pop();
|
||||
if (action->scope().has_value()) {
|
||||
interpreter->DeallocateScope(*action->scope());
|
||||
}
|
||||
}
|
||||
}
|
||||
void operator()(const UnwindTo& unwind_to) { DoUnwindTo(unwind_to.ast_node); }
|
||||
|
||||
void operator()(const UnwindPast& unwind_past) {
|
||||
while (true) {
|
||||
Nonnull<Action*> action = interpreter->todo_.Pop();
|
||||
if (action->scope().has_value()) {
|
||||
interpreter->DeallocateScope(*action->scope());
|
||||
}
|
||||
if (const auto* statement_action = dyn_cast<StatementAction>(action);
|
||||
statement_action != nullptr &&
|
||||
&statement_action->statement() == unwind_past.ast_node) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoUnwindTo(unwind_past.ast_node);
|
||||
// Unwind past the statement and return a result if needed.
|
||||
interpreter->UnwindTodoTop();
|
||||
if (unwind_past.result.has_value()) {
|
||||
interpreter->todo_.Top()->AddResult(*unwind_past.result);
|
||||
}
|
||||
@@ -1123,6 +1104,19 @@ class Interpreter::DoTransition {
|
||||
void operator()(const ManualTransition&) {}
|
||||
|
||||
private:
|
||||
// Unwinds to the indicated node.
|
||||
void DoUnwindTo(Nonnull<const Statement*> ast_node) {
|
||||
while (true) {
|
||||
if (const auto* statement_action =
|
||||
dyn_cast<StatementAction>(interpreter->todo_.Top());
|
||||
statement_action != nullptr &&
|
||||
&statement_action->statement() == ast_node) {
|
||||
break;
|
||||
}
|
||||
interpreter->UnwindTodoTop();
|
||||
}
|
||||
}
|
||||
|
||||
Nonnull<Interpreter*> interpreter;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user