mirror of
https://github.com/fluencelabs/aquavm
synced 2025-03-15 20:40:50 +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 apply_to_arguments::*;
|
||||||
use utils::*;
|
use utils::*;
|
||||||
|
|
||||||
|
use air_parser::ast;
|
||||||
use air_parser::ast::Ap;
|
use air_parser::ast::Ap;
|
||||||
use air_parser::ast::ApResult;
|
|
||||||
use air_trace_handler::merger::MergerApResult;
|
use air_trace_handler::merger::MergerApResult;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -46,9 +46,9 @@ impl<'i> super::ExecutableInstruction<'i> for Ap<'i> {
|
|||||||
// https://github.com/fluencelabs/aquavm/issues/216
|
// https://github.com/fluencelabs/aquavm/issues/216
|
||||||
let result = apply_to_arg(&self.argument, exec_ctx, trace_ctx, should_touch_trace)?;
|
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 merger_ap_result = to_merger_ap_result(self, trace_ctx)?;
|
||||||
let maybe_generation = update_context(&self.result, &merger_ap_result, result, exec_ctx)?;
|
let maybe_generation = populate_context(&self.result, &merger_ap_result, result, exec_ctx)?;
|
||||||
maybe_update_trace(should_touch_trace, &merger_ap_result, maybe_generation, trace_ctx);
|
maybe_update_trace(maybe_generation, trace_ctx);
|
||||||
|
|
||||||
Ok(())
|
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
|
/// This function is intended to check whether a Ap instruction should produce
|
||||||
/// a new state in data.
|
/// a new state in data.
|
||||||
fn should_touch_trace(ap: &Ap<'_>) -> bool {
|
fn should_touch_trace(ap: &Ap<'_>) -> bool {
|
||||||
matches!(ap.result, ApResult::Stream(_))
|
matches!(ap.result, ast::ApResult::Stream(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_merger_ap_result(
|
fn to_merger_ap_result(instr: &Ap<'_>, trace_ctx: &mut TraceHandler) -> ExecutionResult<MergerApResult> {
|
||||||
should_touch_trace: bool,
|
if !should_touch_trace(instr) {
|
||||||
instr: &Ap<'_>,
|
return Ok(MergerApResult::NotMet);
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
|
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)
|
Ok(merger_ap_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_context<'ctx>(
|
fn populate_context<'ctx>(
|
||||||
ap_result_type: &ApResult<'ctx>,
|
ap_result: &ast::ApResult<'ctx>,
|
||||||
merger_ap_result: &MergerApResult,
|
merger_ap_result: &MergerApResult,
|
||||||
result: ValueAggregate,
|
result: ValueAggregate,
|
||||||
exec_ctx: &mut ExecutionCtx<'ctx>,
|
exec_ctx: &mut ExecutionCtx<'ctx>,
|
||||||
) -> ExecutionResult<Option<u32>> {
|
) -> ExecutionResult<Option<u32>> {
|
||||||
match ap_result_type {
|
match ap_result {
|
||||||
ApResult::Scalar(scalar) => exec_ctx.scalars.set_scalar_value(scalar.name, result).map(|_| None),
|
ast::ApResult::Scalar(scalar) => exec_ctx.scalars.set_scalar_value(scalar.name, result).map(|_| None),
|
||||||
ApResult::Stream(stream) => {
|
ast::ApResult::Stream(stream) => {
|
||||||
let generation = ap_result_to_generation(merger_ap_result);
|
let generation = ap_result_to_generation(merger_ap_result);
|
||||||
exec_ctx
|
exec_ctx
|
||||||
.streams
|
.streams
|
||||||
@ -94,18 +88,11 @@ fn update_context<'ctx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_update_trace(
|
fn maybe_update_trace(maybe_generation: Option<u32>, trace_ctx: &mut TraceHandler) {
|
||||||
should_touch_trace: bool,
|
use air_interpreter_data::ApResult;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
let final_ap_result = to_ap_result(merger_ap_result, maybe_generation);
|
if let Some(generation) = maybe_generation {
|
||||||
trace_ctx.meet_ap_end(final_ap_result);
|
let final_ap_result = ApResult::new(generation);
|
||||||
|
trace_ctx.meet_ap_end(final_ap_result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,56 +17,31 @@
|
|||||||
use super::ExecutionResult;
|
use super::ExecutionResult;
|
||||||
use crate::execution_step::Generation;
|
use crate::execution_step::Generation;
|
||||||
|
|
||||||
use air_interpreter_data::ApResult;
|
|
||||||
use air_parser::ast;
|
use air_parser::ast;
|
||||||
use air_parser::ast::Ap;
|
use air_parser::ast::Ap;
|
||||||
use air_trace_handler::merger::MergerApResult;
|
use air_trace_handler::merger::MergerApResult;
|
||||||
|
|
||||||
pub(super) fn ap_result_to_generation(ap_result: &MergerApResult) -> Generation {
|
pub(super) fn ap_result_to_generation(ap_result: &MergerApResult) -> Generation {
|
||||||
match ap_result {
|
use air_trace_handler::merger::ValueSource;
|
||||||
MergerApResult::Empty => Generation::Last,
|
|
||||||
MergerApResult::ApResult { res_generation, .. } => Generation::from_option(*res_generation),
|
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<()> {
|
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 crate::execution_step::UncatchableError::ApResultNotCorrespondToInstr;
|
||||||
use ast::ApResult::*;
|
use ast::ApResult;
|
||||||
|
|
||||||
match (variable, generation) {
|
match (&instr.result, merger_ap_result) {
|
||||||
(Stream(_), Some(_)) => Ok(()),
|
(ApResult::Stream(_), MergerApResult::Met(_)) => Ok(()),
|
||||||
(Scalar(_), None) => Ok(()),
|
(_, MergerApResult::NotMet) => Ok(()),
|
||||||
_ => Err(ApResultNotCorrespondToInstr(ap_result.clone()).into()),
|
_ => Err(ApResultNotCorrespondToInstr(merger_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![],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ use air_interpreter_data::CallResult;
|
|||||||
use air_interpreter_data::Sender;
|
use air_interpreter_data::Sender;
|
||||||
use air_interpreter_interface::CallServiceResult;
|
use air_interpreter_interface::CallServiceResult;
|
||||||
use air_parser::ast::CallOutputValue;
|
use air_parser::ast::CallOutputValue;
|
||||||
use air_trace_handler::merger::MetResult;
|
use air_trace_handler::merger::MetCallResult;
|
||||||
use air_trace_handler::TraceHandler;
|
use air_trace_handler::TraceHandler;
|
||||||
|
|
||||||
use fstrings::f;
|
use fstrings::f;
|
||||||
@ -38,7 +38,7 @@ pub(crate) struct StateDescriptor {
|
|||||||
/// This function looks at the existing call state, validates it,
|
/// This function looks at the existing call state, validates it,
|
||||||
/// and returns Ok(true) if the call should be executed further.
|
/// and returns Ok(true) if the call should be executed further.
|
||||||
pub(super) fn handle_prev_state<'i>(
|
pub(super) fn handle_prev_state<'i>(
|
||||||
met_result: MetResult,
|
met_result: MetCallResult,
|
||||||
tetraplet: &RcSecurityTetraplet,
|
tetraplet: &RcSecurityTetraplet,
|
||||||
output: &CallOutputValue<'i>,
|
output: &CallOutputValue<'i>,
|
||||||
exec_ctx: &mut ExecutionCtx<'i>,
|
exec_ctx: &mut ExecutionCtx<'i>,
|
||||||
|
@ -190,15 +190,6 @@ pub(crate) enum Generation {
|
|||||||
Nth(u32),
|
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> {
|
pub(crate) struct StreamIter<'result> {
|
||||||
iter: Box<dyn Iterator<Item = &'result ValueAggregate> + 'result>,
|
iter: Box<dyn Iterator<Item = &'result ValueAggregate> + 'result>,
|
||||||
len: usize,
|
len: usize,
|
||||||
|
@ -83,8 +83,8 @@ fn length_functor_for_stream() {
|
|||||||
let actual_trace = trace_from_result(&result);
|
let actual_trace = trace_from_result(&result);
|
||||||
|
|
||||||
let expected_trace = vec![
|
let expected_trace = vec![
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::scalar_number(2),
|
executed_state::scalar_number(2),
|
||||||
];
|
];
|
||||||
assert_eq!(actual_trace, expected_trace);
|
assert_eq!(actual_trace, expected_trace);
|
||||||
@ -131,8 +131,8 @@ fn length_functor_for_canon_stream() {
|
|||||||
let actual_trace = trace_from_result(&result);
|
let actual_trace = trace_from_result(&result);
|
||||||
|
|
||||||
let expected_trace = vec![
|
let expected_trace = vec![
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::canon(vec![0.into(), 1.into()]),
|
executed_state::canon(vec![0.into(), 1.into()]),
|
||||||
executed_state::scalar_number(2),
|
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::subtrace_lore(11, subtrace_desc(12, 2), subtrace_desc(14, 0)),
|
||||||
]),
|
]),
|
||||||
executed_state::scalar_string("non_join"),
|
executed_state::scalar_string("non_join"),
|
||||||
executed_state::ap(Some(1)),
|
executed_state::ap(1),
|
||||||
executed_state::scalar_string("non_join"),
|
executed_state::scalar_string("non_join"),
|
||||||
executed_state::ap(Some(2)),
|
executed_state::ap(2),
|
||||||
executed_state::scalar_string("non_join"),
|
executed_state::scalar_string("non_join"),
|
||||||
executed_state::ap(Some(3)),
|
executed_state::ap(3),
|
||||||
executed_state::scalar_string("non_join"),
|
executed_state::scalar_string("non_join"),
|
||||||
executed_state::ap(Some(4)),
|
executed_state::ap(4),
|
||||||
executed_state::scalar_string("join"),
|
executed_state::scalar_string("join"),
|
||||||
executed_state::scalar_string(""),
|
executed_state::scalar_string(""),
|
||||||
executed_state::scalar_string(result_value),
|
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 result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||||
|
|
||||||
let actual_trace = trace_from_result(&result);
|
let actual_trace = trace_from_result(&result);
|
||||||
let expected_state = vec![
|
let expected_state = vec![executed_state::ap(0), executed_state::scalar(json!([some_string]))];
|
||||||
executed_state::ap(Some(0)),
|
|
||||||
executed_state::scalar(json!([some_string])),
|
|
||||||
];
|
|
||||||
|
|
||||||
assert_eq!(actual_trace, expected_state);
|
assert_eq!(actual_trace, expected_state);
|
||||||
assert!(result.next_peer_pks.is_empty());
|
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 result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||||
|
|
||||||
let actual_trace = trace_from_result(&result);
|
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_eq!(actual_trace, expected_state);
|
||||||
assert!(result.next_peer_pks.is_empty());
|
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 result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||||
|
|
||||||
let actual_trace = trace_from_result(&result);
|
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_eq!(actual_trace, expected_state);
|
||||||
assert!(result.next_peer_pks.is_empty());
|
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 result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||||
|
|
||||||
let actual_trace = trace_from_result(&result);
|
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_eq!(actual_trace, expected_state);
|
||||||
assert!(result.next_peer_pks.is_empty());
|
assert!(result.next_peer_pks.is_empty());
|
||||||
@ -205,7 +202,7 @@ fn ap_with_dst_stream() {
|
|||||||
let actual_trace = trace_from_result(&result);
|
let actual_trace = trace_from_result(&result);
|
||||||
let expected_state = vec![
|
let expected_state = vec![
|
||||||
executed_state::scalar(json!({ "field": test_value })),
|
executed_state::scalar(json!({ "field": test_value })),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::scalar(json!([{ "field": test_value }])),
|
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(0, 0),
|
||||||
executed_state::stream_number(1, 1),
|
executed_state::stream_number(1, 1),
|
||||||
executed_state::canon(vec![0.into(), 1.into()]),
|
executed_state::canon(vec![0.into(), 1.into()]),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::scalar(json!([1])),
|
executed_state::scalar(json!([1])),
|
||||||
];
|
];
|
||||||
assert_eq!(actual_trace, expected_state);
|
assert_eq!(actual_trace, expected_state);
|
||||||
@ -281,7 +278,7 @@ fn ap_canon_stream() {
|
|||||||
executed_state::stream_number(0, 0),
|
executed_state::stream_number(0, 0),
|
||||||
executed_state::stream_number(1, 1),
|
executed_state::stream_number(1, 1),
|
||||||
executed_state::canon(vec![0.into(), 1.into()]),
|
executed_state::canon(vec![0.into(), 1.into()]),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::scalar(json!([[0, 1]])),
|
executed_state::scalar(json!([[0, 1]])),
|
||||||
];
|
];
|
||||||
assert_eq!(actual_trace, expected_state);
|
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 actual_trace = trace_from_result(&result);
|
||||||
|
|
||||||
let expected_trace = vec![
|
let expected_trace = vec![
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::fold(vec![
|
executed_state::fold(vec![
|
||||||
subtrace_lore(0, SubTraceDesc::new(3.into(), 1), SubTraceDesc::new(6.into(), 0)),
|
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)),
|
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 result_2 = checked_call_vm!(vm_2, <_>::default(), &script, "", result_1.data.clone());
|
||||||
let actual_trace = trace_from_result(&result_2);
|
let actual_trace = trace_from_result(&result_2);
|
||||||
let expected_trace = vec![
|
let expected_trace = vec![
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::fold(vec![
|
executed_state::fold(vec![
|
||||||
subtrace_lore(0, SubTraceDesc::new(4.into(), 2), SubTraceDesc::new(10.into(), 0)),
|
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)),
|
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 result_3 = checked_call_vm!(vm_3, <_>::default(), &script, "", result_1.data.clone());
|
||||||
let actual_trace = trace_from_result(&result_3);
|
let actual_trace = trace_from_result(&result_3);
|
||||||
let expected_trace = vec![
|
let expected_trace = vec![
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::fold(vec![
|
executed_state::fold(vec![
|
||||||
subtrace_lore(0, SubTraceDesc::new(4.into(), 2), SubTraceDesc::new(10.into(), 0)),
|
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)),
|
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 result_4 = checked_call_vm!(vm_4, <_>::default(), &script, "", result_1.data);
|
||||||
let actual_trace = trace_from_result(&result_4);
|
let actual_trace = trace_from_result(&result_4);
|
||||||
let expected_trace = vec![
|
let expected_trace = vec![
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::fold(vec![
|
executed_state::fold(vec![
|
||||||
subtrace_lore(0, SubTraceDesc::new(4.into(), 2), SubTraceDesc::new(10.into(), 0)),
|
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)),
|
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 actual_trace = trace_from_result(&result);
|
||||||
let expected_trace = vec![
|
let expected_trace = vec![
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::scalar(json!(["more"])),
|
executed_state::scalar(json!(["more"])),
|
||||||
executed_state::scalar(json!(["push more"])),
|
executed_state::scalar(json!(["push 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 actual_trace = trace_from_result(&result);
|
||||||
let expected_trace = vec![
|
let expected_trace = vec![
|
||||||
executed_state::scalar(json!([1, 2, 3, 4, 5])),
|
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::scalar_string_array(vec!["none"]),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::scalar_string_array(vec!["none"]),
|
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::scalar_string_array(vec!["none"]),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::scalar_string_array(vec!["none"]),
|
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::scalar_string_array(vec!["none"]),
|
||||||
];
|
];
|
||||||
assert_eq!(actual_trace, expected_trace);
|
assert_eq!(actual_trace, expected_trace);
|
||||||
|
@ -43,6 +43,6 @@ fn issue_206() {
|
|||||||
let result = checked_call_vm!(peer_1, test_params, &script, "", "");
|
let result = checked_call_vm!(peer_1, test_params, &script, "", "");
|
||||||
|
|
||||||
let actual_trace = trace_from_result(&result);
|
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);
|
assert_eq!(actual_trace, expected_trace);
|
||||||
}
|
}
|
||||||
|
@ -68,11 +68,11 @@ fn issue_211() {
|
|||||||
executed_state::scalar(json!([1, 2, 3])),
|
executed_state::scalar(json!([1, 2, 3])),
|
||||||
executed_state::par(6, 0),
|
executed_state::par(6, 0),
|
||||||
executed_state::par(1, 4),
|
executed_state::par(1, 4),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::par(1, 2),
|
executed_state::par(1, 2),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::par(1, 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"),
|
||||||
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::scalar(json!([peer_1_id, peer_2_id])),
|
||||||
executed_state::par(2, 3),
|
executed_state::par(2, 3),
|
||||||
executed_state::scalar_string(peer_1_value),
|
executed_state::scalar_string(peer_1_value),
|
||||||
executed_state::ap(Some(0)),
|
executed_state::ap(0),
|
||||||
executed_state::par(2, 0),
|
executed_state::par(2, 0),
|
||||||
executed_state::scalar_string(peer_2_value),
|
executed_state::scalar_string(peer_2_value),
|
||||||
executed_state::ap(Some(1)),
|
executed_state::ap(1),
|
||||||
executed_state::fold(vec![
|
executed_state::fold(vec![
|
||||||
executed_state::subtrace_lore(3, SubTraceDesc::new(8.into(), 4), SubTraceDesc::new(12.into(), 0)),
|
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)),
|
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 current_trace = vec![executed_state::scalar_string(""), executed_state::scalar_string("")];
|
||||||
let prev_data = raw_data_from_trace(prev_trace);
|
let prev_data = raw_data_from_trace(prev_trace);
|
||||||
let current_data = raw_data_from_trace(current_trace);
|
let current_data = raw_data_from_trace(current_trace);
|
||||||
@ -42,7 +42,7 @@ fn issue_295() {
|
|||||||
|
|
||||||
let expected_error = UncatchableError::TraceError {
|
let expected_error = UncatchableError::TraceError {
|
||||||
trace_error: TraceHandlerError::MergeError(MergeError::IncompatibleExecutedStates(
|
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!(""))))),
|
ExecutedState::Call(CallResult::Executed(Value::Scalar(Rc::new(json!(""))))),
|
||||||
)),
|
)),
|
||||||
instruction: "ap scalar $stream".to_string(),
|
instruction: "ap scalar $stream".to_string(),
|
||||||
|
@ -79,9 +79,9 @@ impl ExecutedState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ApResult {
|
impl ApResult {
|
||||||
pub fn new(res_gens: Vec<u32>) -> Self {
|
pub fn new(res_generation: u32) -> Self {
|
||||||
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 {
|
pub fn ap(generation: u32) -> ExecutedState {
|
||||||
let res_generations = option_to_vec(dst);
|
let ap_result = ApResult::new(generation);
|
||||||
let ap_result = ApResult::new(res_generations);
|
|
||||||
|
|
||||||
ExecutedState::Ap(ap_result)
|
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);
|
let canon_result = CanonResult::new(stream_elements_pos);
|
||||||
ExecutedState::Canon(canon_result)
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum MergerApResult {
|
pub enum MergerApResult {
|
||||||
/// There is no corresponding state in a trace for this call.
|
/// 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
|
/// There was a state in at least one of the contexts. If there were two states in
|
||||||
/// both contexts, they were successfully merged.
|
/// 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> {
|
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();
|
let current_state = data_keeper.current_slider_mut().next_state();
|
||||||
|
|
||||||
match (prev_state, current_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)), Some(Ap(_))) => prepare_merge_result(prev_ap, Both, data_keeper),
|
||||||
(Some(Ap(prev_ap)), None) => prepare_merge_result(Some(prev_ap), Previous, 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
|
// check that current state is Ap, but it's impossible to use it, because prev_data
|
||||||
// could not have streams with such generations
|
// could not have streams with such generations
|
||||||
(None, Some(Ap(_))) => prepare_merge_result(None, Current, data_keeper),
|
(None, Some(Ap(current_ap))) => prepare_merge_result(current_ap, Current, data_keeper),
|
||||||
(None, None) => Ok(MergerApResult::Empty),
|
(None, None) => Ok(MergerApResult::NotMet),
|
||||||
(prev_state, current_state) => Err(MergeError::incompatible_states(
|
(prev_state, current_state) => Err(MergeError::incompatible_states(
|
||||||
prev_state,
|
prev_state,
|
||||||
current_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 {
|
macro_rules! to_maybe_generation {
|
||||||
($ap_result:ident, $generations:expr, $error_ty:ident) => {
|
($ap_result:ident, $generations:expr, $error_ty:ident) => {
|
||||||
match $generations.len() {
|
match $generations.len() {
|
||||||
0 => None,
|
1 => $generations[0],
|
||||||
1 => Some($generations[0]),
|
|
||||||
_ => {
|
_ => {
|
||||||
let ap_error = super::ApResultError::$error_ty($ap_result);
|
let ap_error = super::ApResultError::$error_ty($ap_result);
|
||||||
return Err(super::MergeError::IncorrectApResult(ap_error));
|
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> {
|
fn prepare_merge_result(
|
||||||
let res_generation = to_maybe_generation!(ap_result, &ap_result.res_generations, TooManyDstGenerations);
|
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)
|
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
|
/// There was a state in at least one of the contexts. If there were two states in
|
||||||
/// both contexts, they were successfully merged.
|
/// both contexts, they were successfully merged.
|
||||||
Met(MetResult),
|
Met(MetCallResult),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MetResult {
|
pub struct MetCallResult {
|
||||||
pub result: CallResult,
|
pub result: CallResult,
|
||||||
pub trace_pos: TracePos,
|
pub trace_pos: TracePos,
|
||||||
pub source: ValueSource,
|
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> {
|
pub(crate) fn try_merge_next_state_as_call(data_keeper: &mut DataKeeper) -> MergeResult<MergerCallResult> {
|
||||||
use ExecutedState::Call;
|
use ExecutedState::Call;
|
||||||
use PreparationScheme::*;
|
use PreparationScheme::*;
|
||||||
@ -99,7 +93,7 @@ pub(super) fn prepare_call_result(
|
|||||||
let trace_pos = data_keeper.result_trace_next_pos();
|
let trace_pos = data_keeper.result_trace_next_pos();
|
||||||
prepare_positions_mapping(scheme, data_keeper);
|
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)
|
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 {
|
pub fn new(result: CallResult, trace_pos: TracePos, source: ValueSource) -> Self {
|
||||||
Self {
|
Self {
|
||||||
result,
|
result,
|
||||||
|
@ -55,9 +55,9 @@ pub enum MergeError {
|
|||||||
|
|
||||||
#[derive(ThisError, Debug)]
|
#[derive(ThisError, Debug)]
|
||||||
pub enum ApResultError {
|
pub enum ApResultError {
|
||||||
/// Error occurred when Ap results contains more then 1 generation in destination.
|
/// Error occurred when Ap results contains not 1 generation in destination.
|
||||||
#[error("{0:?} ap result contains too many generations in destination")]
|
#[error("{0:?} ap result contains inappropriate generation count in destination")]
|
||||||
TooManyDstGenerations(ApResult),
|
InvalidDstGenerations(ApResult),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(ThisError, Debug)]
|
#[derive(ThisError, Debug)]
|
||||||
|
@ -240,7 +240,7 @@ mod tests {
|
|||||||
|
|
||||||
let fold_result = FoldResult { lore };
|
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 ctx = MergeCtx { slider };
|
||||||
|
|
||||||
let (all_states, convoluted_lens) =
|
let (all_states, convoluted_lens) =
|
||||||
@ -285,9 +285,9 @@ mod tests {
|
|||||||
let fold_result = FoldResult { lore };
|
let fold_result = FoldResult { lore };
|
||||||
|
|
||||||
let slider = TraceSlider::new(vec![
|
let slider = TraceSlider::new(vec![
|
||||||
ExecutedState::Ap(ApResult::new(vec![0])),
|
ExecutedState::Ap(ApResult::new(0)),
|
||||||
ExecutedState::Ap(ApResult::new(vec![1])),
|
ExecutedState::Ap(ApResult::new(1)),
|
||||||
ExecutedState::Ap(ApResult::new(vec![2])),
|
ExecutedState::Ap(ApResult::new(2)),
|
||||||
]);
|
]);
|
||||||
let ctx = MergeCtx { slider };
|
let ctx = MergeCtx { slider };
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ mod par_merger;
|
|||||||
mod position_mapping;
|
mod position_mapping;
|
||||||
|
|
||||||
pub use ap_merger::MergerApResult;
|
pub use ap_merger::MergerApResult;
|
||||||
|
pub use ap_merger::MetApResult;
|
||||||
pub use call_merger::MergerCallResult;
|
pub use call_merger::MergerCallResult;
|
||||||
pub use call_merger::MetResult;
|
pub use call_merger::MetCallResult;
|
||||||
pub use call_merger::ValueSource;
|
|
||||||
pub use canon_merger::MergerCanonResult;
|
pub use canon_merger::MergerCanonResult;
|
||||||
pub use fold_merger::MergerFoldResult;
|
pub use fold_merger::MergerFoldResult;
|
||||||
pub use par_merger::MergerParResult;
|
pub use par_merger::MergerParResult;
|
||||||
@ -60,6 +60,12 @@ pub enum MergeCtxType {
|
|||||||
Previous,
|
Previous,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum ValueSource {
|
||||||
|
PreviousData,
|
||||||
|
CurrentData,
|
||||||
|
}
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
impl fmt::Display for MergeCtxType {
|
impl fmt::Display for MergeCtxType {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user