mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-04 15:20:16 +00:00
refactor(aquavm): improve readability of ap
merger and handler (#354)
At the moment `Ap` state contains vector of generations, although the ap instruction itself allow to specify only one stream. It was done to support several streams in a result position in a future. But the current realization allows to handle empty vector that was implemented to support states for scalars and it turned out (for more info see #326) that states for scalars aren't actually needed. Closes #355.
This commit is contained in:
parent
a8b227caf5
commit
cd598c28ae
@ -30,8 +30,8 @@ use crate::SecurityTetraplet;
|
||||
use apply_to_arguments::*;
|
||||
use utils::*;
|
||||
|
||||
use air_parser::ast;
|
||||
use air_parser::ast::Ap;
|
||||
use air_parser::ast::ApResult;
|
||||
use air_trace_handler::merger::MergerApResult;
|
||||
|
||||
use std::rc::Rc;
|
||||
@ -46,9 +46,9 @@ impl<'i> super::ExecutableInstruction<'i> for Ap<'i> {
|
||||
// https://github.com/fluencelabs/aquavm/issues/216
|
||||
let result = apply_to_arg(&self.argument, exec_ctx, trace_ctx, should_touch_trace)?;
|
||||
|
||||
let merger_ap_result = to_merger_ap_result(should_touch_trace, self, trace_ctx)?;
|
||||
let maybe_generation = update_context(&self.result, &merger_ap_result, result, exec_ctx)?;
|
||||
maybe_update_trace(should_touch_trace, &merger_ap_result, maybe_generation, trace_ctx);
|
||||
let merger_ap_result = to_merger_ap_result(self, trace_ctx)?;
|
||||
let maybe_generation = populate_context(&self.result, &merger_ap_result, result, exec_ctx)?;
|
||||
maybe_update_trace(maybe_generation, trace_ctx);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -57,34 +57,28 @@ impl<'i> super::ExecutableInstruction<'i> for Ap<'i> {
|
||||
/// This function is intended to check whether a Ap instruction should produce
|
||||
/// a new state in data.
|
||||
fn should_touch_trace(ap: &Ap<'_>) -> bool {
|
||||
matches!(ap.result, ApResult::Stream(_))
|
||||
matches!(ap.result, ast::ApResult::Stream(_))
|
||||
}
|
||||
|
||||
fn to_merger_ap_result(
|
||||
should_touch_trace: bool,
|
||||
instr: &Ap<'_>,
|
||||
trace_ctx: &mut TraceHandler,
|
||||
) -> ExecutionResult<MergerApResult> {
|
||||
let merger_ap_result = if should_touch_trace {
|
||||
let merger_ap_result = trace_to_exec_err!(trace_ctx.meet_ap_start(), instr)?;
|
||||
try_match_trace_to_instr(&merger_ap_result, instr)?;
|
||||
merger_ap_result
|
||||
} else {
|
||||
MergerApResult::Empty
|
||||
};
|
||||
fn to_merger_ap_result(instr: &Ap<'_>, trace_ctx: &mut TraceHandler) -> ExecutionResult<MergerApResult> {
|
||||
if !should_touch_trace(instr) {
|
||||
return Ok(MergerApResult::NotMet);
|
||||
}
|
||||
|
||||
let merger_ap_result = trace_to_exec_err!(trace_ctx.meet_ap_start(), instr)?;
|
||||
try_match_trace_to_instr(&merger_ap_result, instr)?;
|
||||
Ok(merger_ap_result)
|
||||
}
|
||||
|
||||
fn update_context<'ctx>(
|
||||
ap_result_type: &ApResult<'ctx>,
|
||||
fn populate_context<'ctx>(
|
||||
ap_result: &ast::ApResult<'ctx>,
|
||||
merger_ap_result: &MergerApResult,
|
||||
result: ValueAggregate,
|
||||
exec_ctx: &mut ExecutionCtx<'ctx>,
|
||||
) -> ExecutionResult<Option<u32>> {
|
||||
match ap_result_type {
|
||||
ApResult::Scalar(scalar) => exec_ctx.scalars.set_scalar_value(scalar.name, result).map(|_| None),
|
||||
ApResult::Stream(stream) => {
|
||||
match ap_result {
|
||||
ast::ApResult::Scalar(scalar) => exec_ctx.scalars.set_scalar_value(scalar.name, result).map(|_| None),
|
||||
ast::ApResult::Stream(stream) => {
|
||||
let generation = ap_result_to_generation(merger_ap_result);
|
||||
exec_ctx
|
||||
.streams
|
||||
@ -94,18 +88,11 @@ fn update_context<'ctx>(
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_update_trace(
|
||||
should_touch_trace: bool,
|
||||
merger_ap_result: &MergerApResult,
|
||||
maybe_generation: Option<u32>,
|
||||
trace_ctx: &mut TraceHandler,
|
||||
) {
|
||||
if !should_touch_trace {
|
||||
// if generations are empty, then this ap instruction operates only with scalars and data
|
||||
// shouldn't be updated
|
||||
return;
|
||||
}
|
||||
fn maybe_update_trace(maybe_generation: Option<u32>, trace_ctx: &mut TraceHandler) {
|
||||
use air_interpreter_data::ApResult;
|
||||
|
||||
let final_ap_result = to_ap_result(merger_ap_result, maybe_generation);
|
||||
trace_ctx.meet_ap_end(final_ap_result);
|
||||
if let Some(generation) = maybe_generation {
|
||||
let final_ap_result = ApResult::new(generation);
|
||||
trace_ctx.meet_ap_end(final_ap_result);
|
||||
}
|
||||
}
|
||||
|
@ -17,56 +17,31 @@
|
||||
use super::ExecutionResult;
|
||||
use crate::execution_step::Generation;
|
||||
|
||||
use air_interpreter_data::ApResult;
|
||||
use air_parser::ast;
|
||||
use air_parser::ast::Ap;
|
||||
use air_trace_handler::merger::MergerApResult;
|
||||
|
||||
pub(super) fn ap_result_to_generation(ap_result: &MergerApResult) -> Generation {
|
||||
match ap_result {
|
||||
MergerApResult::Empty => Generation::Last,
|
||||
MergerApResult::ApResult { res_generation, .. } => Generation::from_option(*res_generation),
|
||||
use air_trace_handler::merger::ValueSource;
|
||||
|
||||
let met_result = match ap_result {
|
||||
MergerApResult::NotMet => return Generation::Last,
|
||||
MergerApResult::Met(met_result) => met_result,
|
||||
};
|
||||
|
||||
match met_result.value_source {
|
||||
ValueSource::PreviousData => Generation::Nth(met_result.generation),
|
||||
ValueSource::CurrentData => Generation::Last,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn try_match_trace_to_instr(merger_ap_result: &MergerApResult, instr: &Ap<'_>) -> ExecutionResult<()> {
|
||||
let res_generation = match merger_ap_result {
|
||||
MergerApResult::ApResult { res_generation } => *res_generation,
|
||||
MergerApResult::Empty => return Ok(()),
|
||||
};
|
||||
|
||||
match_position_variable(&instr.result, res_generation, merger_ap_result)
|
||||
}
|
||||
|
||||
fn match_position_variable(
|
||||
variable: &ast::ApResult<'_>,
|
||||
generation: Option<u32>,
|
||||
ap_result: &MergerApResult,
|
||||
) -> ExecutionResult<()> {
|
||||
use crate::execution_step::UncatchableError::ApResultNotCorrespondToInstr;
|
||||
use ast::ApResult::*;
|
||||
use ast::ApResult;
|
||||
|
||||
match (variable, generation) {
|
||||
(Stream(_), Some(_)) => Ok(()),
|
||||
(Scalar(_), None) => Ok(()),
|
||||
_ => Err(ApResultNotCorrespondToInstr(ap_result.clone()).into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn to_ap_result(merger_ap_result: &MergerApResult, maybe_generation: Option<u32>) -> ApResult {
|
||||
if let MergerApResult::ApResult { res_generation } = merger_ap_result {
|
||||
let res_generation = option_to_vec(*res_generation);
|
||||
|
||||
return ApResult::new(res_generation);
|
||||
}
|
||||
|
||||
let res_generation = option_to_vec(maybe_generation);
|
||||
ApResult::new(res_generation)
|
||||
}
|
||||
|
||||
fn option_to_vec(value: Option<u32>) -> Vec<u32> {
|
||||
match value {
|
||||
Some(value) => vec![value],
|
||||
None => vec![],
|
||||
match (&instr.result, merger_ap_result) {
|
||||
(ApResult::Stream(_), MergerApResult::Met(_)) => Ok(()),
|
||||
(_, MergerApResult::NotMet) => Ok(()),
|
||||
_ => Err(ApResultNotCorrespondToInstr(merger_ap_result.clone()).into()),
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ use air_interpreter_data::CallResult;
|
||||
use air_interpreter_data::Sender;
|
||||
use air_interpreter_interface::CallServiceResult;
|
||||
use air_parser::ast::CallOutputValue;
|
||||
use air_trace_handler::merger::MetResult;
|
||||
use air_trace_handler::merger::MetCallResult;
|
||||
use air_trace_handler::TraceHandler;
|
||||
|
||||
use fstrings::f;
|
||||
@ -38,7 +38,7 @@ pub(crate) struct StateDescriptor {
|
||||
/// This function looks at the existing call state, validates it,
|
||||
/// and returns Ok(true) if the call should be executed further.
|
||||
pub(super) fn handle_prev_state<'i>(
|
||||
met_result: MetResult,
|
||||
met_result: MetCallResult,
|
||||
tetraplet: &RcSecurityTetraplet,
|
||||
output: &CallOutputValue<'i>,
|
||||
exec_ctx: &mut ExecutionCtx<'i>,
|
||||
|
@ -190,15 +190,6 @@ pub(crate) enum Generation {
|
||||
Nth(u32),
|
||||
}
|
||||
|
||||
impl Generation {
|
||||
pub(crate) fn from_option(raw_generation: Option<u32>) -> Self {
|
||||
match raw_generation {
|
||||
Some(generation) => Generation::Nth(generation),
|
||||
None => Generation::Last,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct StreamIter<'result> {
|
||||
iter: Box<dyn Iterator<Item = &'result ValueAggregate> + 'result>,
|
||||
len: usize,
|
||||
|
@ -83,8 +83,8 @@ fn length_functor_for_stream() {
|
||||
let actual_trace = trace_from_result(&result);
|
||||
|
||||
let expected_trace = vec![
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar_number(2),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
@ -131,8 +131,8 @@ fn length_functor_for_canon_stream() {
|
||||
let actual_trace = trace_from_result(&result);
|
||||
|
||||
let expected_trace = vec![
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(vec![0.into(), 1.into()]),
|
||||
executed_state::scalar_number(2),
|
||||
];
|
||||
|
@ -228,13 +228,13 @@ fn recursive_stream_join() {
|
||||
executed_state::subtrace_lore(11, subtrace_desc(12, 2), subtrace_desc(14, 0)),
|
||||
]),
|
||||
executed_state::scalar_string("non_join"),
|
||||
executed_state::ap(Some(1)),
|
||||
executed_state::ap(1),
|
||||
executed_state::scalar_string("non_join"),
|
||||
executed_state::ap(Some(2)),
|
||||
executed_state::ap(2),
|
||||
executed_state::scalar_string("non_join"),
|
||||
executed_state::ap(Some(3)),
|
||||
executed_state::ap(3),
|
||||
executed_state::scalar_string("non_join"),
|
||||
executed_state::ap(Some(4)),
|
||||
executed_state::ap(4),
|
||||
executed_state::scalar_string("join"),
|
||||
executed_state::scalar_string(""),
|
||||
executed_state::scalar_string(result_value),
|
||||
|
@ -66,10 +66,7 @@ fn ap_with_string_literal() {
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_state = vec![
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::scalar(json!([some_string])),
|
||||
];
|
||||
let expected_state = vec![executed_state::ap(0), executed_state::scalar(json!([some_string]))];
|
||||
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
assert!(result.next_peer_pks.is_empty());
|
||||
@ -90,7 +87,7 @@ fn ap_with_bool_literal() {
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_state = vec![executed_state::ap(Some(0)), executed_state::scalar(json!([true]))];
|
||||
let expected_state = vec![executed_state::ap(0), executed_state::scalar(json!([true]))];
|
||||
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
assert!(result.next_peer_pks.is_empty());
|
||||
@ -111,7 +108,7 @@ fn ap_with_number_literal() {
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_state = vec![executed_state::ap(Some(0)), executed_state::scalar(json!([100]))];
|
||||
let expected_state = vec![executed_state::ap(0), executed_state::scalar(json!([100]))];
|
||||
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
assert!(result.next_peer_pks.is_empty());
|
||||
@ -132,7 +129,7 @@ fn ap_with_last_error() {
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_state = vec![executed_state::ap(Some(0)), executed_state::scalar(json!([null]))];
|
||||
let expected_state = vec![executed_state::ap(0), executed_state::scalar(json!([null]))];
|
||||
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
assert!(result.next_peer_pks.is_empty());
|
||||
@ -205,7 +202,7 @@ fn ap_with_dst_stream() {
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_state = vec![
|
||||
executed_state::scalar(json!({ "field": test_value })),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar(json!([{ "field": test_value }])),
|
||||
];
|
||||
|
||||
@ -240,7 +237,7 @@ fn ap_canon_stream_with_lambda() {
|
||||
executed_state::stream_number(0, 0),
|
||||
executed_state::stream_number(1, 1),
|
||||
executed_state::canon(vec![0.into(), 1.into()]),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar(json!([1])),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
@ -281,7 +278,7 @@ fn ap_canon_stream() {
|
||||
executed_state::stream_number(0, 0),
|
||||
executed_state::stream_number(1, 1),
|
||||
executed_state::canon(vec![0.into(), 1.into()]),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar(json!([[0, 1]])),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
|
@ -654,8 +654,8 @@ fn fold_stream_seq_next_saves_call_result() {
|
||||
let actual_trace = trace_from_result(&result);
|
||||
|
||||
let expected_trace = vec![
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::fold(vec![
|
||||
subtrace_lore(0, SubTraceDesc::new(3.into(), 1), SubTraceDesc::new(6.into(), 0)),
|
||||
subtrace_lore(1, SubTraceDesc::new(4.into(), 1), SubTraceDesc::new(5.into(), 1)),
|
||||
@ -704,9 +704,9 @@ fn fold_par_next_completes() {
|
||||
let result_2 = checked_call_vm!(vm_2, <_>::default(), &script, "", result_1.data.clone());
|
||||
let actual_trace = trace_from_result(&result_2);
|
||||
let expected_trace = vec![
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::fold(vec![
|
||||
subtrace_lore(0, SubTraceDesc::new(4.into(), 2), SubTraceDesc::new(10.into(), 0)),
|
||||
subtrace_lore(1, SubTraceDesc::new(6.into(), 2), SubTraceDesc::new(10.into(), 0)),
|
||||
@ -725,9 +725,9 @@ fn fold_par_next_completes() {
|
||||
let result_3 = checked_call_vm!(vm_3, <_>::default(), &script, "", result_1.data.clone());
|
||||
let actual_trace = trace_from_result(&result_3);
|
||||
let expected_trace = vec![
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::fold(vec![
|
||||
subtrace_lore(0, SubTraceDesc::new(4.into(), 2), SubTraceDesc::new(10.into(), 0)),
|
||||
subtrace_lore(1, SubTraceDesc::new(6.into(), 2), SubTraceDesc::new(10.into(), 0)),
|
||||
@ -746,9 +746,9 @@ fn fold_par_next_completes() {
|
||||
let result_4 = checked_call_vm!(vm_4, <_>::default(), &script, "", result_1.data);
|
||||
let actual_trace = trace_from_result(&result_4);
|
||||
let expected_trace = vec![
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::fold(vec![
|
||||
subtrace_lore(0, SubTraceDesc::new(4.into(), 2), SubTraceDesc::new(10.into(), 0)),
|
||||
subtrace_lore(1, SubTraceDesc::new(6.into(), 2), SubTraceDesc::new(10.into(), 0)),
|
||||
|
@ -159,9 +159,9 @@ fn check_influence_to_not_restricted() {
|
||||
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_trace = vec![
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar(json!(["more"])),
|
||||
executed_state::scalar(json!(["push more"])),
|
||||
executed_state::scalar(json!(["push more"])),
|
||||
@ -202,15 +202,15 @@ fn new_in_fold_with_ap() {
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_trace = vec![
|
||||
executed_state::scalar(json!([1, 2, 3, 4, 5])),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar_string_array(vec!["none"]),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar_string_array(vec!["none"]),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar_string_array(vec!["none"]),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar_string_array(vec!["none"]),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar_string_array(vec!["none"]),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
|
@ -43,6 +43,6 @@ fn issue_206() {
|
||||
let result = checked_call_vm!(peer_1, test_params, &script, "", "");
|
||||
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_trace = vec![executed_state::ap(Some(0)), executed_state::scalar(json!(["is nil"]))];
|
||||
let expected_trace = vec![executed_state::ap(0), executed_state::scalar(json!(["is nil"]))];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
}
|
||||
|
@ -68,11 +68,11 @@ fn issue_211() {
|
||||
executed_state::scalar(json!([1, 2, 3])),
|
||||
executed_state::par(6, 0),
|
||||
executed_state::par(1, 4),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::par(1, 2),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::par(1, 0),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar_string("expected result"),
|
||||
executed_state::scalar_string("expected result"),
|
||||
];
|
||||
|
@ -89,10 +89,10 @@ fn issue_221() {
|
||||
executed_state::scalar(json!([peer_1_id, peer_2_id])),
|
||||
executed_state::par(2, 3),
|
||||
executed_state::scalar_string(peer_1_value),
|
||||
executed_state::ap(Some(0)),
|
||||
executed_state::ap(0),
|
||||
executed_state::par(2, 0),
|
||||
executed_state::scalar_string(peer_2_value),
|
||||
executed_state::ap(Some(1)),
|
||||
executed_state::ap(1),
|
||||
executed_state::fold(vec![
|
||||
executed_state::subtrace_lore(3, SubTraceDesc::new(8.into(), 4), SubTraceDesc::new(12.into(), 0)),
|
||||
executed_state::subtrace_lore(6, SubTraceDesc::new(12.into(), 4), SubTraceDesc::new(16.into(), 0)),
|
||||
|
@ -34,7 +34,7 @@ fn issue_295() {
|
||||
)
|
||||
"#);
|
||||
|
||||
let prev_trace = vec![executed_state::scalar_string(""), executed_state::ap(Some(1))];
|
||||
let prev_trace = vec![executed_state::scalar_string(""), executed_state::ap(1)];
|
||||
let current_trace = vec![executed_state::scalar_string(""), executed_state::scalar_string("")];
|
||||
let prev_data = raw_data_from_trace(prev_trace);
|
||||
let current_data = raw_data_from_trace(current_trace);
|
||||
@ -42,7 +42,7 @@ fn issue_295() {
|
||||
|
||||
let expected_error = UncatchableError::TraceError {
|
||||
trace_error: TraceHandlerError::MergeError(MergeError::IncompatibleExecutedStates(
|
||||
ExecutedState::Ap(ApResult::new(vec![1])),
|
||||
ExecutedState::Ap(ApResult::new(1)),
|
||||
ExecutedState::Call(CallResult::Executed(Value::Scalar(Rc::new(json!(""))))),
|
||||
)),
|
||||
instruction: "ap scalar $stream".to_string(),
|
||||
|
@ -79,9 +79,9 @@ impl ExecutedState {
|
||||
}
|
||||
|
||||
impl ApResult {
|
||||
pub fn new(res_gens: Vec<u32>) -> Self {
|
||||
pub fn new(res_generation: u32) -> Self {
|
||||
Self {
|
||||
res_generations: res_gens,
|
||||
res_generations: vec![res_generation],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,10 +132,8 @@ pub fn subtrace_desc(begin_pos: impl Into<TracePos>, subtrace_len: u32) -> SubTr
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ap(dst: Option<u32>) -> ExecutedState {
|
||||
let res_generations = option_to_vec(dst);
|
||||
let ap_result = ApResult::new(res_generations);
|
||||
|
||||
pub fn ap(generation: u32) -> ExecutedState {
|
||||
let ap_result = ApResult::new(generation);
|
||||
ExecutedState::Ap(ap_result)
|
||||
}
|
||||
|
||||
@ -143,10 +141,3 @@ pub fn canon(stream_elements_pos: Vec<TracePos>) -> ExecutedState {
|
||||
let canon_result = CanonResult::new(stream_elements_pos);
|
||||
ExecutedState::Canon(canon_result)
|
||||
}
|
||||
|
||||
fn option_to_vec(maybe_value: Option<u32>) -> Vec<u32> {
|
||||
match maybe_value {
|
||||
Some(value) => vec![value],
|
||||
None => vec![],
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,17 @@ const EXPECTED_STATE_NAME: &str = "ap";
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MergerApResult {
|
||||
/// There is no corresponding state in a trace for this call.
|
||||
Empty,
|
||||
NotMet,
|
||||
|
||||
/// There was a state in at least one of the contexts. If there were two states in
|
||||
/// both contexts, they were successfully merged.
|
||||
ApResult { res_generation: Option<u32> },
|
||||
Met(MetApResult),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MetApResult {
|
||||
pub generation: u32,
|
||||
pub value_source: ValueSource,
|
||||
}
|
||||
|
||||
pub(crate) fn try_merge_next_state_as_ap(data_keeper: &mut DataKeeper) -> MergeResult<MergerApResult> {
|
||||
@ -36,12 +42,12 @@ pub(crate) fn try_merge_next_state_as_ap(data_keeper: &mut DataKeeper) -> MergeR
|
||||
let current_state = data_keeper.current_slider_mut().next_state();
|
||||
|
||||
match (prev_state, current_state) {
|
||||
(Some(Ap(prev_ap)), Some(Ap(_))) => prepare_merge_result(Some(prev_ap), Both, data_keeper),
|
||||
(Some(Ap(prev_ap)), None) => prepare_merge_result(Some(prev_ap), Previous, data_keeper),
|
||||
(Some(Ap(prev_ap)), Some(Ap(_))) => prepare_merge_result(prev_ap, Both, data_keeper),
|
||||
(Some(Ap(prev_ap)), None) => prepare_merge_result(prev_ap, Previous, data_keeper),
|
||||
// check that current state is Ap, but it's impossible to use it, because prev_data
|
||||
// could not have streams with such generations
|
||||
(None, Some(Ap(_))) => prepare_merge_result(None, Current, data_keeper),
|
||||
(None, None) => Ok(MergerApResult::Empty),
|
||||
(None, Some(Ap(current_ap))) => prepare_merge_result(current_ap, Current, data_keeper),
|
||||
(None, None) => Ok(MergerApResult::NotMet),
|
||||
(prev_state, current_state) => Err(MergeError::incompatible_states(
|
||||
prev_state,
|
||||
current_state,
|
||||
@ -50,24 +56,10 @@ pub(crate) fn try_merge_next_state_as_ap(data_keeper: &mut DataKeeper) -> MergeR
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_merge_result(
|
||||
ap_result: Option<ApResult>,
|
||||
scheme: PreparationScheme,
|
||||
data_keeper: &mut DataKeeper,
|
||||
) -> MergeResult<MergerApResult> {
|
||||
prepare_positions_mapping(scheme, data_keeper);
|
||||
|
||||
match ap_result {
|
||||
Some(ap_result) => to_merger_result(ap_result),
|
||||
None => Ok(MergerApResult::Empty),
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! to_maybe_generation {
|
||||
($ap_result:ident, $generations:expr, $error_ty:ident) => {
|
||||
match $generations.len() {
|
||||
0 => None,
|
||||
1 => Some($generations[0]),
|
||||
1 => $generations[0],
|
||||
_ => {
|
||||
let ap_error = super::ApResultError::$error_ty($ap_result);
|
||||
return Err(super::MergeError::IncorrectApResult(ap_error));
|
||||
@ -76,10 +68,25 @@ macro_rules! to_maybe_generation {
|
||||
};
|
||||
}
|
||||
|
||||
fn to_merger_result(ap_result: ApResult) -> MergeResult<MergerApResult> {
|
||||
let res_generation = to_maybe_generation!(ap_result, &ap_result.res_generations, TooManyDstGenerations);
|
||||
fn prepare_merge_result(
|
||||
ap_result: ApResult,
|
||||
scheme: PreparationScheme,
|
||||
data_keeper: &mut DataKeeper,
|
||||
) -> MergeResult<MergerApResult> {
|
||||
prepare_positions_mapping(scheme, data_keeper);
|
||||
|
||||
let ap_result = MergerApResult::ApResult { res_generation };
|
||||
let generation = to_maybe_generation!(ap_result, &ap_result.res_generations, InvalidDstGenerations);
|
||||
let met_result = MetApResult::new(generation, scheme.into());
|
||||
let ap_result = MergerApResult::Met(met_result);
|
||||
|
||||
Ok(ap_result)
|
||||
}
|
||||
|
||||
impl MetApResult {
|
||||
pub(crate) fn new(generation: u32, value_source: ValueSource) -> Self {
|
||||
Self {
|
||||
generation,
|
||||
value_source,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,22 +29,16 @@ pub enum MergerCallResult {
|
||||
|
||||
/// There was a state in at least one of the contexts. If there were two states in
|
||||
/// both contexts, they were successfully merged.
|
||||
Met(MetResult),
|
||||
Met(MetCallResult),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MetResult {
|
||||
pub struct MetCallResult {
|
||||
pub result: CallResult,
|
||||
pub trace_pos: TracePos,
|
||||
pub source: ValueSource,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ValueSource {
|
||||
PreviousData,
|
||||
CurrentData,
|
||||
}
|
||||
|
||||
pub(crate) fn try_merge_next_state_as_call(data_keeper: &mut DataKeeper) -> MergeResult<MergerCallResult> {
|
||||
use ExecutedState::Call;
|
||||
use PreparationScheme::*;
|
||||
@ -99,7 +93,7 @@ pub(super) fn prepare_call_result(
|
||||
let trace_pos = data_keeper.result_trace_next_pos();
|
||||
prepare_positions_mapping(scheme, data_keeper);
|
||||
|
||||
let met_result = MetResult::new(call_result, trace_pos, scheme.into());
|
||||
let met_result = MetCallResult::new(call_result, trace_pos, scheme.into());
|
||||
MergerCallResult::Met(met_result)
|
||||
}
|
||||
|
||||
@ -112,7 +106,7 @@ impl From<PreparationScheme> for ValueSource {
|
||||
}
|
||||
}
|
||||
|
||||
impl MetResult {
|
||||
impl MetCallResult {
|
||||
pub fn new(result: CallResult, trace_pos: TracePos, source: ValueSource) -> Self {
|
||||
Self {
|
||||
result,
|
||||
|
@ -55,9 +55,9 @@ pub enum MergeError {
|
||||
|
||||
#[derive(ThisError, Debug)]
|
||||
pub enum ApResultError {
|
||||
/// Error occurred when Ap results contains more then 1 generation in destination.
|
||||
#[error("{0:?} ap result contains too many generations in destination")]
|
||||
TooManyDstGenerations(ApResult),
|
||||
/// Error occurred when Ap results contains not 1 generation in destination.
|
||||
#[error("{0:?} ap result contains inappropriate generation count in destination")]
|
||||
InvalidDstGenerations(ApResult),
|
||||
}
|
||||
|
||||
#[derive(ThisError, Debug)]
|
||||
|
@ -240,7 +240,7 @@ mod tests {
|
||||
|
||||
let fold_result = FoldResult { lore };
|
||||
|
||||
let slider = TraceSlider::new(vec![ExecutedState::Ap(ApResult::new(vec![0]))]);
|
||||
let slider = TraceSlider::new(vec![ExecutedState::Ap(ApResult::new(0))]);
|
||||
let ctx = MergeCtx { slider };
|
||||
|
||||
let (all_states, convoluted_lens) =
|
||||
@ -285,9 +285,9 @@ mod tests {
|
||||
let fold_result = FoldResult { lore };
|
||||
|
||||
let slider = TraceSlider::new(vec![
|
||||
ExecutedState::Ap(ApResult::new(vec![0])),
|
||||
ExecutedState::Ap(ApResult::new(vec![1])),
|
||||
ExecutedState::Ap(ApResult::new(vec![2])),
|
||||
ExecutedState::Ap(ApResult::new(0)),
|
||||
ExecutedState::Ap(ApResult::new(1)),
|
||||
ExecutedState::Ap(ApResult::new(2)),
|
||||
]);
|
||||
let ctx = MergeCtx { slider };
|
||||
|
||||
|
@ -23,9 +23,9 @@ mod par_merger;
|
||||
mod position_mapping;
|
||||
|
||||
pub use ap_merger::MergerApResult;
|
||||
pub use ap_merger::MetApResult;
|
||||
pub use call_merger::MergerCallResult;
|
||||
pub use call_merger::MetResult;
|
||||
pub use call_merger::ValueSource;
|
||||
pub use call_merger::MetCallResult;
|
||||
pub use canon_merger::MergerCanonResult;
|
||||
pub use fold_merger::MergerFoldResult;
|
||||
pub use par_merger::MergerParResult;
|
||||
@ -60,6 +60,12 @@ pub enum MergeCtxType {
|
||||
Previous,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ValueSource {
|
||||
PreviousData,
|
||||
CurrentData,
|
||||
}
|
||||
|
||||
use std::fmt;
|
||||
|
||||
impl fmt::Display for MergeCtxType {
|
||||
|
Loading…
Reference in New Issue
Block a user