For loop for arrays (#1753)

Co-authored-by: m new <michael.burzan@outlook.de>
Co-authored-by: Geoff Romer <gromer@google.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
pmqtt
2022-08-09 15:34:24 -07:00
committed by GitHub
co-authored by m new Geoff Romer Richard Smith
parent 2c921efe36
commit f754373786
23 changed files with 361 additions and 4 deletions
+71
View File
@@ -1505,7 +1505,78 @@ auto Interpreter::StepStmt() -> ErrorOr<Success> {
}
}
}
case StatementKind::For: {
constexpr int TargetVarPosInResult = 0;
constexpr int CurrentIndexPosInResult = 1;
constexpr int EndIndexPosInResult = 2;
constexpr int LoopVarPosInResult = 3;
if (act.pos() == 0) {
return todo_.Spawn(
std::make_unique<ExpressionAction>(&cast<For>(stmt).loop_target()));
}
if (act.pos() == 1) {
Nonnull<const TupleValue*> source_array =
cast<const TupleValue>(act.results()[TargetVarPosInResult]);
auto end_index = static_cast<int>(source_array->elements().size());
if (end_index == 0) {
return todo_.FinishAction();
}
act.AddResult(arena_->New<IntValue>(0));
act.AddResult(arena_->New<IntValue>(end_index));
return todo_.Spawn(std::make_unique<PatternAction>(
&cast<For>(stmt).variable_declaration()));
}
if (act.pos() == 2) {
Nonnull<const BindingPlaceholderValue*> loop_var =
cast<const BindingPlaceholderValue>(
act.results()[LoopVarPosInResult]);
Nonnull<const TupleValue*> source_array =
cast<const TupleValue>(act.results()[TargetVarPosInResult]);
auto start_index =
cast<IntValue>(act.results()[CurrentIndexPosInResult])->value();
todo_.Initialize(*(loop_var->value_node()),
source_array->elements()[start_index]);
act.ReplaceResult(CurrentIndexPosInResult,
arena_->New<IntValue>(start_index + 1));
return todo_.Spawn(
std::make_unique<StatementAction>(&cast<For>(stmt).body()));
}
if (act.pos() >= 3) {
auto current_index =
cast<IntValue>(act.results()[CurrentIndexPosInResult])->value();
auto end_index =
cast<IntValue>(act.results()[EndIndexPosInResult])->value();
if (current_index < end_index) {
Nonnull<const TupleValue*> source_array =
cast<const TupleValue>(act.results()[TargetVarPosInResult]);
Nonnull<const BindingPlaceholderValue*> loop_var =
cast<const BindingPlaceholderValue>(
act.results()[LoopVarPosInResult]);
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> assigned_array_element,
todo_.ValueOfNode(*(loop_var->value_node()), stmt.source_loc()));
auto lvalue = cast<LValue>(assigned_array_element);
CARBON_RETURN_IF_ERROR(heap_.Write(
lvalue->address(), source_array->elements()[current_index],
stmt.source_loc()));
act.ReplaceResult(CurrentIndexPosInResult,
arena_->New<IntValue>(current_index + 1));
return todo_.Spawn(
std::make_unique<StatementAction>(&cast<For>(stmt).body()));
}
}
return todo_.FinishAction();
}
case StatementKind::While:
// TODO: Rewrite While to use ReplaceResult to store condition result.
// This will remove the inconsistency between the while and for
// loops.
if (act.pos() % 2 == 0) {
// { { (while (e) s) :: C, E, F} :: S, H}
// -> { { e :: (while ([]) s) :: C, E, F} :: S, H}