use crate::error::{
OwnedRuleAttemptStepError, OwnedRunStepError, RuleAttemptStepError, RunStepError,
};
use crate::inspect::RuleView;
use crate::limits::{RuleAttemptCount, StepCount};
use crate::program::{Program, ReturnOutput};
use super::attempt::{RuleAttemptStableReason, RuleMiss};
use super::engine::{AttemptSession, CoreAppliedRule, CoreRuleAttempt, CoreStep, RunCore, Session};
use super::session::{
BorrowedRuleAttemptSession, BorrowedRunSession, OwnedRuleAttemptSession, OwnedRunSession,
};
use super::transition::{
BorrowedAppliedStep, BorrowedFailedRun, BorrowedMissedRuleAttempt, BorrowedReturnedRun,
BorrowedRuleAttemptAppliedStep, BorrowedRuleAttemptFailedRun, BorrowedRuleAttemptReturnedRun,
BorrowedRuleAttemptStableRun, BorrowedRuleAttemptTransition, BorrowedStableRun,
BorrowedStepTransition, OwnedAppliedStep, OwnedFailedRun, OwnedMissedRuleAttempt,
OwnedReturnedRun, OwnedRuleAttemptAppliedStep, OwnedRuleAttemptFailedRun,
OwnedRuleAttemptReturnedRun, OwnedRuleAttemptStableRun, OwnedRuleAttemptTransition,
OwnedStableRun, OwnedStepTransition,
};
use super::witness::OwnedRuleWitness;
pub(super) struct StepwiseApplied<RuleWitness> {
step: StepCount,
rule: RuleWitness,
}
pub(super) struct StepwiseReturned<RuleWitness> {
step: StepCount,
rule: RuleWitness,
output: ReturnOutput,
}
pub(super) struct TerminalRunParts<ProgramHandle> {
program: ProgramHandle,
core: RunCore,
}
pub(super) struct RuleAttemptMissed<RuleWitness> {
attempt: RuleAttemptCount,
miss: RuleMiss<RuleWitness>,
}
pub(super) struct RuleAttemptApplied<RuleWitness> {
attempt: RuleAttemptCount,
step: StepCount,
rule: RuleWitness,
}
pub(super) struct RuleAttemptReturned<RuleWitness> {
attempt: RuleAttemptCount,
step: StepCount,
rule: RuleWitness,
output: ReturnOutput,
}
pub(super) struct RuleAttemptStable<RuleWitness> {
attempts: RuleAttemptCount,
steps: StepCount,
stable_reason: RuleAttemptStableReason<RuleWitness>,
}
pub(super) trait StepwiseTransition<Session, RuleWitness, ProgramHandle, StepError> {
fn applied(applied: StepwiseApplied<RuleWitness>, session: Session) -> Self;
fn returned(
returned: StepwiseReturned<RuleWitness>,
terminal: TerminalRunParts<ProgramHandle>,
) -> Self;
fn stable(steps: StepCount, terminal: TerminalRunParts<ProgramHandle>) -> Self;
fn failed(error: StepError, session: Session) -> Self;
}
pub(super) trait RuleAttemptTransition<Session, RuleWitness, ProgramHandle, StepError> {
fn missed(missed: RuleAttemptMissed<RuleWitness>, session: Session) -> Self;
fn applied(applied: RuleAttemptApplied<RuleWitness>, session: Session) -> Self;
fn returned(
returned: RuleAttemptReturned<RuleWitness>,
terminal: TerminalRunParts<ProgramHandle>,
) -> Self;
fn stable(
stable: RuleAttemptStable<RuleWitness>,
terminal: TerminalRunParts<ProgramHandle>,
) -> Self;
fn failed(error: StepError, session: Session) -> Self;
}
pub(super) trait StepwiseRunSession: Sized {
type Transition: StepwiseTransition<Self, Self::RuleWitness, Self::TerminalProgram, Self::StepError>;
type RuleWitness;
type StepError;
type TerminalProgram;
fn session_step(&mut self) -> Result<CoreStep<Self::RuleWitness>, Self::StepError>;
fn into_terminal_parts(self) -> TerminalRunParts<Self::TerminalProgram>;
fn step_transition(mut self) -> Self::Transition {
match self.session_step() {
Ok(CoreStep::Applied(CoreAppliedRule::Rewrite { step, rule })) => {
Self::Transition::applied(StepwiseApplied { step, rule }, self)
}
Ok(CoreStep::Applied(CoreAppliedRule::Return { step, rule, output })) => {
Self::Transition::returned(
StepwiseReturned { step, rule, output },
self.into_terminal_parts(),
)
}
Ok(CoreStep::Stable(steps)) => {
Self::Transition::stable(steps, self.into_terminal_parts())
}
Err(error) => Self::Transition::failed(error, self),
}
}
}
pub(super) trait RuleAttemptRunSession: Sized {
type Transition: RuleAttemptTransition<Self, Self::RuleWitness, Self::TerminalProgram, Self::StepError>;
type RuleWitness;
type StepError;
type TerminalProgram;
fn session_step(&mut self) -> Result<CoreRuleAttempt<Self::RuleWitness>, Self::StepError>;
fn into_terminal_parts(self) -> TerminalRunParts<Self::TerminalProgram>;
fn step_transition(mut self) -> Self::Transition {
match self.session_step() {
Ok(CoreRuleAttempt::Missed { attempt, miss }) => {
Self::Transition::missed(RuleAttemptMissed { attempt, miss }, self)
}
Ok(CoreRuleAttempt::Applied {
attempt,
applied: CoreAppliedRule::Rewrite { step, rule },
}) => Self::Transition::applied(
RuleAttemptApplied {
attempt,
step,
rule,
},
self,
),
Ok(CoreRuleAttempt::Applied {
attempt,
applied: CoreAppliedRule::Return { step, rule, output },
}) => Self::Transition::returned(
RuleAttemptReturned {
attempt,
step,
rule,
output,
},
self.into_terminal_parts(),
),
Ok(CoreRuleAttempt::Stable {
attempts,
steps,
stable_reason,
}) => Self::Transition::stable(
RuleAttemptStable {
attempts,
steps,
stable_reason,
},
self.into_terminal_parts(),
),
Err(error) => Self::Transition::failed(error, self),
}
}
}
impl<'program> StepwiseRunSession for BorrowedRunSession<'program> {
type Transition = BorrowedStepTransition<'program>;
type RuleWitness = RuleView<'program>;
type StepError = RunStepError;
type TerminalProgram = &'program Program;
fn session_step(&mut self) -> Result<CoreStep<Self::RuleWitness>, Self::StepError> {
self.session.step_borrowed()
}
fn into_terminal_parts(self) -> TerminalRunParts<Self::TerminalProgram> {
let Session { program, core } = self.session;
TerminalRunParts {
program: program.program,
core,
}
}
}
impl<'program>
StepwiseTransition<
BorrowedRunSession<'program>,
RuleView<'program>,
&'program Program,
RunStepError,
> for BorrowedStepTransition<'program>
{
fn applied(
StepwiseApplied { step, rule }: StepwiseApplied<RuleView<'program>>,
session: BorrowedRunSession<'program>,
) -> Self {
BorrowedStepTransition::Applied(BorrowedAppliedStep {
step,
rule,
session,
})
}
fn returned(
StepwiseReturned { step, rule, output }: StepwiseReturned<RuleView<'program>>,
TerminalRunParts { program, core: _ }: TerminalRunParts<&'program Program>,
) -> Self {
BorrowedStepTransition::Returned(BorrowedReturnedRun {
step,
rule,
program,
output,
})
}
fn stable(
steps: StepCount,
TerminalRunParts { program, core }: TerminalRunParts<&'program Program>,
) -> Self {
BorrowedStepTransition::Stable(BorrowedStableRun {
steps,
program,
core,
})
}
fn failed(error: RunStepError, session: BorrowedRunSession<'program>) -> Self {
BorrowedStepTransition::Failed(BorrowedFailedRun::new(error, session))
}
}
impl StepwiseRunSession for OwnedRunSession {
type Transition = OwnedStepTransition;
type RuleWitness = OwnedRuleWitness;
type StepError = OwnedRunStepError;
type TerminalProgram = Program;
fn session_step(&mut self) -> Result<CoreStep<Self::RuleWitness>, Self::StepError> {
self.session.step_owned()
}
fn into_terminal_parts(self) -> TerminalRunParts<Self::TerminalProgram> {
let (program, core) = self.session.into_program_core();
TerminalRunParts { program, core }
}
}
impl StepwiseTransition<OwnedRunSession, OwnedRuleWitness, Program, OwnedRunStepError>
for OwnedStepTransition
{
fn applied(
StepwiseApplied { step, rule }: StepwiseApplied<OwnedRuleWitness>,
session: OwnedRunSession,
) -> Self {
OwnedStepTransition::Applied(OwnedAppliedStep {
step,
rule,
session,
})
}
fn returned(
StepwiseReturned { step, rule, output }: StepwiseReturned<OwnedRuleWitness>,
TerminalRunParts { program, core: _ }: TerminalRunParts<Program>,
) -> Self {
OwnedStepTransition::Returned(OwnedReturnedRun {
step,
rule,
program,
output,
})
}
fn stable(
steps: StepCount,
TerminalRunParts { program, core }: TerminalRunParts<Program>,
) -> Self {
OwnedStepTransition::Stable(OwnedStableRun {
steps,
program,
core,
})
}
fn failed(error: OwnedRunStepError, session: OwnedRunSession) -> Self {
OwnedStepTransition::Failed(OwnedFailedRun::new(error, session))
}
}
impl<'program> RuleAttemptRunSession for BorrowedRuleAttemptSession<'program> {
type Transition = BorrowedRuleAttemptTransition<'program>;
type RuleWitness = RuleView<'program>;
type StepError = RuleAttemptStepError;
type TerminalProgram = &'program Program;
fn session_step(&mut self) -> Result<CoreRuleAttempt<Self::RuleWitness>, Self::StepError> {
self.session.step_borrowed()
}
fn into_terminal_parts(self) -> TerminalRunParts<Self::TerminalProgram> {
let AttemptSession {
program,
core,
cursor: _,
attempt_budget: _,
} = self.session;
TerminalRunParts {
program: program.program,
core,
}
}
}
impl<'program>
RuleAttemptTransition<
BorrowedRuleAttemptSession<'program>,
RuleView<'program>,
&'program Program,
RuleAttemptStepError,
> for BorrowedRuleAttemptTransition<'program>
{
fn missed(
RuleAttemptMissed { attempt, miss }: RuleAttemptMissed<RuleView<'program>>,
session: BorrowedRuleAttemptSession<'program>,
) -> Self {
BorrowedRuleAttemptTransition::Missed(BorrowedMissedRuleAttempt {
attempt,
miss,
session,
})
}
fn applied(
RuleAttemptApplied {
attempt,
step,
rule,
}: RuleAttemptApplied<RuleView<'program>>,
session: BorrowedRuleAttemptSession<'program>,
) -> Self {
BorrowedRuleAttemptTransition::Applied(BorrowedRuleAttemptAppliedStep {
attempt,
step,
rule,
session,
})
}
fn returned(
RuleAttemptReturned {
attempt,
step,
rule,
output,
}: RuleAttemptReturned<RuleView<'program>>,
TerminalRunParts { program, core: _ }: TerminalRunParts<&'program Program>,
) -> Self {
BorrowedRuleAttemptTransition::Returned(BorrowedRuleAttemptReturnedRun {
attempt,
step,
rule,
program,
output,
})
}
fn stable(
RuleAttemptStable {
attempts,
steps,
stable_reason,
}: RuleAttemptStable<RuleView<'program>>,
TerminalRunParts { program, core }: TerminalRunParts<&'program Program>,
) -> Self {
BorrowedRuleAttemptTransition::Stable(BorrowedRuleAttemptStableRun {
attempts,
steps,
stable_reason,
program,
core,
})
}
fn failed(error: RuleAttemptStepError, session: BorrowedRuleAttemptSession<'program>) -> Self {
BorrowedRuleAttemptTransition::Failed(BorrowedRuleAttemptFailedRun::new(error, session))
}
}
impl RuleAttemptRunSession for OwnedRuleAttemptSession {
type Transition = OwnedRuleAttemptTransition;
type RuleWitness = OwnedRuleWitness;
type StepError = OwnedRuleAttemptStepError;
type TerminalProgram = Program;
fn session_step(&mut self) -> Result<CoreRuleAttempt<Self::RuleWitness>, Self::StepError> {
self.session.step_owned()
}
fn into_terminal_parts(self) -> TerminalRunParts<Self::TerminalProgram> {
let (program, core) = self.session.into_program_core();
TerminalRunParts { program, core }
}
}
impl
RuleAttemptTransition<
OwnedRuleAttemptSession,
OwnedRuleWitness,
Program,
OwnedRuleAttemptStepError,
> for OwnedRuleAttemptTransition
{
fn missed(
RuleAttemptMissed { attempt, miss }: RuleAttemptMissed<OwnedRuleWitness>,
session: OwnedRuleAttemptSession,
) -> Self {
OwnedRuleAttemptTransition::Missed(OwnedMissedRuleAttempt {
attempt,
miss,
session,
})
}
fn applied(
RuleAttemptApplied {
attempt,
step,
rule,
}: RuleAttemptApplied<OwnedRuleWitness>,
session: OwnedRuleAttemptSession,
) -> Self {
OwnedRuleAttemptTransition::Applied(OwnedRuleAttemptAppliedStep {
attempt,
step,
rule,
session,
})
}
fn returned(
RuleAttemptReturned {
attempt,
step,
rule,
output,
}: RuleAttemptReturned<OwnedRuleWitness>,
TerminalRunParts { program, core: _ }: TerminalRunParts<Program>,
) -> Self {
OwnedRuleAttemptTransition::Returned(OwnedRuleAttemptReturnedRun {
attempt,
step,
rule,
program,
output,
})
}
fn stable(
RuleAttemptStable {
attempts,
steps,
stable_reason,
}: RuleAttemptStable<OwnedRuleWitness>,
TerminalRunParts { program, core }: TerminalRunParts<Program>,
) -> Self {
OwnedRuleAttemptTransition::Stable(OwnedRuleAttemptStableRun {
attempts,
steps,
stable_reason,
program,
core,
})
}
fn failed(error: OwnedRuleAttemptStepError, session: OwnedRuleAttemptSession) -> Self {
OwnedRuleAttemptTransition::Failed(OwnedRuleAttemptFailedRun::new(error, session))
}
}