Feature destructor (#2116)

This commit is contained in:
pmqtt
2022-09-26 10:11:05 -07:00
committed by GitHub
parent c63ae9b05d
commit cfa295c0af
29 changed files with 827 additions and 82 deletions
+79 -2
View File
@@ -4,6 +4,8 @@
#include "explorer/interpreter/interpreter.h"
#include <llvm/Support/raw_ostream.h>
#include <iterator>
#include <map>
#include <optional>
@@ -83,6 +85,8 @@ class Interpreter {
auto StepStmt() -> ErrorOr<Success>;
// State transition for declarations.
auto StepDeclaration() -> ErrorOr<Success>;
// State transition for object destruction.
auto StepCleanUp() -> ErrorOr<Success>;
auto CreateStruct(const std::vector<FieldInitializer>& fields,
const std::vector<Nonnull<const Value*>>& values)
@@ -142,6 +146,9 @@ class Interpreter {
Nonnull<const Value*> arg, ImplWitnessMap&& witnesses)
-> ErrorOr<Success>;
auto CallDestructor(Nonnull<const DestructorDeclaration*> fun,
Nonnull<const Value*> receiver) -> ErrorOr<Success>;
void PrintState(llvm::raw_ostream& out);
Phase phase() const { return phase_; }
@@ -615,6 +622,7 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
switch (value->kind()) {
case Value::Kind::IntValue:
case Value::Kind::FunctionValue:
case Value::Kind::DestructorValue:
case Value::Kind::BoundMethodValue:
case Value::Kind::PointerValue:
case Value::Kind::LValue:
@@ -739,6 +747,26 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
}
}
auto Interpreter::CallDestructor(Nonnull<const DestructorDeclaration*> fun,
Nonnull<const Value*> receiver)
-> ErrorOr<Success> {
const DestructorDeclaration& method = *fun;
CARBON_CHECK(method.is_method());
RuntimeScope method_scope(&heap_);
BindingMap generic_args;
CARBON_CHECK(PatternMatch(&method.me_pattern().value(), receiver,
fun->source_loc(), &method_scope, generic_args,
trace_stream_, this->arena_));
CARBON_CHECK(method.body().has_value())
<< "Calling a method that's missing a body";
auto act = std::make_unique<StatementAction>(*method.body());
method_scope.TransitState();
return todo_.Spawn(std::unique_ptr<Action>(std::move(act)),
std::move(method_scope));
}
auto Interpreter::CallFunction(const CallExpression& call,
Nonnull<const Value*> fun,
Nonnull<const Value*> arg,
@@ -1756,7 +1784,7 @@ auto Interpreter::StepStmt() -> ErrorOr<Success> {
CARBON_ASSIGN_OR_RETURN(
value, heap_.Read(lvalue->address(), ret_var.source_loc()));
}
const FunctionDeclaration& function = cast<Return>(stmt).function();
const CallableDeclaration& function = cast<Return>(stmt).function();
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> return_value,
Convert(value, &function.return_term().static_type(),
@@ -1772,7 +1800,7 @@ auto Interpreter::StepStmt() -> ErrorOr<Success> {
} else {
// { {v :: return [] :: C, E, F} :: {C', E', F'} :: S, H}
// -> { {v :: C', E', F'} :: S, H}
const FunctionDeclaration& function = cast<Return>(stmt).function();
const CallableDeclaration& function = cast<Return>(stmt).function();
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> return_value,
Convert(act.results()[0], &function.return_term().static_type(),
@@ -1841,6 +1869,7 @@ auto Interpreter::StepDeclaration() -> ErrorOr<Success> {
return todo_.FinishAction();
}
}
case DeclarationKind::DestructorDeclaration:
case DeclarationKind::FunctionDeclaration:
case DeclarationKind::ClassDeclaration:
case DeclarationKind::MixinDeclaration:
@@ -1856,6 +1885,51 @@ auto Interpreter::StepDeclaration() -> ErrorOr<Success> {
}
}
auto Interpreter::StepCleanUp() -> ErrorOr<Success> {
Action& act = todo_.CurrentAction();
CleanupAction& cleanup = cast<CleanupAction>(act);
if (act.pos() < cleanup.locals_count()) {
auto lvalue = act.scope()->locals()[cleanup.locals_count() - act.pos() - 1];
SourceLocation source_loc("destructor", 1);
auto value = heap_.Read(lvalue->address(), source_loc);
if (value.ok()) {
if (act.scope()->DestructionState() < RuntimeScope::State::CleanUpped) {
if (const auto* class_obj = dyn_cast<NominalClassValue>(*value)) {
const auto& class_type = cast<NominalClassType>(class_obj->type());
const auto& class_dec = class_type.declaration();
if (class_dec.destructor().has_value()) {
return CallDestructor(*class_dec.destructor(), class_obj);
}
}
} else {
if (const auto* class_obj = dyn_cast<NominalClassValue>(*value)) {
const auto& class_type = cast<NominalClassType>(class_obj->type());
const auto& class_dec = class_type.declaration();
const auto& class_members = class_dec.members();
for (const auto& member : class_members) {
if (const auto* var = dyn_cast<VariableDeclaration>(member)) {
const auto& type = var->static_type();
if (const auto* c_type = dyn_cast<NominalClassType>(&type)) {
auto& c_dec = c_type->declaration();
if (c_dec.destructor().has_value()) {
Address object = lvalue->address();
Address mem = object.SubobjectAddress(Member(var));
auto v = heap_.Read(mem, source_loc);
act.scope()->TransitState();
return CallDestructor(*c_dec.destructor(), *v);
}
}
}
}
}
act.scope()->TransitState();
}
}
}
todo_.Pop();
return Success();
}
// State transition.
auto Interpreter::Step() -> ErrorOr<Success> {
Action& act = todo_.CurrentAction();
@@ -1875,6 +1949,9 @@ auto Interpreter::Step() -> ErrorOr<Success> {
case Action::Kind::DeclarationAction:
CARBON_RETURN_IF_ERROR(StepDeclaration());
break;
case Action::Kind::CleanUpAction:
CARBON_RETURN_IF_ERROR(StepCleanUp());
break;
case Action::Kind::ScopeAction:
CARBON_FATAL() << "ScopeAction escaped ActionStack";
case Action::Kind::RecursiveAction: