use super::fold::IterableType;
use super::ExecutionCtx;
use super::ExecutionResult;
use super::FoldState;
use super::TraceHandler;
use crate::execution_step::PEEK_ALLOWED_ON_NON_EMPTY;
use crate::log_instruction;
use crate::trace_to_exec_err;
use air_parser::ast::Next;
impl<'i> super::ExecutableInstruction<'i> for Next<'i> {
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
log_instruction!(next, exec_ctx, trace_ctx);
let iterator_name = &self.iterator.name;
let fold_state = exec_ctx.scalars.get_iterable_mut(iterator_name)?;
maybe_meet_iteration_end(self, fold_state, trace_ctx)?;
if !fold_state.iterable.next() {
maybe_meet_back_iterator(self, fold_state, trace_ctx)?;
let fold_state = exec_ctx.scalars.get_iterable(iterator_name)?;
if let Some(last_instr) = &fold_state.last_instr_head {
let last_instr = last_instr.clone();
exec_ctx.flush_subgraph_completeness(); last_instr.execute(exec_ctx, trace_ctx)?;
} else {
let fold_state = exec_ctx.scalars.get_iterable_mut(iterator_name)?;
if !fold_state.back_iteration_started && matches!(fold_state.iterable_type, IterableType::Stream(_)) {
fold_state.back_iteration_started = true;
exec_ctx.make_subgraph_incomplete();
}
}
return Ok(());
}
let next_instr = fold_state.instr_head.clone();
maybe_meet_iteration_start(self, fold_state, trace_ctx)?;
exec_ctx.scalars.meet_next_before();
let result = next_instr.execute(exec_ctx, trace_ctx);
exec_ctx.scalars.meet_next_after();
result?;
let fold_state = exec_ctx.scalars.get_iterable_mut(iterator_name)?;
fold_state.iterable.prev();
maybe_meet_back_iterator(self, fold_state, trace_ctx)?;
Ok(())
}
}
fn maybe_meet_iteration_start<'i>(
next: &Next<'i>,
fold_state: &FoldState<'i>,
trace_ctx: &mut TraceHandler,
) -> ExecutionResult<()> {
if let IterableType::Stream(fold_id) = &fold_state.iterable_type {
trace_to_exec_err!(
trace_ctx.meet_iteration_start(
*fold_id,
fold_state.iterable.peek().expect(PEEK_ALLOWED_ON_NON_EMPTY).pos()
),
next
)?;
}
Ok(())
}
fn maybe_meet_iteration_end<'i>(
next: &Next<'i>,
fold_state: &FoldState<'i>,
trace_ctx: &mut TraceHandler,
) -> ExecutionResult<()> {
if let IterableType::Stream(fold_id) = &fold_state.iterable_type {
trace_to_exec_err!(trace_ctx.meet_iteration_end(*fold_id), next)?;
}
Ok(())
}
fn maybe_meet_back_iterator<'i>(
next: &Next<'i>,
fold_state: &FoldState<'i>,
trace_ctx: &mut TraceHandler,
) -> ExecutionResult<()> {
if let IterableType::Stream(fold_id) = &fold_state.iterable_type {
trace_to_exec_err!(trace_ctx.meet_back_iterator(*fold_id), next)?;
}
Ok(())
}