mirror of
https://github.com/fluencelabs/aquavm
synced 2025-04-24 14:52:15 +00:00
feat(all): reduce stream usage scope (#298)
This PR intended to reduce stream usage scope in order to make AquaVM truly deterministic. Refs: #297. Co-authored-by: Ivan Boldyrev <ivan@fluence.one> Co-authored-by: Anatoly Laskaris <github_me@nahsi.dev>
This commit is contained in:
parent
30967626e3
commit
9fe7afb897
@ -1,3 +1,11 @@
|
||||
## Version 0.32.0 (2022-11-25)
|
||||
|
||||
[PR 298](https://github.com/fluencelabs/aquavm/pull/298):
|
||||
Reduce stream scopes in order to prohibit nondeterministic behaviour
|
||||
|
||||
[PR 366](https://github.com/fluencelabs/aquavm/pull/366):
|
||||
Save order between current generations
|
||||
|
||||
## Version 0.31.0 (2022-10-11)
|
||||
|
||||
[PR 362](https://github.com/fluencelabs/aquavm/pull/362):
|
||||
|
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -13,7 +13,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "air"
|
||||
version = "0.31.2"
|
||||
version = "0.32.0"
|
||||
dependencies = [
|
||||
"air-execution-info-collector",
|
||||
"air-interpreter-data",
|
||||
@ -84,7 +84,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "air-interpreter"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
dependencies = [
|
||||
"air",
|
||||
"air-interpreter-interface",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "air-interpreter"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
description = "Crate-wrapper for air"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "air"
|
||||
version = "0.31.2"
|
||||
version = "0.32.0"
|
||||
description = "Interpreter of AIR scripts intended to coordinate request flow in the Fluence network"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
@ -38,7 +38,9 @@ pub(super) fn apply_to_arg(
|
||||
Boolean(value) => apply_const(*value, exec_ctx, trace_ctx),
|
||||
EmptyArray => apply_const(serde_json::json!([]), exec_ctx, trace_ctx),
|
||||
Scalar(scalar) => apply_scalar(scalar, exec_ctx, trace_ctx, should_touch_trace)?,
|
||||
ScalarWithLambda(scalar) => apply_scalar_wl(scalar, exec_ctx, trace_ctx)?,
|
||||
CanonStream(canon_stream) => apply_canon_stream(canon_stream, exec_ctx, trace_ctx)?,
|
||||
CanonStreamWithLambda(canon_stream) => apply_canon_stream_wl(canon_stream, exec_ctx, trace_ctx)?,
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
@ -67,27 +69,14 @@ fn apply_last_error<'i>(
|
||||
}
|
||||
|
||||
fn apply_scalar(
|
||||
scalar: &ast::ScalarWithLambda<'_>,
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
trace_ctx: &TraceHandler,
|
||||
should_touch_trace: bool,
|
||||
) -> ExecutionResult<ValueAggregate> {
|
||||
// TODO: refactor this code after boxed value
|
||||
match &scalar.lambda {
|
||||
Some(lambda) => apply_scalar_wl_impl(scalar.name, lambda, exec_ctx, trace_ctx),
|
||||
None => apply_scalar_impl(scalar.name, exec_ctx, trace_ctx, should_touch_trace),
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_scalar_impl(
|
||||
scalar_name: &str,
|
||||
ast_scalar: &ast::Scalar<'_>,
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
trace_ctx: &TraceHandler,
|
||||
should_touch_trace: bool,
|
||||
) -> ExecutionResult<ValueAggregate> {
|
||||
use crate::execution_step::ScalarRef;
|
||||
|
||||
let scalar = exec_ctx.scalars.get_value(scalar_name)?;
|
||||
let scalar = exec_ctx.scalars.get_value(ast_scalar.name)?;
|
||||
|
||||
let mut result = match scalar {
|
||||
ScalarRef::Value(result) => result.clone(),
|
||||
@ -104,14 +93,13 @@ fn apply_scalar_impl(
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn apply_scalar_wl_impl(
|
||||
scalar_name: &str,
|
||||
lambda: &LambdaAST<'_>,
|
||||
fn apply_scalar_wl(
|
||||
ast_scalar: &ast::ScalarWithLambda<'_>,
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
trace_ctx: &TraceHandler,
|
||||
) -> ExecutionResult<ValueAggregate> {
|
||||
let variable = Variable::scalar(scalar_name);
|
||||
let (jvalue, tetraplet) = apply_lambda(variable, lambda, exec_ctx)?;
|
||||
let variable = Variable::scalar(ast_scalar.name);
|
||||
let (jvalue, tetraplet) = apply_lambda(variable, &ast_scalar.lambda, exec_ctx)?;
|
||||
let tetraplet = Rc::new(tetraplet);
|
||||
let result = ValueAggregate::new(Rc::new(jvalue), tetraplet, trace_ctx.trace_pos());
|
||||
|
||||
@ -119,45 +107,32 @@ fn apply_scalar_wl_impl(
|
||||
}
|
||||
|
||||
fn apply_canon_stream(
|
||||
canon_stream: &ast::CanonStreamWithLambda<'_>,
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
trace_ctx: &TraceHandler,
|
||||
) -> ExecutionResult<ValueAggregate> {
|
||||
match &canon_stream.lambda {
|
||||
Some(lambda) => apply_canon_stream_with_lambda(canon_stream.name, lambda, exec_ctx, trace_ctx),
|
||||
None => apply_canon_stream_without_lambda(canon_stream.name, exec_ctx, trace_ctx),
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_canon_stream_with_lambda(
|
||||
stream_name: &str,
|
||||
lambda: &LambdaAST<'_>,
|
||||
ast_stream: &ast::CanonStream<'_>,
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
trace_ctx: &TraceHandler,
|
||||
) -> ExecutionResult<ValueAggregate> {
|
||||
// TODO: refactor this code after boxed value
|
||||
use crate::execution_step::boxed_value::JValuable;
|
||||
|
||||
let canon_stream = exec_ctx.scalars.get_canon_stream(stream_name)?;
|
||||
let (result, tetraplet) = JValuable::apply_lambda_with_tetraplets(&canon_stream, lambda, exec_ctx)?;
|
||||
let position = trace_ctx.trace_pos();
|
||||
|
||||
let value = ValueAggregate::new(Rc::new(result.into_owned()), Rc::new(tetraplet), position);
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn apply_canon_stream_without_lambda(
|
||||
stream_name: &str,
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
trace_ctx: &TraceHandler,
|
||||
) -> ExecutionResult<ValueAggregate> {
|
||||
use crate::execution_step::boxed_value::JValuable;
|
||||
|
||||
let canon_stream = exec_ctx.scalars.get_canon_stream(stream_name)?;
|
||||
// TODO: refactor this code after boxed value
|
||||
let canon_stream = exec_ctx.scalars.get_canon_stream(ast_stream.name)?;
|
||||
let value = JValuable::as_jvalue(&canon_stream).into_owned();
|
||||
let tetraplet = canon_stream.tetraplet().clone();
|
||||
let position = trace_ctx.trace_pos();
|
||||
let value = ValueAggregate::new(Rc::new(value), tetraplet, position);
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn apply_canon_stream_wl(
|
||||
ast_stream: &ast::CanonStreamWithLambda<'_>,
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
trace_ctx: &TraceHandler,
|
||||
) -> ExecutionResult<ValueAggregate> {
|
||||
// TODO: refactor this code after boxed value
|
||||
use crate::execution_step::boxed_value::JValuable;
|
||||
|
||||
let canon_stream = exec_ctx.scalars.get_canon_stream(ast_stream.name)?;
|
||||
let (result, tetraplet) = JValuable::apply_lambda_with_tetraplets(&canon_stream, &ast_stream.lambda, exec_ctx)?;
|
||||
let position = trace_ctx.trace_pos();
|
||||
let value = ValueAggregate::new(Rc::new(result.into_owned()), Rc::new(tetraplet), position);
|
||||
Ok(value)
|
||||
}
|
||||
|
@ -40,11 +40,11 @@ impl<'i> super::ExecutableInstruction<'i> for Call<'i> {
|
||||
log_instruction!(call, exec_ctx, trace_ctx);
|
||||
exec_ctx.tracker.meet_call();
|
||||
|
||||
let resolved_call = joinable!(ResolvedCall::new(self, exec_ctx), exec_ctx)
|
||||
let resolved_call = joinable!(ResolvedCall::new(self, exec_ctx), exec_ctx, ())
|
||||
.map_err(|e| set_last_error(self, exec_ctx, e, None))?;
|
||||
|
||||
let tetraplet = resolved_call.as_tetraplet();
|
||||
joinable!(resolved_call.execute(self, exec_ctx, trace_ctx), exec_ctx)
|
||||
joinable!(resolved_call.execute(self, exec_ctx, trace_ctx), exec_ctx, ())
|
||||
.map_err(|e| set_last_error(self, exec_ctx, e, Some(tetraplet)))
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ use std::rc::Rc;
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub(super) struct ResolvedCall<'i> {
|
||||
tetraplet: RcSecurityTetraplet,
|
||||
function_arg_paths: Rc<Vec<ast::Value<'i>>>,
|
||||
function_arg_paths: Rc<Vec<ast::ImmutableValue<'i>>>,
|
||||
output: ast::CallOutputValue<'i>,
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,12 @@ use polyplets::ResolvedTriplet;
|
||||
/// Resolve variables, literals, etc in the `Triplet`, and build a `ResolvedTriplet`.
|
||||
pub(crate) fn resolve<'i>(triplet: &ast::Triplet<'i>, ctx: &ExecutionCtx<'i>) -> ExecutionResult<ResolvedTriplet> {
|
||||
let ast::Triplet {
|
||||
peer_pk,
|
||||
peer_id: peer_pk,
|
||||
service_id,
|
||||
function_name,
|
||||
} = triplet;
|
||||
|
||||
let peer_pk = resolve_to_string(peer_pk, ctx)?;
|
||||
let peer_pk = resolve_peer_id_to_string(peer_pk, ctx)?;
|
||||
let service_id = resolve_to_string(service_id, ctx)?;
|
||||
let function_name = resolve_to_string(function_name, ctx)?;
|
||||
|
||||
@ -41,33 +41,58 @@ pub(crate) fn resolve<'i>(triplet: &ast::Triplet<'i>, ctx: &ExecutionCtx<'i>) ->
|
||||
})
|
||||
}
|
||||
|
||||
/// Resolve peer id to string by either resolving variable from `ExecutionCtx`, taking literal value, or etc.
|
||||
// TODO: return Rc<String> to avoid excess cloning
|
||||
// TODO: move this function into resolve in boxed value PR
|
||||
pub(crate) fn resolve_peer_id_to_string<'i>(
|
||||
value: &ast::ResolvableToPeerIdVariable<'i>,
|
||||
exec_ctx: &ExecutionCtx<'i>,
|
||||
) -> ExecutionResult<String> {
|
||||
use crate::execution_step::resolver;
|
||||
use ast::ResolvableToPeerIdVariable::*;
|
||||
|
||||
let ((jvalue, _), name) = match value {
|
||||
InitPeerId => return Ok(exec_ctx.run_parameters.init_peer_id.to_string()),
|
||||
Literal(value) => return Ok(value.to_string()),
|
||||
Scalar(scalar) => (resolver::resolve_ast_scalar(scalar, exec_ctx)?, scalar.name),
|
||||
ScalarWithLambda(scalar) => (resolver::resolve_ast_scalar_wl(scalar, exec_ctx)?, scalar.name),
|
||||
CanonStreamWithLambda(canon_stream) => (
|
||||
resolver::resolve_ast_canon_wl(canon_stream, exec_ctx)?,
|
||||
canon_stream.name,
|
||||
),
|
||||
};
|
||||
|
||||
try_jvalue_to_string(jvalue, name)
|
||||
}
|
||||
|
||||
/// Resolve value to string by either resolving variable from `ExecutionCtx`, taking literal value, or etc.
|
||||
// TODO: return Rc<String> to avoid excess cloning
|
||||
// TODO: move this function into resolve in boxed value PR
|
||||
pub(crate) fn resolve_to_string<'i>(
|
||||
value: &ast::CallInstrValue<'i>,
|
||||
ctx: &ExecutionCtx<'i>,
|
||||
value: &ast::ResolvableToStringVariable<'i>,
|
||||
exec_ctx: &ExecutionCtx<'i>,
|
||||
) -> ExecutionResult<String> {
|
||||
use crate::execution_step::resolver::resolve_ast_variable_wl;
|
||||
use ast::CallInstrValue::*;
|
||||
use crate::execution_step::resolver;
|
||||
use ast::ResolvableToStringVariable::*;
|
||||
|
||||
let resolved = match value {
|
||||
InitPeerId => ctx.run_parameters.init_peer_id.to_string(),
|
||||
Literal(value) => value.to_string(),
|
||||
Variable(variable) => {
|
||||
let (resolved, _) = resolve_ast_variable_wl(variable, ctx)?;
|
||||
try_jvalue_to_string(resolved, variable)?
|
||||
}
|
||||
let ((jvalue, _), name) = match value {
|
||||
Literal(value) => return Ok(value.to_string()),
|
||||
Scalar(scalar) => (resolver::resolve_ast_scalar(scalar, exec_ctx)?, scalar.name),
|
||||
ScalarWithLambda(scalar) => (resolver::resolve_ast_scalar_wl(scalar, exec_ctx)?, scalar.name),
|
||||
CanonStreamWithLambda(canon_stream) => (
|
||||
resolver::resolve_ast_canon_wl(canon_stream, exec_ctx)?,
|
||||
canon_stream.name,
|
||||
),
|
||||
};
|
||||
|
||||
Ok(resolved)
|
||||
try_jvalue_to_string(jvalue, name)
|
||||
}
|
||||
|
||||
fn try_jvalue_to_string(jvalue: JValue, variable: &ast::VariableWithLambda<'_>) -> ExecutionResult<String> {
|
||||
fn try_jvalue_to_string(jvalue: JValue, variable_name: impl Into<String>) -> ExecutionResult<String> {
|
||||
match jvalue {
|
||||
JValue::String(s) => Ok(s),
|
||||
_ => Err(CatchableError::IncompatibleJValueType {
|
||||
variable_name: variable.name().to_string(),
|
||||
variable_name: variable_name.into(),
|
||||
actual_value: jvalue,
|
||||
expected_value_type: "string",
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ fn handle_unseen_canon(
|
||||
exec_ctx: &mut ExecutionCtx<'_>,
|
||||
trace_ctx: &mut TraceHandler,
|
||||
) -> ExecutionResult<()> {
|
||||
let peer_id = crate::execution_step::air::resolve_to_string(&ast_canon.peer_pk, exec_ctx)?;
|
||||
let peer_id = crate::execution_step::air::resolve_peer_id_to_string(&ast_canon.peer_id, exec_ctx)?;
|
||||
|
||||
if exec_ctx.run_parameters.current_peer_id.as_str() != peer_id {
|
||||
exec_ctx.subgraph_complete = false;
|
||||
|
@ -17,20 +17,24 @@
|
||||
use crate::execution_step::air::ExecutionResult;
|
||||
use crate::execution_step::execution_context::ExecutionCtx;
|
||||
use crate::execution_step::resolver::prepare_last_error;
|
||||
use crate::execution_step::resolver::resolve_ast_variable;
|
||||
use crate::execution_step::resolver::resolve_ast_variable_wl;
|
||||
use crate::JValue;
|
||||
|
||||
use air_parser::ast;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) fn are_matchable_eq<'ctx>(
|
||||
left: &ast::Value<'_>,
|
||||
right: &ast::Value<'_>,
|
||||
left: &ast::ImmutableValue<'_>,
|
||||
right: &ast::ImmutableValue<'_>,
|
||||
exec_ctx: &'ctx ExecutionCtx<'_>,
|
||||
) -> ExecutionResult<bool> {
|
||||
use ast::Value::*;
|
||||
use ast::ImmutableValue::*;
|
||||
|
||||
match (left, right) {
|
||||
// TODO: introduce traits to refactor this in boxed values
|
||||
(InitPeerId, InitPeerId) => Ok(true),
|
||||
(InitPeerId, matchable) | (matchable, InitPeerId) => compare_matchable(
|
||||
matchable,
|
||||
@ -78,6 +82,27 @@ pub(crate) fn are_matchable_eq<'ctx>(
|
||||
}
|
||||
|
||||
(Variable(left_variable), Variable(right_variable)) => {
|
||||
let (left_value, _) = resolve_ast_variable(left_variable, exec_ctx)?;
|
||||
let (right_value, _) = resolve_ast_variable(right_variable, exec_ctx)?;
|
||||
|
||||
Ok(left_value == right_value)
|
||||
}
|
||||
|
||||
(Variable(left_variable), VariableWithLambda(right_variable)) => {
|
||||
let (left_value, _) = resolve_ast_variable(left_variable, exec_ctx)?;
|
||||
let (right_value, _) = resolve_ast_variable_wl(right_variable, exec_ctx)?;
|
||||
|
||||
Ok(left_value == right_value)
|
||||
}
|
||||
|
||||
(VariableWithLambda(left_variable), Variable(right_variable)) => {
|
||||
let (left_value, _) = resolve_ast_variable_wl(left_variable, exec_ctx)?;
|
||||
let (right_value, _) = resolve_ast_variable(right_variable, exec_ctx)?;
|
||||
|
||||
Ok(left_value == right_value)
|
||||
}
|
||||
|
||||
(VariableWithLambda(left_variable), VariableWithLambda(right_variable)) => {
|
||||
let (left_value, _) = resolve_ast_variable_wl(left_variable, exec_ctx)?;
|
||||
let (right_value, _) = resolve_ast_variable_wl(right_variable, exec_ctx)?;
|
||||
|
||||
@ -86,15 +111,14 @@ pub(crate) fn are_matchable_eq<'ctx>(
|
||||
}
|
||||
}
|
||||
|
||||
use std::borrow::Cow;
|
||||
type Comparator<'a> = Box<dyn Fn(Cow<'_, JValue>) -> bool + 'a>;
|
||||
|
||||
fn compare_matchable<'ctx>(
|
||||
matchable: &ast::Value<'_>,
|
||||
matchable: &ast::ImmutableValue<'_>,
|
||||
exec_ctx: &'ctx ExecutionCtx<'_>,
|
||||
comparator: Comparator<'ctx>,
|
||||
) -> ExecutionResult<bool> {
|
||||
use ast::Value::*;
|
||||
use ast::ImmutableValue::*;
|
||||
|
||||
match matchable {
|
||||
InitPeerId => {
|
||||
@ -131,6 +155,10 @@ fn compare_matchable<'ctx>(
|
||||
Ok(comparator(Cow::Owned(jvalue)))
|
||||
}
|
||||
Variable(variable) => {
|
||||
let (jvalue, _) = resolve_ast_variable(variable, exec_ctx)?;
|
||||
Ok(comparator(Cow::Owned(jvalue)))
|
||||
}
|
||||
VariableWithLambda(variable) => {
|
||||
let (jvalue, _) = resolve_ast_variable_wl(variable, exec_ctx)?;
|
||||
Ok(comparator(Cow::Owned(jvalue)))
|
||||
}
|
||||
|
@ -17,8 +17,9 @@
|
||||
use super::ExecutionCtx;
|
||||
use super::ExecutionResult;
|
||||
use super::TraceHandler;
|
||||
use crate::execution_step::boxed_value::Variable;
|
||||
use crate::execution_step::execution_context::check_error_object;
|
||||
use crate::execution_step::resolver::{apply_lambda, resolve_ast_scalar_wl};
|
||||
use crate::execution_step::resolver;
|
||||
use crate::execution_step::CatchableError;
|
||||
use crate::execution_step::LastError;
|
||||
use crate::execution_step::RcSecurityTetraplet;
|
||||
@ -30,8 +31,6 @@ use air_parser::ast;
|
||||
use air_parser::ast::Fail;
|
||||
use polyplets::SecurityTetraplet;
|
||||
|
||||
use crate::execution_step::boxed_value::Variable;
|
||||
use air_lambda_ast::LambdaAST;
|
||||
use std::rc::Rc;
|
||||
|
||||
impl<'i> super::ExecutableInstruction<'i> for Fail<'i> {
|
||||
@ -40,19 +39,29 @@ impl<'i> super::ExecutableInstruction<'i> for Fail<'i> {
|
||||
|
||||
match self {
|
||||
Fail::Scalar(scalar) => fail_with_scalar(scalar, exec_ctx),
|
||||
Fail::ScalarWithLambda(scalar) => fail_with_scalar_wl(scalar, exec_ctx),
|
||||
&Fail::Literal {
|
||||
ret_code,
|
||||
error_message,
|
||||
} => fail_with_literals(ret_code, error_message, self, exec_ctx),
|
||||
Fail::CanonStream { name, lambda } => fail_with_canon_stream(name, lambda, exec_ctx),
|
||||
Fail::CanonStreamWithLambda(canon_stream) => fail_with_canon_stream(canon_stream, exec_ctx),
|
||||
// bubble last error up
|
||||
Fail::LastError => fail_with_last_error(exec_ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fail_with_scalar<'i>(scalar: &ast::ScalarWithLambda<'i>, exec_ctx: &mut ExecutionCtx<'i>) -> ExecutionResult<()> {
|
||||
let (value, mut tetraplet) = resolve_ast_scalar_wl(scalar, exec_ctx)?;
|
||||
fn fail_with_scalar<'i>(scalar: &ast::Scalar<'i>, exec_ctx: &mut ExecutionCtx<'i>) -> ExecutionResult<()> {
|
||||
let (value, mut tetraplet) = resolver::resolve_ast_scalar(scalar, exec_ctx)?;
|
||||
// tetraplets always have one element here and it'll be refactored after boxed value
|
||||
let tetraplet = tetraplet.remove(0);
|
||||
check_error_object(&value).map_err(CatchableError::InvalidLastErrorObjectError)?;
|
||||
|
||||
fail_with_error_object(exec_ctx, Rc::new(value), Some(tetraplet))
|
||||
}
|
||||
|
||||
fn fail_with_scalar_wl<'i>(scalar: &ast::ScalarWithLambda<'i>, exec_ctx: &mut ExecutionCtx<'i>) -> ExecutionResult<()> {
|
||||
let (value, mut tetraplet) = resolver::resolve_ast_scalar_wl(scalar, exec_ctx)?;
|
||||
// tetraplets always have one element here and it'll be refactored after boxed value
|
||||
let tetraplet = tetraplet.remove(0);
|
||||
check_error_object(&value).map_err(CatchableError::InvalidLastErrorObjectError)?;
|
||||
@ -79,14 +88,13 @@ fn fail_with_literals(
|
||||
fail_with_error_object(exec_ctx, Rc::new(error_object), Some(literal_tetraplet))
|
||||
}
|
||||
|
||||
fn fail_with_canon_stream<'i>(
|
||||
name: &'i str,
|
||||
lambda: &LambdaAST<'i>,
|
||||
exec_ctx: &mut ExecutionCtx<'i>,
|
||||
fn fail_with_canon_stream(
|
||||
ast_canon: &ast::CanonStreamWithLambda<'_>,
|
||||
exec_ctx: &mut ExecutionCtx<'_>,
|
||||
) -> ExecutionResult<()> {
|
||||
let variable = Variable::CanonStream { name };
|
||||
let variable = Variable::CanonStream { name: ast_canon.name };
|
||||
|
||||
let (value, tetraplet) = apply_lambda(variable, lambda, exec_ctx)?;
|
||||
let (value, tetraplet) = resolver::apply_lambda(variable, &ast_canon.lambda, exec_ctx)?;
|
||||
// tetraplets always have one element here and it'll be refactored after boxed value
|
||||
check_error_object(&value).map_err(CatchableError::InvalidLastErrorObjectError)?;
|
||||
|
||||
|
@ -37,19 +37,48 @@ pub(crate) enum FoldIterableScalar {
|
||||
ScalarBased(IterableValue),
|
||||
}
|
||||
|
||||
/// Constructs iterable value for given scalar iterable.
|
||||
pub(crate) fn construct_scalar_iterable_value<'ctx>(
|
||||
iterable: &ast::ScalarWithLambda<'ctx>,
|
||||
exec_ctx: &ExecutionCtx<'ctx>,
|
||||
/// Creates iterable value for given scalar iterable.
|
||||
pub(crate) fn create_scalar_iterable(
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
variable_name: &str,
|
||||
) -> ExecutionResult<FoldIterableScalar> {
|
||||
match &iterable.lambda {
|
||||
None => create_scalar_iterable(exec_ctx, iterable.name),
|
||||
Some(lambda) => create_scalar_lambda_iterable(exec_ctx, iterable.name, lambda),
|
||||
match exec_ctx.scalars.get_value(variable_name)? {
|
||||
ScalarRef::Value(call_result) => from_value(call_result.clone(), variable_name),
|
||||
ScalarRef::IterableValue(fold_state) => {
|
||||
let iterable_value = fold_state.iterable.peek().expect(PEEK_ALLOWED_ON_NON_EMPTY);
|
||||
let call_result = iterable_value.into_resolved_result();
|
||||
from_value(call_result, variable_name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs iterable value for given canon stream.
|
||||
pub(crate) fn construct_canon_stream_iterable_value<'ctx>(
|
||||
/// Creates iterable value for given scalar with lambda iterable.
|
||||
pub(crate) fn create_scalar_wl_iterable<'ctx>(
|
||||
scalar_iterable: &ast::ScalarWithLambda<'ctx>,
|
||||
exec_ctx: &ExecutionCtx<'ctx>,
|
||||
) -> ExecutionResult<FoldIterableScalar> {
|
||||
use crate::execution_step::lambda_applier::select_by_lambda_from_scalar;
|
||||
let scalar_name = scalar_iterable.name;
|
||||
let lambda = &scalar_iterable.lambda;
|
||||
|
||||
match exec_ctx.scalars.get_value(scalar_name)? {
|
||||
ScalarRef::Value(variable) => {
|
||||
let jvalues = select_by_lambda_from_scalar(&variable.result, lambda, exec_ctx)?;
|
||||
let tetraplet = variable.tetraplet.deref().clone();
|
||||
from_jvalue(jvalues, tetraplet, lambda)
|
||||
}
|
||||
ScalarRef::IterableValue(fold_state) => {
|
||||
let iterable_value = fold_state.iterable.peek().unwrap();
|
||||
let jvalue = iterable_value.apply_lambda(lambda, exec_ctx)?;
|
||||
let tetraplet = to_tetraplet(&iterable_value);
|
||||
|
||||
from_jvalue(jvalue, tetraplet, lambda)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates iterable value for given canon stream.
|
||||
pub(crate) fn create_canon_stream_iterable_value<'ctx>(
|
||||
ast_canon_stream: &ast::CanonStream<'ctx>,
|
||||
exec_ctx: &ExecutionCtx<'ctx>,
|
||||
) -> ExecutionResult<FoldIterableScalar> {
|
||||
@ -86,17 +115,6 @@ pub(crate) fn construct_stream_iterable_values(
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn create_scalar_iterable(exec_ctx: &ExecutionCtx<'_>, variable_name: &str) -> ExecutionResult<FoldIterableScalar> {
|
||||
match exec_ctx.scalars.get_value(variable_name)? {
|
||||
ScalarRef::Value(call_result) => from_value(call_result.clone(), variable_name),
|
||||
ScalarRef::IterableValue(fold_state) => {
|
||||
let iterable_value = fold_state.iterable.peek().expect(PEEK_ALLOWED_ON_NON_EMPTY);
|
||||
let call_result = iterable_value.into_resolved_result();
|
||||
from_value(call_result, variable_name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs iterable value from resolved call result.
|
||||
fn from_value(call_result: ValueAggregate, variable_name: &str) -> ExecutionResult<FoldIterableScalar> {
|
||||
let len = match &call_result.result.deref() {
|
||||
@ -124,29 +142,6 @@ fn from_value(call_result: ValueAggregate, variable_name: &str) -> ExecutionResu
|
||||
Ok(iterable)
|
||||
}
|
||||
|
||||
fn create_scalar_lambda_iterable(
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
scalar_name: &str,
|
||||
lambda: &LambdaAST<'_>,
|
||||
) -> ExecutionResult<FoldIterableScalar> {
|
||||
use crate::execution_step::lambda_applier::select_by_lambda_from_scalar;
|
||||
|
||||
match exec_ctx.scalars.get_value(scalar_name)? {
|
||||
ScalarRef::Value(variable) => {
|
||||
let jvalues = select_by_lambda_from_scalar(&variable.result, lambda, exec_ctx)?;
|
||||
let tetraplet = variable.tetraplet.deref().clone();
|
||||
from_jvalue(jvalues, tetraplet, lambda)
|
||||
}
|
||||
ScalarRef::IterableValue(fold_state) => {
|
||||
let iterable_value = fold_state.iterable.peek().expect(PEEK_ALLOWED_ON_NON_EMPTY);
|
||||
let jvalue = iterable_value.apply_lambda(lambda, exec_ctx)?;
|
||||
let tetraplet = to_tetraplet(&iterable_value);
|
||||
|
||||
from_jvalue(jvalue, tetraplet, lambda)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct IterableValue from the result and given triplet.
|
||||
fn from_jvalue(
|
||||
jvalue: Cow<'_, JValue>,
|
||||
|
@ -35,10 +35,13 @@ impl<'i> ExecutableInstruction<'i> for FoldScalar<'i> {
|
||||
|
||||
let iterable = match &self.iterable {
|
||||
FoldScalarIterable::Scalar(scalar) => {
|
||||
joinable!(construct_scalar_iterable_value(scalar, exec_ctx), exec_ctx)?
|
||||
joinable!(create_scalar_iterable(exec_ctx, scalar.name), exec_ctx, ())?
|
||||
}
|
||||
FoldScalarIterable::ScalarWithLambda(scalar) => {
|
||||
joinable!(create_scalar_wl_iterable(scalar, exec_ctx), exec_ctx, ())?
|
||||
}
|
||||
FoldScalarIterable::CanonStream(canon_stream) => {
|
||||
joinable!(construct_canon_stream_iterable_value(canon_stream, exec_ctx), exec_ctx)?
|
||||
joinable!(create_canon_stream_iterable_value(canon_stream, exec_ctx), exec_ctx, ())?
|
||||
}
|
||||
// just do nothing on an empty array
|
||||
FoldScalarIterable::EmptyArray => return Ok(()),
|
||||
|
@ -31,7 +31,8 @@ impl<'i> super::ExecutableInstruction<'i> for Match<'i> {
|
||||
|
||||
let are_values_equal = joinable!(
|
||||
are_matchable_eq(&self.left_value, &self.right_value, exec_ctx),
|
||||
exec_ctx
|
||||
exec_ctx,
|
||||
()
|
||||
)?;
|
||||
|
||||
if !are_values_equal {
|
||||
|
@ -31,7 +31,8 @@ impl<'i> super::ExecutableInstruction<'i> for MisMatch<'i> {
|
||||
|
||||
let are_values_equal = joinable!(
|
||||
are_matchable_eq(&self.left_value, &self.right_value, exec_ctx),
|
||||
exec_ctx
|
||||
exec_ctx,
|
||||
()
|
||||
)?;
|
||||
|
||||
if are_values_equal {
|
||||
|
@ -32,7 +32,7 @@ mod par;
|
||||
mod seq;
|
||||
mod xor;
|
||||
|
||||
pub(crate) use call::triplet::resolve_to_string;
|
||||
pub(crate) use call::triplet::resolve_peer_id_to_string;
|
||||
pub(crate) use fold::FoldState;
|
||||
|
||||
use super::boxed_value::ScalarRef;
|
||||
@ -141,11 +141,11 @@ macro_rules! log_instruction {
|
||||
/// This macro converts joinable errors to Ok and sets subgraph complete to false.
|
||||
#[macro_export]
|
||||
macro_rules! joinable {
|
||||
($cmd:expr, $exec_ctx:expr) => {
|
||||
($cmd:expr, $exec_ctx:expr, $ok_result:expr) => {
|
||||
match $cmd {
|
||||
Err(e) if e.is_joinable() => {
|
||||
$exec_ctx.subgraph_complete = false;
|
||||
return Ok(());
|
||||
return Ok($ok_result);
|
||||
}
|
||||
v => v,
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ pub(crate) enum Variable<'i> {
|
||||
Scalar {
|
||||
name: &'i str,
|
||||
},
|
||||
#[allow(dead_code)] // it will be used in BoxedValues
|
||||
Stream {
|
||||
name: &'i str,
|
||||
generation: Generation,
|
||||
@ -37,38 +38,28 @@ impl<'i> Variable<'i> {
|
||||
Self::Scalar { name }
|
||||
}
|
||||
|
||||
pub(crate) fn stream(name: &'i str, generation: Generation, position: AirPos) -> Self {
|
||||
Self::Stream {
|
||||
name,
|
||||
generation,
|
||||
position,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn canon_stream(name: &'i str) -> Self {
|
||||
Self::CanonStream { name }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i> From<&ast::Variable<'i>> for Variable<'i> {
|
||||
fn from(ast_variable: &ast::Variable<'i>) -> Self {
|
||||
use ast::Variable::*;
|
||||
impl<'i> From<&ast::ImmutableVariable<'i>> for Variable<'i> {
|
||||
fn from(ast_variable: &ast::ImmutableVariable<'i>) -> Self {
|
||||
use ast::ImmutableVariable::*;
|
||||
|
||||
match ast_variable {
|
||||
Scalar(scalar) => Self::scalar(scalar.name),
|
||||
Stream(stream) => Self::stream(stream.name, Generation::Last, stream.position),
|
||||
CanonStream(canon_stream) => Self::canon_stream(canon_stream.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i> From<&ast::VariableWithLambda<'i>> for Variable<'i> {
|
||||
fn from(ast_variable: &ast::VariableWithLambda<'i>) -> Self {
|
||||
use ast::VariableWithLambda::*;
|
||||
impl<'i> From<&ast::ImmutableVariableWithLambda<'i>> for Variable<'i> {
|
||||
fn from(ast_variable: &ast::ImmutableVariableWithLambda<'i>) -> Self {
|
||||
use ast::ImmutableVariableWithLambda::*;
|
||||
|
||||
match ast_variable {
|
||||
Scalar(scalar) => Self::scalar(scalar.name),
|
||||
Stream(stream) => Self::stream(stream.name, Generation::Last, stream.position),
|
||||
CanonStream(canon_stream) => Self::canon_stream(canon_stream.name),
|
||||
}
|
||||
}
|
||||
|
@ -31,10 +31,10 @@ use std::rc::Rc;
|
||||
|
||||
/// Resolve value to called function arguments.
|
||||
pub(crate) fn resolve_to_args<'i>(
|
||||
value: &ast::Value<'i>,
|
||||
value: &ast::ImmutableValue<'i>,
|
||||
ctx: &ExecutionCtx<'i>,
|
||||
) -> ExecutionResult<(JValue, RcSecurityTetraplets)> {
|
||||
use ast::Value::*;
|
||||
use ast::ImmutableValue::*;
|
||||
|
||||
match value {
|
||||
InitPeerId => prepare_const(ctx.run_parameters.init_peer_id.as_str(), ctx),
|
||||
@ -45,7 +45,8 @@ pub(crate) fn resolve_to_args<'i>(
|
||||
Boolean(value) => prepare_const(*value, ctx),
|
||||
Number(value) => prepare_const(value, ctx),
|
||||
EmptyArray => prepare_const(json!([]), ctx),
|
||||
Variable(variable) => resolve_ast_variable_wl(variable, ctx),
|
||||
Variable(variable) => resolve_ast_variable(variable, ctx),
|
||||
VariableWithLambda(variable) => resolve_ast_variable_wl(variable, ctx),
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,22 +120,37 @@ pub(crate) fn resolve_variable<'ctx, 'i>(
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(exec_ctx))]
|
||||
pub(crate) fn resolve_ast_variable_wl<'ctx, 'i>(
|
||||
ast_variable: &ast::VariableWithLambda<'_>,
|
||||
pub(crate) fn resolve_ast_variable<'ctx, 'i>(
|
||||
ast_variable: &ast::ImmutableVariable<'_>,
|
||||
exec_ctx: &'ctx ExecutionCtx<'i>,
|
||||
) -> ExecutionResult<(JValue, RcSecurityTetraplets)> {
|
||||
let variable: Variable<'_> = ast_variable.into();
|
||||
match ast_variable.lambda() {
|
||||
Some(lambda) => apply_lambda(variable, lambda, exec_ctx).map(|(value, tetraplet)| {
|
||||
let tetraplet = Rc::new(tetraplet);
|
||||
(value, vec![tetraplet])
|
||||
}),
|
||||
None => {
|
||||
let value = resolve_variable(variable, exec_ctx)?;
|
||||
let tetraplets = value.as_tetraplets();
|
||||
Ok((value.into_jvalue(), tetraplets))
|
||||
}
|
||||
}
|
||||
let value = resolve_variable(variable, exec_ctx)?;
|
||||
let tetraplets = value.as_tetraplets();
|
||||
Ok((value.into_jvalue(), tetraplets))
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(exec_ctx))]
|
||||
pub(crate) fn resolve_ast_variable_wl<'ctx, 'i>(
|
||||
ast_variable: &ast::ImmutableVariableWithLambda<'_>,
|
||||
exec_ctx: &'ctx ExecutionCtx<'i>,
|
||||
) -> ExecutionResult<(JValue, RcSecurityTetraplets)> {
|
||||
let variable: Variable<'_> = ast_variable.into();
|
||||
|
||||
apply_lambda(variable, ast_variable.lambda(), exec_ctx).map(|(value, tetraplet)| {
|
||||
let tetraplet = Rc::new(tetraplet);
|
||||
(value, vec![tetraplet])
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(exec_ctx))]
|
||||
pub(crate) fn resolve_ast_scalar<'ctx, 'i>(
|
||||
ast_scalar: &ast::Scalar<'_>,
|
||||
exec_ctx: &'ctx ExecutionCtx<'i>,
|
||||
) -> ExecutionResult<(JValue, RcSecurityTetraplets)> {
|
||||
// TODO: wrap lambda path with Rc to make this clone cheaper
|
||||
let variable = ast::ImmutableVariable::Scalar(ast_scalar.clone());
|
||||
resolve_ast_variable(&variable, exec_ctx)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(exec_ctx))]
|
||||
@ -143,7 +159,17 @@ pub(crate) fn resolve_ast_scalar_wl<'ctx, 'i>(
|
||||
exec_ctx: &'ctx ExecutionCtx<'i>,
|
||||
) -> ExecutionResult<(JValue, RcSecurityTetraplets)> {
|
||||
// TODO: wrap lambda path with Rc to make this clone cheaper
|
||||
let variable = ast::VariableWithLambda::Scalar(ast_scalar.clone());
|
||||
let variable = ast::ImmutableVariableWithLambda::Scalar(ast_scalar.clone());
|
||||
resolve_ast_variable_wl(&variable, exec_ctx)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(exec_ctx))]
|
||||
pub(crate) fn resolve_ast_canon_wl<'ctx, 'i>(
|
||||
ast_canon: &ast::CanonStreamWithLambda<'_>,
|
||||
exec_ctx: &'ctx ExecutionCtx<'i>,
|
||||
) -> ExecutionResult<(JValue, RcSecurityTetraplets)> {
|
||||
// TODO: wrap lambda path with Rc to make this clone cheaper
|
||||
let variable = ast::ImmutableVariableWithLambda::CanonStream(ast_canon.clone());
|
||||
resolve_ast_variable_wl(&variable, exec_ctx)
|
||||
}
|
||||
|
||||
|
@ -178,9 +178,15 @@ fn stream_merge() {
|
||||
(call "A" ("get_providers" "") [] $providers)
|
||||
(seq
|
||||
(call "A" ("get_providers" "") [] $providers)
|
||||
(seq
|
||||
(call "B" ("" "2") [$providers] $void)
|
||||
(call "B" ("" "3") [$void] $void)
|
||||
(seq
|
||||
(seq
|
||||
(canon "B" $providers #providers)
|
||||
(call "B" ("" "2") [#providers] $void)
|
||||
)
|
||||
(seq
|
||||
(canon "B" $void #void)
|
||||
(call "B" ("" "3") [#void] $void)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -64,34 +64,6 @@ fn dont_wait_on_json_path() {
|
||||
assert_eq!(result.next_peer_pks, vec![test_params.init_peer_id.to_string()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wait_on_stream_json_path_by_id() {
|
||||
let local_peer_id = "local_peer_id";
|
||||
let mut local_vm = create_avm(unit_call_service(), local_peer_id);
|
||||
|
||||
let non_join_stream_script = f!(r#"
|
||||
(par
|
||||
(call "{local_peer_id}" ("" "") [] $status)
|
||||
(call "{local_peer_id}" ("history" "add") [$status.$[0]!])
|
||||
)"#);
|
||||
|
||||
let result = checked_call_vm!(local_vm, <_>::default(), non_join_stream_script, "", "");
|
||||
let actual_trace = trace_from_result(&result);
|
||||
|
||||
assert_eq!(actual_trace.len(), 3);
|
||||
|
||||
let join_stream_script = f!(r#"
|
||||
(par
|
||||
(call "{local_peer_id}" ("" "") [] $status)
|
||||
(call "{local_peer_id}" ("history" "add") [$status.$[1]!]) ; $status stream here has only one value
|
||||
)"#);
|
||||
|
||||
let result = checked_call_vm!(local_vm, <_>::default(), join_stream_script, "", "");
|
||||
let actual_trace = trace_from_result(&result);
|
||||
|
||||
assert_eq!(actual_trace.len(), 2); // par and the first call emit traces, second call doesn't
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wait_on_empty_stream_json_path() {
|
||||
let local_peer_id = "local_peer_id";
|
||||
@ -108,13 +80,17 @@ fn wait_on_empty_stream_json_path() {
|
||||
)
|
||||
)
|
||||
)
|
||||
(call "{local_peer_id}" ("" "") [$ns.$.[0] $ns.$.[1] $ns])
|
||||
(seq
|
||||
(canon "{local_peer_id}" $ns #ns)
|
||||
(call "{local_peer_id}" ("" "") [#ns.$.[0] #ns.$.[1] #ns])
|
||||
)
|
||||
)"#);
|
||||
|
||||
let result = checked_call_vm!(local_vm, <_>::default(), join_stream_script, "", "");
|
||||
print_trace(&result, "");
|
||||
let actual_trace = trace_from_result(&result);
|
||||
|
||||
assert_eq!(actual_trace.len(), 1); // only the first call should produce a trace
|
||||
assert_eq!(actual_trace.len(), 2); // only the first call and canon should produce a trace
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -249,26 +225,19 @@ fn fold_with_join_behaviour() {
|
||||
|
||||
#[test]
|
||||
fn canon_with_empty_behaviour() {
|
||||
let peer_1_id = "peer_1_id";
|
||||
let peer_2_id = "peer_2_id";
|
||||
let peer_id = "peer_id";
|
||||
|
||||
let mut peer_2 = create_avm(unit_call_service(), peer_2_id);
|
||||
let mut peer_2 = create_avm(unit_call_service(), peer_id);
|
||||
|
||||
let script = f!(r#"
|
||||
(par
|
||||
(call "{peer_1_id}" ("" "") [] $stream)
|
||||
(canon "{peer_2_id}" $stream #canon_stream))
|
||||
(canon "{peer_id}" $stream #canon_stream)
|
||||
"#);
|
||||
|
||||
let result = checked_call_vm!(peer_2, <_>::default(), script, "", "");
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_trace = vec![
|
||||
executed_state::par(1, 1),
|
||||
executed_state::request_sent_by(peer_2_id),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_2_id", "service_id": ""}, "values": []}),
|
||||
),
|
||||
];
|
||||
let expected_trace = vec![executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id", "service_id": ""}, "values": []}),
|
||||
)];
|
||||
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
}
|
||||
|
@ -148,7 +148,10 @@ fn flattening_empty_values() {
|
||||
let script = f!(r#"
|
||||
(seq
|
||||
(call "{set_variable_peer_id}" ("" "") [] $stream)
|
||||
(call "{local_peer_id}" ("" "") [$stream.$.[1]!]) ; here $stream.$.[1] returns an empty array
|
||||
(seq
|
||||
(canon "{local_peer_id}" $stream #stream)
|
||||
(call "{local_peer_id}" ("" "") [#stream.$.[1]!]) ; here #stream.$.[1] returns an empty array
|
||||
)
|
||||
)
|
||||
"#);
|
||||
|
||||
|
@ -71,7 +71,10 @@ fn length_functor_for_stream() {
|
||||
(seq
|
||||
(ap 1 $stream)
|
||||
(ap 1 $stream))
|
||||
(call %init_peer_id% ("" "") [$stream.length]) ; behaviour = echo
|
||||
(seq
|
||||
(canon %init_peer_id% $stream #stream)
|
||||
(call %init_peer_id% ("" "") [#stream.length]) ; behaviour = echo
|
||||
)
|
||||
)
|
||||
"#;
|
||||
|
||||
@ -85,6 +88,21 @@ fn length_functor_for_stream() {
|
||||
let expected_trace = vec![
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "init_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": 1,
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "init_peer_id", "service_id": ""},
|
||||
"trace_pos": 0,
|
||||
},
|
||||
{
|
||||
"result": 1,
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "init_peer_id", "service_id": ""},
|
||||
"trace_pos": 1,
|
||||
},
|
||||
]
|
||||
})),
|
||||
executed_state::scalar_number(2),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
@ -94,7 +112,10 @@ fn length_functor_for_stream() {
|
||||
fn length_functor_for_empty_stream() {
|
||||
let script = r#"
|
||||
(new $stream
|
||||
(call %init_peer_id% ("" "") [$stream.length]) ; behaviour = echo
|
||||
(seq
|
||||
(canon %init_peer_id% $stream #canon_stream)
|
||||
(call %init_peer_id% ("" "") [#canon_stream.length]) ; behaviour = echo
|
||||
)
|
||||
)
|
||||
"#;
|
||||
|
||||
@ -105,7 +126,13 @@ fn length_functor_for_empty_stream() {
|
||||
let result = executor.execute_one(init_peer_id).unwrap();
|
||||
let actual_trace = trace_from_result(&result);
|
||||
|
||||
let expected_trace = vec![executed_state::scalar_number(0)];
|
||||
let expected_trace = vec![
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "init_peer_id", "service_id": ""},
|
||||
"values": []} ),
|
||||
),
|
||||
executed_state::scalar_number(0),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,10 @@ fn lambda_with_number_stream() {
|
||||
)
|
||||
)
|
||||
)
|
||||
(call "{local_peer_id}" ("" "") [$stream.$.[number_accessor]])
|
||||
(seq
|
||||
(canon "{local_peer_id}" $stream #canon_stream)
|
||||
(call "{local_peer_id}" ("" "") [#canon_stream.$.[number_accessor]])
|
||||
)
|
||||
)
|
||||
"#);
|
||||
|
||||
@ -143,7 +146,7 @@ fn lambda_with_number_stream() {
|
||||
let result = checked_call_vm!(local_vm, <_>::default(), script, "", result.data);
|
||||
let actual_trace = trace_from_result(&result);
|
||||
|
||||
assert_eq!(&actual_trace[5.into()], &executed_state::scalar_number(2));
|
||||
assert_eq!(&actual_trace[6.into()], &executed_state::scalar_number(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -180,7 +183,10 @@ fn lambda_with_number_stream_and_followed_scalar() {
|
||||
)
|
||||
)
|
||||
)
|
||||
(call "{local_peer_id}" ("" "") [$stream.$.[number_accessor].field_1]) ;; get the 2nd value and then access its field
|
||||
(seq
|
||||
(canon "{local_peer_id}" $stream #canon_stream)
|
||||
(call "{local_peer_id}" ("" "") [#canon_stream.$.[number_accessor].field_1]) ;; get the 2nd value and then access its field
|
||||
)
|
||||
)
|
||||
"#);
|
||||
|
||||
@ -188,7 +194,7 @@ fn lambda_with_number_stream_and_followed_scalar() {
|
||||
let result = checked_call_vm!(local_vm, <_>::default(), script, "", result.data);
|
||||
let actual_trace = trace_from_result(&result);
|
||||
|
||||
assert_eq!(&actual_trace[6.into()], &executed_state::scalar_number(checkable_value));
|
||||
assert_eq!(&actual_trace[7.into()], &executed_state::scalar_number(checkable_value));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -223,8 +229,11 @@ fn lambda_with_scalar_join() {
|
||||
assert_eq!(&trace[3.into()], &executed_state::request_sent_by("set_variable"));
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
// after 0.32 version AIR is no longer supports lambdas over stream,
|
||||
// although this test could be useful in the future for functors
|
||||
#[test]
|
||||
fn lambda_with_stream_join() {
|
||||
fn lambda_with_canon_stream_join() {
|
||||
let set_variable_peer_id = "set_variable";
|
||||
let variables = maplit::hashmap! {
|
||||
"number_accessor".to_string() => json!(1),
|
||||
@ -252,7 +261,10 @@ fn lambda_with_stream_join() {
|
||||
)
|
||||
)
|
||||
)
|
||||
(call "{local_peer_id}" ("" "") [$stream.$.[number_accessor]])
|
||||
(seq
|
||||
(canon "{local_peer_id}" $stream #stream)
|
||||
(call "{local_peer_id}" ("" "") [#stream.$.[number_accessor]])
|
||||
)
|
||||
)
|
||||
"#);
|
||||
|
||||
@ -261,7 +273,7 @@ fn lambda_with_stream_join() {
|
||||
let actual_trace = trace_from_result(&result);
|
||||
|
||||
assert_eq!(
|
||||
&actual_trace[6.into()],
|
||||
&executed_state::request_sent_by("set_variable")
|
||||
&actual_trace[7.into()],
|
||||
&executed_state::request_sent_by("set_variable"),
|
||||
);
|
||||
}
|
||||
|
@ -51,7 +51,9 @@ fn ap_with_fold() {
|
||||
(null))))
|
||||
(seq
|
||||
(call "{local_vm_peer_id}" ("op" "noop") [])
|
||||
(call "{local_vm_peer_id}" ("return" "") [$inner]))))
|
||||
(seq
|
||||
(canon "{local_vm_peer_id}" $inner #canon_stream)
|
||||
(call "{local_vm_peer_id}" ("return" "") [#canon_stream])))))
|
||||
"#);
|
||||
|
||||
let result = checked_call_vm!(set_variable_vm, <_>::default(), &script, "", "");
|
||||
|
@ -154,12 +154,15 @@ fn merging_fold_iterations_extensively_2() {
|
||||
)
|
||||
)
|
||||
)
|
||||
(call "p1" ("test" "print") [$pid-num-arrs]) ; behaviour = echo
|
||||
(seq
|
||||
(canon "p1" $pid-num-arrs #pid-num-arrs-1)
|
||||
(call "p1" ("test" "print") [#pid-num-arrs-1]) ; behaviour = echo
|
||||
)
|
||||
)
|
||||
(seq
|
||||
(seq
|
||||
(canon "p1" $pid-num-arrs #pid-num-arrs)
|
||||
(call "p1" ("test" "print") [$pid-num-arrs]) ; behaviour = echo
|
||||
(canon "p1" $pid-num-arrs #pid-num-arrs-2)
|
||||
(call "p1" ("test" "print") [#pid-num-arrs-2]) ; behaviour = echo
|
||||
)
|
||||
(new $result
|
||||
(fold $pid-num-arrs pid-num-arr
|
||||
|
@ -405,7 +405,10 @@ fn recursive_stream_fold_with_n_service_call() {
|
||||
)
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("op" "identity") [$result] result-fix)
|
||||
(seq
|
||||
(canon %init_peer_id% $result #canon_stream)
|
||||
(call %init_peer_id% ("op" "identity") [#canon_stream] result-fix)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -34,13 +34,20 @@ fn empty_stream() {
|
||||
})
|
||||
}
|
||||
|
||||
let mut vm = create_avm(arg_type_check_closure(), "A");
|
||||
let vm_peer_id = "vm_peer_id";
|
||||
let mut vm = create_avm(arg_type_check_closure(), vm_peer_id);
|
||||
|
||||
let script = r#"
|
||||
let script = f!(r#"
|
||||
(seq
|
||||
(call "A" ("" "") [$stream] $other_stream)
|
||||
(par
|
||||
(call "unknown_peer" ("" "") [] $stream) ; to make validator happy
|
||||
(seq
|
||||
(canon "{vm_peer_id}" $stream #canon_stream)
|
||||
(call "{vm_peer_id}" ("" "") [#canon_stream] $other_stream)
|
||||
)
|
||||
)
|
||||
(null)
|
||||
)"#;
|
||||
)"#);
|
||||
|
||||
let _ = checked_call_vm!(vm, <_>::default(), script, "", "");
|
||||
}
|
||||
|
@ -59,14 +59,30 @@ fn ap_with_string_literal() {
|
||||
let script = f!(r#"
|
||||
(seq
|
||||
(ap "{some_string}" $stream)
|
||||
(call "{vm_1_peer_id}" ("" "") [$stream])
|
||||
)
|
||||
(seq
|
||||
(canon "{vm_1_peer_id}" $stream #canon_stream)
|
||||
(call "{vm_1_peer_id}" ("" "") [#canon_stream])))
|
||||
"#);
|
||||
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_state = vec![executed_state::ap(0), executed_state::scalar(json!([some_string]))];
|
||||
let expected_state = vec![
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!(
|
||||
{
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": "some_string",
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
)),
|
||||
executed_state::scalar(json!([some_string])),
|
||||
];
|
||||
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
assert!(result.next_peer_pks.is_empty());
|
||||
@ -80,14 +96,28 @@ fn ap_with_bool_literal() {
|
||||
let script = f!(r#"
|
||||
(seq
|
||||
(ap true $stream)
|
||||
(call "{vm_1_peer_id}" ("" "") [$stream])
|
||||
)
|
||||
(seq
|
||||
(canon "{vm_1_peer_id}" $stream #canon_stream)
|
||||
(call "{vm_1_peer_id}" ("" "") [#canon_stream])))
|
||||
"#);
|
||||
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_state = vec![executed_state::ap(0), executed_state::scalar(json!([true]))];
|
||||
let expected_state = vec![
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!( {
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": true,
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 0
|
||||
}
|
||||
]
|
||||
})),
|
||||
executed_state::scalar(json!([true])),
|
||||
];
|
||||
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
assert!(result.next_peer_pks.is_empty());
|
||||
@ -101,14 +131,28 @@ fn ap_with_number_literal() {
|
||||
let script = f!(r#"
|
||||
(seq
|
||||
(ap 100 $stream)
|
||||
(call "{vm_1_peer_id}" ("" "") [$stream])
|
||||
)
|
||||
(seq
|
||||
(canon "{vm_1_peer_id}" $stream #canon_stream)
|
||||
(call "{vm_1_peer_id}" ("" "") [#canon_stream])))
|
||||
"#);
|
||||
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_state = vec![executed_state::ap(0), executed_state::scalar(json!([100]))];
|
||||
let expected_state = vec![
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": 100,
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 0
|
||||
}
|
||||
]
|
||||
})),
|
||||
executed_state::scalar(json!([100])),
|
||||
];
|
||||
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
assert!(result.next_peer_pks.is_empty());
|
||||
@ -122,14 +166,28 @@ fn ap_with_last_error() {
|
||||
let script = f!(r#"
|
||||
(seq
|
||||
(ap %last_error% $stream)
|
||||
(call "{vm_1_peer_id}" ("" "") [$stream])
|
||||
)
|
||||
(seq
|
||||
(canon "{vm_1_peer_id}" $stream #canon_stream)
|
||||
(call "{vm_1_peer_id}" ("" "") [#canon_stream])))
|
||||
"#);
|
||||
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), script, "", "");
|
||||
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_state = vec![executed_state::ap(0), executed_state::scalar(json!([null]))];
|
||||
let expected_state = vec![
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": null,
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 0
|
||||
}
|
||||
]
|
||||
})),
|
||||
executed_state::scalar(json!([null])),
|
||||
];
|
||||
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
assert!(result.next_peer_pks.is_empty());
|
||||
@ -190,10 +248,10 @@ fn ap_with_dst_stream() {
|
||||
(seq
|
||||
(seq
|
||||
(call "{vm_1_peer_id}" ("" "") ["scalar_1_result"] scalar_1)
|
||||
(ap scalar_1 $stream)
|
||||
)
|
||||
(call "{vm_2_peer_id}" ("" "") [$stream])
|
||||
)
|
||||
(ap scalar_1 $stream))
|
||||
(seq
|
||||
(canon "{vm_2_peer_id}" $stream #canon_stream)
|
||||
(call "{vm_2_peer_id}" ("" "") [#canon_stream])))
|
||||
"#);
|
||||
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), &script, "", "");
|
||||
@ -203,6 +261,16 @@ fn ap_with_dst_stream() {
|
||||
let expected_state = vec![
|
||||
executed_state::scalar(json!({ "field": test_value })),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_2_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": {"field": "scalar_2"},
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"trace_pos": 1
|
||||
}
|
||||
]
|
||||
})),
|
||||
executed_state::scalar(json!([{ "field": test_value }])),
|
||||
];
|
||||
|
||||
@ -227,7 +295,9 @@ fn ap_canon_stream_with_lambda() {
|
||||
(canon "{vm_1_peer_id}" $stream #canon_stream)
|
||||
(seq
|
||||
(ap #canon_stream.$.[1] $stream_2)
|
||||
(call "{vm_1_peer_id}" ("" "") [$stream_2]))))
|
||||
(seq
|
||||
(canon "{vm_1_peer_id}" $stream_2 #canon_stream_2)
|
||||
(call "{vm_1_peer_id}" ("" "") [#canon_stream_2])))))
|
||||
"#);
|
||||
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), &script, "", "");
|
||||
@ -238,10 +308,22 @@ fn ap_canon_stream_with_lambda() {
|
||||
executed_state::stream_number(1, 1),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"values": [{"result": 0, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""}, "trace_pos": 0},
|
||||
{"result": 1, "tetraplet": {"function_name": "some_function_name", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": "some_service_name"}, "trace_pos": 1}]}),
|
||||
"values": [{"result": 0, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""}, "trace_pos": 0},
|
||||
{"result": 1, "tetraplet": {"function_name": "some_function_name", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": "some_service_name"}, "trace_pos": 1}]}),
|
||||
),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!(
|
||||
{
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": 1,
|
||||
"tetraplet": {"function_name": "some_function_name", "json_path": ".$.[1]", "peer_pk": "vm_1_peer_id", "service_id": "some_service_name"},
|
||||
"trace_pos": 3,
|
||||
}
|
||||
]
|
||||
}
|
||||
)),
|
||||
executed_state::scalar(json!([1])),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
@ -272,10 +354,13 @@ fn ap_canon_stream() {
|
||||
(canon "{vm_1_peer_id}" $stream #canon_stream)
|
||||
(seq
|
||||
(ap #canon_stream $stream_2)
|
||||
(call "{vm_1_peer_id}" ("" "") [$stream_2]))))
|
||||
(seq
|
||||
(canon "{vm_1_peer_id}" $stream_2 #canon_stream_2)
|
||||
(call "{vm_1_peer_id}" ("" "") [#canon_stream_2])))))
|
||||
"#);
|
||||
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), &script, "", "");
|
||||
print_trace(&result, "");
|
||||
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_state = vec![
|
||||
@ -283,10 +368,22 @@ fn ap_canon_stream() {
|
||||
executed_state::stream_number(1, 1),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"values": [{"result": 0, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""}, "trace_pos": 0},
|
||||
{"result": 1, "tetraplet": {"function_name": "some_function_name", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": "some_service_name"}, "trace_pos": 1}]}),
|
||||
"values": [{"result": 0, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""}, "trace_pos": 0},
|
||||
{"result": 1, "tetraplet": {"function_name": "some_function_name", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": "some_service_name"}, "trace_pos": 1}]}),
|
||||
),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!(
|
||||
{
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": [0, 1],
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"trace_pos": 3,
|
||||
}
|
||||
]
|
||||
}
|
||||
)),
|
||||
executed_state::scalar(json!([[0, 1]])),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_state);
|
||||
|
@ -161,7 +161,9 @@ fn canon_stream_can_be_created_from_aps() {
|
||||
(canon "{vm_1_peer_id}" $stream #canon_stream)
|
||||
(seq
|
||||
(ap #canon_stream $stream_2)
|
||||
(call "{vm_2_peer_id}" ("" "") [$stream_2]))))
|
||||
(seq
|
||||
(canon "{vm_2_peer_id}" $stream_2 #canon_stream_2)
|
||||
(call "{vm_2_peer_id}" ("" "") [#canon_stream_2])))))
|
||||
"#);
|
||||
|
||||
let result_1 = checked_call_vm!(vm_1, <_>::default(), &script, "", "");
|
||||
@ -267,14 +269,21 @@ fn canon_empty_not_writable_stream() {
|
||||
let mut vm = create_avm(echo_call_service(), peer_id);
|
||||
|
||||
let script = f!(r#"
|
||||
(canon "{peer_id}" $stream #canon_stream)
|
||||
(par
|
||||
(call "unwkown_peer_id" ("" "") [] $stream)
|
||||
(canon "{peer_id}" $stream #canon_stream)
|
||||
)
|
||||
"#);
|
||||
|
||||
let result = checked_call_vm!(vm, <_>::default(), &script, "", "");
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_trace = vec![executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id", "service_id": ""}, "values": []} ),
|
||||
)];
|
||||
let expected_trace = vec![
|
||||
executed_state::par(1, 1),
|
||||
executed_state::request_sent_by(peer_id),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id", "service_id": ""}, "values": []} ),
|
||||
),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
}
|
||||
|
||||
|
@ -306,7 +306,10 @@ fn issue_165() {
|
||||
)
|
||||
(ap 2 $results)
|
||||
)
|
||||
(call "{echo_peer_id}" ("callbackSrv" "response") [$results.$.[0]!])
|
||||
(seq
|
||||
(canon "{echo_peer_id}" $results #results)
|
||||
(call "{echo_peer_id}" ("callbackSrv" "response") [#results.$.[0]!])
|
||||
)
|
||||
)
|
||||
)
|
||||
"#);
|
||||
|
@ -109,7 +109,10 @@ fn several_restrictions() {
|
||||
(new $stream
|
||||
(call "{vm_peer_id}" ("" "") ["test"] $stream)
|
||||
)
|
||||
(call "{vm_peer_id}" ("" "") [$stream])
|
||||
(seq
|
||||
(canon "{vm_peer_id}" $stream #canon_stream)
|
||||
(call "{vm_peer_id}" ("" "") [#canon_stream])
|
||||
)
|
||||
)
|
||||
)"#);
|
||||
|
||||
@ -118,6 +121,12 @@ fn several_restrictions() {
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_trace = vec![
|
||||
executed_state::stream_string("test", 0),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
|
||||
]
|
||||
})),
|
||||
executed_state::scalar(json!([])),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
@ -139,16 +148,28 @@ fn check_influence_to_not_restricted() {
|
||||
)
|
||||
(ap "more" $a)
|
||||
)
|
||||
(call "{vm_peer_id}" ("op" "identity") [$a] a-fix)
|
||||
(seq
|
||||
(canon "{vm_peer_id}" $a #a)
|
||||
(call "{vm_peer_id}" ("op" "identity") [#a] a-fix)
|
||||
)
|
||||
)
|
||||
)
|
||||
(seq
|
||||
(seq
|
||||
(call "{vm_peer_id}" ("callbackSrv" "response") [$a0]) ;; should be non-empty
|
||||
(call "{vm_peer_id}" ("callbackSrv" "response") [$a1]) ;; should be non-empty
|
||||
(seq
|
||||
(canon "{vm_peer_id}" $a0 #a0)
|
||||
(call "{vm_peer_id}" ("callbackSrv" "response") [#a0]) ;; should be non-empty
|
||||
)
|
||||
(seq
|
||||
(canon "{vm_peer_id}" $a1 #a1)
|
||||
(call "{vm_peer_id}" ("callbackSrv" "response") [#a1]) ;; should be non-empty
|
||||
)
|
||||
)
|
||||
(seq
|
||||
(call "{vm_peer_id}" ("callbackSrv" "response") [$a]) ;; should be empty
|
||||
(seq
|
||||
(canon "{vm_peer_id}" $a #aa)
|
||||
(call "{vm_peer_id}" ("callbackSrv" "response") [#aa]) ;; should be empty
|
||||
)
|
||||
(call "{vm_peer_id}" ("callbackSrv" "response") [a-fix]) ;; should be empty
|
||||
)
|
||||
)
|
||||
@ -162,9 +183,48 @@ fn check_influence_to_not_restricted() {
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!(
|
||||
{
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": "more",
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
)),
|
||||
executed_state::scalar(json!(["more"])),
|
||||
executed_state::canon(json!(
|
||||
{
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": "push more",
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
)),
|
||||
executed_state::scalar(json!(["push more"])),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": "push more",
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 1
|
||||
}
|
||||
]
|
||||
})),
|
||||
executed_state::scalar(json!(["push more"])),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
]
|
||||
})),
|
||||
executed_state::scalar(json!([])),
|
||||
executed_state::scalar(json!(["more"])),
|
||||
];
|
||||
@ -187,7 +247,10 @@ fn new_in_fold_with_ap() {
|
||||
(new $s1
|
||||
(seq
|
||||
(ap "none" $s1)
|
||||
(call "{vm_peer_id}" ("" "") [$s1] s-fix1) ;; should contains only "none" on each iteration
|
||||
(seq
|
||||
(canon "{vm_peer_id}" $s1 #canon_s1)
|
||||
(call "{vm_peer_id}" ("" "") [#canon_s1] s-fix1) ;; should contains only "none" on each iteration
|
||||
)
|
||||
)
|
||||
)
|
||||
(next x)
|
||||
@ -203,14 +266,64 @@ fn new_in_fold_with_ap() {
|
||||
let expected_trace = vec![
|
||||
executed_state::scalar(json!([1, 2, 3, 4, 5])),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": "none",
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 1
|
||||
}
|
||||
]
|
||||
})),
|
||||
executed_state::scalar_string_array(vec!["none"]),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": "none",
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 4
|
||||
}
|
||||
]
|
||||
})),
|
||||
executed_state::scalar_string_array(vec!["none"]),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": "none",
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 7
|
||||
}
|
||||
]
|
||||
})),
|
||||
executed_state::scalar_string_array(vec!["none"]),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": "none",
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 10
|
||||
}
|
||||
]
|
||||
})),
|
||||
executed_state::scalar_string_array(vec!["none"]),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": "none",
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "", "service_id": ""},
|
||||
"trace_pos": 13
|
||||
}
|
||||
]
|
||||
})),
|
||||
executed_state::scalar_string_array(vec!["none"]),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
|
@ -27,8 +27,31 @@ fn issue_177() {
|
||||
let variables = maplit::hashmap! {
|
||||
"-relay-".to_string() => json!(relay_peer_id),
|
||||
"noop".to_string() => json!([]),
|
||||
"string_to_parse_iter".to_string() => json!("CovLVG4fQcqVPcweSGV5ANQ8NQ2hJnVQrFJJPyQvdKmMDDNDuYYveDy4ncnmDbsvRFA5FcG"),
|
||||
"neighborhood".to_string() => json!(["12D3KooWGzNvhSDsgFoHwpWHAyPf1kcTYCGeRBPfznL8J6qdyu2H","12D3KooWJbJFaZ3k5sNd8DjQgg3aERoKtBAnirEvPV8yp76kEXHB","12D3KooWBSdm6TkqnEFrgBuSkpVE3dR1kr6952DsWQRNwJZjFZBv","12D3KooWKnRcsTpYx9axkJ6d69LPfpPXrkVLe96skuPTAo76LLVH","12D3KooWHCJbJKGDfCgHSoCuK9q4STyRnVveqLoXAPBbXHTZx9Cv","12D3KooWMhVpgfQxBLkQkJed8VFNvgN4iE6MD7xCybb1ZYWW2Gtz","12D3KooWF7gjXhQ4LaKj6j7ntxsPpGk34psdQicN2KNfBi9bFKXg","12D3KooWBUJifCTgaxAUrcM9JysqCcS4CS8tiYH5hExbdWCAoNwb","12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE9","12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er","12D3KooWDcpWuyrMTDinqNgmXAuRdfd2mTdY9VoXZSAet2pDzh6r","12D3KooWCKCeqLPSgMnDjyFsJuWqREDtKNHx1JEBiwaMXhCLNTRb","12D3KooWMigkP4jkVyufq5JnDJL6nXvyjeaDNpRfEZqQhsG3sYCU","12D3KooWB9P1xmV3c7ZPpBemovbwCiRRTKd3Kq2jsVPQN4ZukDfy","12D3KooWAKNos2KogexTXhrkMZzFYpLHuWJ4PgoAhurSAv7o5CWA","12D3KooWDUszU2NeWyUVjCXhGEt1MoZrhvdmaQQwtZUriuGN1jTr","12D3KooWKnEqMfYo9zvfHmqTLpLdiHXPe4SVqUWcWHDJdFGrSmcA","12D3KooWEFFCZnar1cUJQ3rMWjvPQg6yMV2aXWs2DkJNSRbduBWn","12D3KooWHBG9oaVx4i3vi6c1rSBUm7MLBmyGmmbHoZ23pmjDCnvK","12D3KooWFpQ7LHxcC9FEBUh3k4nSCC12jBhijJv3gJbi7wsNYzJ5"]),
|
||||
"string_to_parse_iter".to_string() => json!(
|
||||
"CovLVG4fQcqVPcweSGV5ANQ8NQ2hJnVQrFJJPyQvdKmMDDNDuYYveDy4ncnmDbsvRFA5FcG"
|
||||
),
|
||||
"neighborhood".to_string() => json!([
|
||||
"12D3KooWGzNvhSDsgFoHwpWHAyPf1kcTYCGeRBPfznL8J6qdyu2H",
|
||||
"12D3KooWJbJFaZ3k5sNd8DjQgg3aERoKtBAnirEvPV8yp76kEXHB",
|
||||
"12D3KooWBSdm6TkqnEFrgBuSkpVE3dR1kr6952DsWQRNwJZjFZBv",
|
||||
"12D3KooWKnRcsTpYx9axkJ6d69LPfpPXrkVLe96skuPTAo76LLVH",
|
||||
"12D3KooWHCJbJKGDfCgHSoCuK9q4STyRnVveqLoXAPBbXHTZx9Cv",
|
||||
"12D3KooWMhVpgfQxBLkQkJed8VFNvgN4iE6MD7xCybb1ZYWW2Gtz",
|
||||
"12D3KooWF7gjXhQ4LaKj6j7ntxsPpGk34psdQicN2KNfBi9bFKXg",
|
||||
"12D3KooWBUJifCTgaxAUrcM9JysqCcS4CS8tiYH5hExbdWCAoNwb",
|
||||
"12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE9",
|
||||
"12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er",
|
||||
"12D3KooWDcpWuyrMTDinqNgmXAuRdfd2mTdY9VoXZSAet2pDzh6r",
|
||||
"12D3KooWCKCeqLPSgMnDjyFsJuWqREDtKNHx1JEBiwaMXhCLNTRb",
|
||||
"12D3KooWMigkP4jkVyufq5JnDJL6nXvyjeaDNpRfEZqQhsG3sYCU",
|
||||
"12D3KooWB9P1xmV3c7ZPpBemovbwCiRRTKd3Kq2jsVPQN4ZukDfy",
|
||||
"12D3KooWAKNos2KogexTXhrkMZzFYpLHuWJ4PgoAhurSAv7o5CWA",
|
||||
"12D3KooWDUszU2NeWyUVjCXhGEt1MoZrhvdmaQQwtZUriuGN1jTr",
|
||||
"12D3KooWKnEqMfYo9zvfHmqTLpLdiHXPe4SVqUWcWHDJdFGrSmcA",
|
||||
"12D3KooWEFFCZnar1cUJQ3rMWjvPQg6yMV2aXWs2DkJNSRbduBWn",
|
||||
"12D3KooWHBG9oaVx4i3vi6c1rSBUm7MLBmyGmmbHoZ23pmjDCnvK",
|
||||
"12D3KooWFpQ7LHxcC9FEBUh3k4nSCC12jBhijJv3gJbi7wsNYzJ5"
|
||||
]),
|
||||
};
|
||||
|
||||
let mut client = create_avm(
|
||||
|
@ -32,7 +32,10 @@ fn par_ap_behaviour() {
|
||||
(call "{relay_id}" ("peer" "timeout") [join_it] $result) ; behaviour=unit
|
||||
(ap "fast_result" $result)
|
||||
)
|
||||
(call "{client_id}" ("op" "return") [$result.$[0]]) ; behaviour=unit
|
||||
(seq
|
||||
(canon "{client_id}" $result #result)
|
||||
(call "{client_id}" ("op" "return") [#result.$[0]]) ; behaviour=unit
|
||||
)
|
||||
)
|
||||
)
|
||||
"#);
|
||||
|
@ -17,7 +17,8 @@
|
||||
use air_test_utils::prelude::*;
|
||||
|
||||
#[test]
|
||||
// test for github.com/fluencelabs/aquavm/issues/206
|
||||
#[ignore] // this test is not actual because streams are prohibited to be used as match operands
|
||||
// test for github.com/fluencelabs/aquavm/issues/206
|
||||
fn issue_206() {
|
||||
let peer_1_id = "peer_1_id";
|
||||
let mut peer_1 = create_avm(echo_call_service(), peer_1_id);
|
||||
|
@ -23,38 +23,44 @@ fn issue_211() {
|
||||
let peer_1_id = "peer_1_id";
|
||||
|
||||
let script = f!(r#"
|
||||
(xor
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(xor
|
||||
(seq
|
||||
(null)
|
||||
(call %init_peer_id% ("getDataSrv" "idx") [] idx) ; ok=2
|
||||
)
|
||||
(call %init_peer_id% ("getDataSrv" "nodes") [] nodes) ; ok = [1,2,3]
|
||||
)
|
||||
(new $nodes2
|
||||
(seq
|
||||
(seq
|
||||
(par
|
||||
(fold nodes node
|
||||
(par
|
||||
(ap node $nodes2)
|
||||
(next node)
|
||||
)
|
||||
)
|
||||
(null)
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(null)
|
||||
(call %init_peer_id% ("getdatasrv" "idx") [] idx) ; ok=2
|
||||
)
|
||||
(call %init_peer_id% ("getdatasrv" "nodes") [] nodes) ; ok = [1,2,3]
|
||||
)
|
||||
(new $nodes2
|
||||
(seq
|
||||
(seq
|
||||
(par
|
||||
(fold nodes node
|
||||
(par
|
||||
(ap node $nodes2)
|
||||
(next node)
|
||||
)
|
||||
)
|
||||
(null)
|
||||
)
|
||||
(seq
|
||||
(canon %init_peer_id% $nodes2 #nodes2_0)
|
||||
(call %init_peer_id% ("op" "noop") [#nodes2_0.$.[idx]! nodes]) ; ok="expected result"
|
||||
)
|
||||
)
|
||||
(seq
|
||||
(canon %init_peer_id% $nodes2 #nodes2_1)
|
||||
(call %init_peer_id% ("op" "identity") [#nodes2_1] nodes2-fix) ; ok="expected result"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("op" "noop") [$nodes2.$.[idx] nodes]) ; ok="expected result"
|
||||
)
|
||||
(call %init_peer_id% ("op" "identity") [$nodes2] nodes2-fix) ; ok="expected result"
|
||||
(null)
|
||||
)
|
||||
)
|
||||
)
|
||||
(null)
|
||||
(call %init_peer_id% ("errorhandlingsrv" "error") [%last_error% 2]) ; ok="error"
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2]) ; ok="error"
|
||||
)
|
||||
"#);
|
||||
|
||||
let run_params = TestRunParameters::from_init_peer_id(peer_1_id);
|
||||
@ -74,7 +80,47 @@ fn issue_211() {
|
||||
executed_state::ap(0),
|
||||
executed_state::par(1, 0),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_1_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": 1,
|
||||
"tetraplet": {"function_name": "nodes", "json_path": "", "peer_pk": "peer_1_id", "service_id": "getdatasrv..1"},
|
||||
"trace_pos": 4
|
||||
},
|
||||
{
|
||||
"result": 2,
|
||||
"tetraplet": {"function_name": "nodes", "json_path": "", "peer_pk": "peer_1_id", "service_id": "getdatasrv..1"},
|
||||
"trace_pos": 6
|
||||
},
|
||||
{
|
||||
"result": 3,
|
||||
"tetraplet": {"function_name": "nodes", "json_path": "", "peer_pk": "peer_1_id", "service_id": "getdatasrv..1"},
|
||||
"trace_pos": 8
|
||||
},
|
||||
]
|
||||
})),
|
||||
executed_state::scalar_string("expected result"),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_1_id", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": 1,
|
||||
"tetraplet": {"function_name": "nodes", "json_path": "", "peer_pk": "peer_1_id", "service_id": "getdatasrv..1"},
|
||||
"trace_pos": 4
|
||||
},
|
||||
{
|
||||
"result": 2,
|
||||
"tetraplet": {"function_name": "nodes", "json_path": "", "peer_pk": "peer_1_id", "service_id": "getdatasrv..1"},
|
||||
"trace_pos": 6
|
||||
},
|
||||
{
|
||||
"result": 3,
|
||||
"tetraplet": {"function_name": "nodes", "json_path": "", "peer_pk": "peer_1_id", "service_id": "getdatasrv..1"},
|
||||
"trace_pos": 8
|
||||
},
|
||||
]
|
||||
})),
|
||||
executed_state::scalar_string("expected result"),
|
||||
];
|
||||
|
||||
|
@ -38,7 +38,10 @@ fn issue_302() {
|
||||
(call "{peer_id_2}" ("" "") [1] $stream)
|
||||
(seq
|
||||
(call "{peer_id_3}" ("" "") [0] $stream)
|
||||
(call "{peer_id_2}" ("" "") [$stream])
|
||||
(seq
|
||||
(canon "{peer_id_2}" $stream #stream)
|
||||
(call "{peer_id_2}" ("" "") [#stream])
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -52,10 +55,30 @@ fn issue_302() {
|
||||
let actual_trace = trace_from_result(&result_4);
|
||||
|
||||
let expected_trace = vec![
|
||||
executed_state::par(1, 3),
|
||||
executed_state::par(1, 4),
|
||||
executed_state::stream_number(2, 1),
|
||||
executed_state::stream_number(1, 0),
|
||||
executed_state::stream_number(0, 2),
|
||||
executed_state::canon(json!({
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_2", "service_id": ""},
|
||||
"values": [
|
||||
{
|
||||
"result": 1,
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_2", "service_id": ""},
|
||||
"trace_pos": 2
|
||||
},
|
||||
{
|
||||
"result": 2,
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_1", "service_id": ""},
|
||||
"trace_pos": 1
|
||||
},
|
||||
{
|
||||
"result": 0,
|
||||
"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_3", "service_id": ""},
|
||||
"trace_pos": 3
|
||||
},
|
||||
]
|
||||
})),
|
||||
executed_state::scalar(json!([1, 2, 0])),
|
||||
];
|
||||
assert_eq!(actual_trace.deref(), expected_trace);
|
||||
|
@ -29,7 +29,12 @@ fn issue_331() {
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call %init_peer_id% ("op" "array_length") [$status] array_length)
|
||||
(seq
|
||||
(new $status
|
||||
(canon %init_peer_id% $status #status)
|
||||
)
|
||||
(call %init_peer_id% ("op" "array_length") [#status] array_length)
|
||||
)
|
||||
(ap array_length $array-inline)
|
||||
)
|
||||
(seq
|
||||
|
@ -43,7 +43,10 @@ fn issue_356() {
|
||||
)
|
||||
)
|
||||
)
|
||||
(call "client" ("return" "") [$external_addresses neighs_inner] x) ; ok = null
|
||||
(seq
|
||||
(canon "client" $external_addresses #external_addresses)
|
||||
(call "client" ("return" "") [#external_addresses neighs_inner] x) ; ok = null
|
||||
)
|
||||
)
|
||||
)
|
||||
"#;
|
||||
|
@ -39,11 +39,17 @@
|
||||
)
|
||||
)
|
||||
(par
|
||||
(call %init_peer_id% ("op" "identity") [$res.$.[19]!])
|
||||
(seq
|
||||
(canon %init_peer_id% $res #res)
|
||||
(call %init_peer_id% ("op" "identity") [#res.$.[19]!])
|
||||
)
|
||||
(call %init_peer_id% ("peer" "timeout") [1000 "timeout"])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("op" "identity") [$res] res-fix)
|
||||
(seq
|
||||
(canon %init_peer_id% $res #res)
|
||||
(call %init_peer_id% ("op" "identity") [#res] res-fix)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -18,23 +18,37 @@ mod impls;
|
||||
mod traits;
|
||||
|
||||
use super::CanonStream;
|
||||
use super::CanonStreamWithLambda;
|
||||
use super::ImmutableVariable;
|
||||
use super::ImmutableVariableWithLambda;
|
||||
use super::Scalar;
|
||||
use super::ScalarWithLambda;
|
||||
use super::Stream;
|
||||
use super::VariableWithLambda;
|
||||
|
||||
use air_lambda_ast::LambdaAST;
|
||||
|
||||
use crate::ast::CanonStreamWithLambda;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
// TODO: rename CallInstrValue, since it'd used by the canon instruction
|
||||
/// Contains all variable variants that could be resolved to a peer id.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum CallInstrValue<'i> {
|
||||
pub enum ResolvableToPeerIdVariable<'i> {
|
||||
InitPeerId,
|
||||
Literal(&'i str),
|
||||
Variable(VariableWithLambda<'i>),
|
||||
Scalar(Scalar<'i>),
|
||||
ScalarWithLambda(ScalarWithLambda<'i>),
|
||||
// canon without lambda can't be resolved to a string, since it represents an array of values
|
||||
CanonStreamWithLambda(CanonStreamWithLambda<'i>),
|
||||
}
|
||||
|
||||
/// Contains all variable variants that could be resolved to a string type.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum ResolvableToStringVariable<'i> {
|
||||
Literal(&'i str),
|
||||
Scalar(Scalar<'i>),
|
||||
ScalarWithLambda(ScalarWithLambda<'i>),
|
||||
// canon without lambda can't be resolved to a string, since it represents an array of values
|
||||
CanonStreamWithLambda(CanonStreamWithLambda<'i>),
|
||||
}
|
||||
|
||||
/// Triplet represents a location of the executable code in the network.
|
||||
@ -42,16 +56,16 @@ pub enum CallInstrValue<'i> {
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct Triplet<'i> {
|
||||
#[serde(borrow)]
|
||||
pub peer_pk: CallInstrValue<'i>,
|
||||
pub peer_id: ResolvableToPeerIdVariable<'i>,
|
||||
#[serde(borrow)]
|
||||
pub service_id: CallInstrValue<'i>,
|
||||
pub service_id: ResolvableToStringVariable<'i>,
|
||||
#[serde(borrow)]
|
||||
pub function_name: CallInstrValue<'i>,
|
||||
pub function_name: ResolvableToStringVariable<'i>,
|
||||
}
|
||||
|
||||
/// Represents all values that is possible to set in AIR scripts.
|
||||
/// Represents all immutable values that is possible to set in AIR scripts.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub enum Value<'i> {
|
||||
pub enum ImmutableValue<'i> {
|
||||
InitPeerId,
|
||||
LastError(Option<LambdaAST<'i>>),
|
||||
Timestamp,
|
||||
@ -60,7 +74,8 @@ pub enum Value<'i> {
|
||||
Number(Number),
|
||||
Boolean(bool),
|
||||
EmptyArray, // only empty arrays are allowed now
|
||||
Variable(VariableWithLambda<'i>),
|
||||
Variable(ImmutableVariable<'i>),
|
||||
VariableWithLambda(ImmutableVariableWithLambda<'i>),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, PartialEq, Eq, Clone)]
|
||||
@ -82,8 +97,10 @@ pub enum ApArgument<'i> {
|
||||
Number(Number),
|
||||
Boolean(bool),
|
||||
EmptyArray,
|
||||
Scalar(ScalarWithLambda<'i>),
|
||||
CanonStream(CanonStreamWithLambda<'i>),
|
||||
Scalar(Scalar<'i>),
|
||||
ScalarWithLambda(ScalarWithLambda<'i>),
|
||||
CanonStream(CanonStream<'i>),
|
||||
CanonStreamWithLambda(CanonStreamWithLambda<'i>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
@ -103,7 +120,9 @@ pub enum Number {
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum FoldScalarIterable<'i> {
|
||||
#[serde(borrow)]
|
||||
Scalar(ScalarWithLambda<'i>),
|
||||
Scalar(Scalar<'i>),
|
||||
#[serde(borrow)]
|
||||
ScalarWithLambda(ScalarWithLambda<'i>),
|
||||
// it's important not to have lambda here
|
||||
#[serde(borrow)]
|
||||
CanonStream(CanonStream<'i>),
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
use super::*;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
impl fmt::Display for ApResult<'_> {
|
||||
@ -28,9 +29,9 @@ impl fmt::Display for ApResult<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Value<'_> {
|
||||
impl fmt::Display for ImmutableValue<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use Value::*;
|
||||
use ImmutableValue::*;
|
||||
|
||||
match self {
|
||||
InitPeerId => write!(f, "%init_peer_id%"),
|
||||
@ -42,18 +43,34 @@ impl fmt::Display for Value<'_> {
|
||||
Boolean(bool) => write!(f, "{}", bool),
|
||||
EmptyArray => write!(f, "[]"),
|
||||
Variable(variable) => write!(f, "{}", variable),
|
||||
VariableWithLambda(variable) => write!(f, "{}", variable),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CallInstrValue<'_> {
|
||||
impl fmt::Display for ResolvableToPeerIdVariable<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use CallInstrValue::*;
|
||||
use ResolvableToPeerIdVariable::*;
|
||||
|
||||
match self {
|
||||
InitPeerId => write!(f, "%init_peer_id%"),
|
||||
Literal(literal) => write!(f, r#""{}""#, literal),
|
||||
Variable(variable) => write!(f, "{}", variable),
|
||||
Scalar(scalar) => write!(f, "{}", scalar),
|
||||
ScalarWithLambda(scalar) => write!(f, "{}", scalar),
|
||||
CanonStreamWithLambda(canon_stream) => write!(f, "{}", canon_stream),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ResolvableToStringVariable<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use ResolvableToStringVariable::*;
|
||||
|
||||
match self {
|
||||
Literal(literal) => write!(f, r#""{}""#, literal),
|
||||
Scalar(scalar) => write!(f, "{}", scalar),
|
||||
ScalarWithLambda(scalar) => write!(f, "{}", scalar),
|
||||
CanonStreamWithLambda(canon_stream) => write!(f, "{}", canon_stream),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,7 +101,9 @@ impl fmt::Display for ApArgument<'_> {
|
||||
Boolean(bool) => write!(f, "{}", bool),
|
||||
EmptyArray => write!(f, "[]"),
|
||||
Scalar(scalar) => write!(f, "{}", scalar),
|
||||
ScalarWithLambda(scalar) => write!(f, "{}", scalar),
|
||||
CanonStream(canon_stream) => write!(f, "{}", canon_stream),
|
||||
CanonStreamWithLambda(canon_stream) => write!(f, "{}", canon_stream),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,7 +113,7 @@ impl fmt::Display for Triplet<'_> {
|
||||
write!(
|
||||
f,
|
||||
"{} ({} {})",
|
||||
self.peer_pk, self.service_id, self.function_name
|
||||
self.peer_id, self.service_id, self.function_name
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -125,7 +144,8 @@ impl fmt::Display for FoldScalarIterable<'_> {
|
||||
use FoldScalarIterable::*;
|
||||
|
||||
match self {
|
||||
Scalar(variable) => write!(f, "{}", variable),
|
||||
Scalar(scalar) => write!(f, "{}", scalar),
|
||||
ScalarWithLambda(scalar) => write!(f, "{}", scalar),
|
||||
CanonStream(canon_stream) => write!(f, "{}", canon_stream),
|
||||
EmptyArray => write!(f, "[]"),
|
||||
}
|
||||
|
@ -18,8 +18,9 @@ mod impls;
|
||||
mod traits;
|
||||
|
||||
use super::*;
|
||||
use air_lambda_ast::LambdaAST;
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
// TODO: sort instruction in alphanumeric order
|
||||
@ -48,7 +49,7 @@ pub enum Instruction<'i> {
|
||||
#[derive(Serialize, Debug, PartialEq)]
|
||||
pub struct Call<'i> {
|
||||
pub triplet: Triplet<'i>,
|
||||
pub args: Rc<Vec<Value<'i>>>,
|
||||
pub args: Rc<Vec<ImmutableValue<'i>>>,
|
||||
pub output: CallOutputValue<'i>,
|
||||
}
|
||||
|
||||
@ -62,7 +63,7 @@ pub struct Ap<'i> {
|
||||
/// (canon peer_id $stream #canon_stream)
|
||||
#[derive(Serialize, Debug, PartialEq, Eq)]
|
||||
pub struct Canon<'i> {
|
||||
pub peer_pk: CallInstrValue<'i>,
|
||||
pub peer_id: ResolvableToPeerIdVariable<'i>,
|
||||
pub stream: Stream<'i>,
|
||||
pub canon_stream: CanonStream<'i>,
|
||||
}
|
||||
@ -82,32 +83,31 @@ pub struct Xor<'i>(pub Box<Instruction<'i>>, pub Box<Instruction<'i>>);
|
||||
/// (match left_value right_value instruction)
|
||||
#[derive(Serialize, Debug, PartialEq)]
|
||||
pub struct Match<'i> {
|
||||
pub left_value: Value<'i>,
|
||||
pub right_value: Value<'i>,
|
||||
pub left_value: ImmutableValue<'i>,
|
||||
pub right_value: ImmutableValue<'i>,
|
||||
pub instruction: Box<Instruction<'i>>,
|
||||
}
|
||||
|
||||
/// (mismatch left_value right_value instruction)
|
||||
#[derive(Serialize, Debug, PartialEq)]
|
||||
pub struct MisMatch<'i> {
|
||||
pub left_value: Value<'i>,
|
||||
pub right_value: Value<'i>,
|
||||
pub left_value: ImmutableValue<'i>,
|
||||
pub right_value: ImmutableValue<'i>,
|
||||
pub instruction: Box<Instruction<'i>>,
|
||||
}
|
||||
|
||||
/// (fail 1337 "error message")
|
||||
/// (fail %last_error%)
|
||||
/// (fail value)
|
||||
#[derive(Serialize, Debug, PartialEq, Eq)]
|
||||
pub enum Fail<'i> {
|
||||
Scalar(ScalarWithLambda<'i>),
|
||||
Scalar(Scalar<'i>),
|
||||
ScalarWithLambda(ScalarWithLambda<'i>),
|
||||
Literal {
|
||||
ret_code: i64,
|
||||
error_message: &'i str,
|
||||
},
|
||||
CanonStream {
|
||||
name: &'i str,
|
||||
lambda: LambdaAST<'i>,
|
||||
},
|
||||
CanonStreamWithLambda(CanonStreamWithLambda<'i>),
|
||||
LastError,
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ impl<'i> Ap<'i> {
|
||||
impl<'i> Call<'i> {
|
||||
pub fn new(
|
||||
triplet: Triplet<'i>,
|
||||
args: Rc<Vec<Value<'i>>>,
|
||||
args: Rc<Vec<ImmutableValue<'i>>>,
|
||||
output: CallOutputValue<'i>,
|
||||
) -> Self {
|
||||
Self {
|
||||
@ -38,12 +38,12 @@ impl<'i> Call<'i> {
|
||||
|
||||
impl<'i> Canon<'i> {
|
||||
pub fn new(
|
||||
peer_pk: CallInstrValue<'i>,
|
||||
peer_id: ResolvableToPeerIdVariable<'i>,
|
||||
stream: Stream<'i>,
|
||||
canon_stream: CanonStream<'i>,
|
||||
) -> Self {
|
||||
Self {
|
||||
peer_pk,
|
||||
peer_id,
|
||||
stream,
|
||||
canon_stream,
|
||||
}
|
||||
@ -79,8 +79,8 @@ impl<'i> Xor<'i> {
|
||||
|
||||
impl<'i> Match<'i> {
|
||||
pub fn new(
|
||||
left_value: Value<'i>,
|
||||
right_value: Value<'i>,
|
||||
left_value: ImmutableValue<'i>,
|
||||
right_value: ImmutableValue<'i>,
|
||||
instruction: Box<Instruction<'i>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
@ -93,8 +93,8 @@ impl<'i> Match<'i> {
|
||||
|
||||
impl<'i> MisMatch<'i> {
|
||||
pub fn new(
|
||||
left_value: Value<'i>,
|
||||
right_value: Value<'i>,
|
||||
left_value: ImmutableValue<'i>,
|
||||
right_value: ImmutableValue<'i>,
|
||||
instruction: Box<Instruction<'i>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
@ -57,7 +57,7 @@ impl fmt::Display for Canon<'_> {
|
||||
write!(
|
||||
f,
|
||||
"canon {} {} {}",
|
||||
self.peer_pk, self.stream, self.canon_stream
|
||||
self.peer_id, self.stream, self.canon_stream
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -72,12 +72,13 @@ impl fmt::Display for Fail<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Fail::Scalar(scalar) => write!(f, "fail {}", scalar),
|
||||
Fail::ScalarWithLambda(scalar) => write!(f, "fail {}", scalar),
|
||||
Fail::Literal {
|
||||
ret_code,
|
||||
error_message,
|
||||
} => write!(f, r#"fail {} "{}""#, ret_code, error_message),
|
||||
Fail::CanonStream { name, lambda, .. } => {
|
||||
write!(f, "fail {}.$.{}", name, lambda)
|
||||
Fail::CanonStreamWithLambda(stream) => {
|
||||
write!(f, "fail {}", stream)
|
||||
}
|
||||
Fail::LastError => write!(f, "fail %last_error%"),
|
||||
}
|
||||
|
@ -14,14 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::ast::Value;
|
||||
use crate::ast::ImmutableValue;
|
||||
|
||||
use air_lambda_ast::LambdaAST;
|
||||
use air_lambda_ast::ValueAccessor;
|
||||
|
||||
#[test]
|
||||
// https://github.com/fluencelabs/aquavm/issues/263
|
||||
fn issue_263() {
|
||||
let val = Value::LastError(Some(
|
||||
let val = ImmutableValue::LastError(Some(
|
||||
LambdaAST::try_from_accessors(vec![ValueAccessor::FieldAccessByName {
|
||||
field_name: "message",
|
||||
}])
|
||||
|
@ -23,72 +23,59 @@ use air_lambda_parser::LambdaAST;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
/// A scalar value without lambda.
|
||||
/// A scalar value without a lambda.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct Scalar<'i> {
|
||||
pub name: &'i str,
|
||||
pub position: AirPos,
|
||||
}
|
||||
|
||||
/// A scalar value with possible lambda expression.
|
||||
/// A scalar value with a lambda expression.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct ScalarWithLambda<'i> {
|
||||
pub name: &'i str,
|
||||
#[serde(borrow)]
|
||||
pub lambda: Option<LambdaAST<'i>>,
|
||||
pub lambda: LambdaAST<'i>,
|
||||
pub position: AirPos,
|
||||
}
|
||||
|
||||
/// A stream without lambda.
|
||||
/// A stream without a lambda.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct Stream<'i> {
|
||||
pub name: &'i str,
|
||||
pub position: AirPos,
|
||||
}
|
||||
|
||||
/// A stream with possible lambda expression.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct StreamWithLambda<'i> {
|
||||
pub name: &'i str,
|
||||
#[serde(borrow)]
|
||||
pub lambda: Option<LambdaAST<'i>>,
|
||||
pub position: AirPos,
|
||||
}
|
||||
|
||||
/// A canonicalized stream without lambda.
|
||||
/// A canonicalized stream without a lambda.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct CanonStream<'i> {
|
||||
pub name: &'i str,
|
||||
pub position: AirPos,
|
||||
}
|
||||
|
||||
/// A canonicalized stream with lambda.
|
||||
/// A canonicalized stream with a lambda.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct CanonStreamWithLambda<'i> {
|
||||
pub name: &'i str,
|
||||
#[serde(borrow)]
|
||||
pub lambda: Option<LambdaAST<'i>>,
|
||||
pub lambda: LambdaAST<'i>,
|
||||
pub position: AirPos,
|
||||
}
|
||||
|
||||
/// A variable that could be either scalar or stream without lambda.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum Variable<'i> {
|
||||
pub enum ImmutableVariable<'i> {
|
||||
#[serde(borrow)]
|
||||
Scalar(Scalar<'i>),
|
||||
#[serde(borrow)]
|
||||
Stream(Stream<'i>),
|
||||
#[serde(borrow)]
|
||||
CanonStream(CanonStream<'i>),
|
||||
}
|
||||
|
||||
/// A variable that could be either scalar or stream with possible lambda expression.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum VariableWithLambda<'i> {
|
||||
pub enum ImmutableVariableWithLambda<'i> {
|
||||
#[serde(borrow)]
|
||||
Scalar(ScalarWithLambda<'i>),
|
||||
#[serde(borrow)]
|
||||
Stream(StreamWithLambda<'i>),
|
||||
#[serde(borrow)]
|
||||
CanonStream(CanonStreamWithLambda<'i>),
|
||||
}
|
||||
|
@ -16,10 +16,9 @@
|
||||
|
||||
use super::*;
|
||||
use air_lambda_parser::LambdaAST;
|
||||
use air_lambda_parser::ValueAccessor;
|
||||
|
||||
impl<'i> ScalarWithLambda<'i> {
|
||||
pub fn new(name: &'i str, lambda: Option<LambdaAST<'i>>, position: AirPos) -> Self {
|
||||
pub fn new(name: &'i str, lambda: LambdaAST<'i>, position: AirPos) -> Self {
|
||||
Self {
|
||||
name,
|
||||
lambda,
|
||||
@ -27,36 +26,13 @@ impl<'i> ScalarWithLambda<'i> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_value_path(
|
||||
#[cfg(test)]
|
||||
pub(crate) fn from_raw_lambda(
|
||||
name: &'i str,
|
||||
accessors: Vec<ValueAccessor<'i>>,
|
||||
lambda: Vec<air_lambda_parser::ValueAccessor<'i>>,
|
||||
position: AirPos,
|
||||
) -> Self {
|
||||
let lambda = LambdaAST::try_from_accessors(accessors).ok();
|
||||
Self {
|
||||
name,
|
||||
lambda,
|
||||
position,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i> StreamWithLambda<'i> {
|
||||
pub fn new(name: &'i str, lambda: Option<LambdaAST<'i>>, position: AirPos) -> Self {
|
||||
Self {
|
||||
name,
|
||||
lambda,
|
||||
position,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn from_value_path(
|
||||
name: &'i str,
|
||||
accessors: Vec<ValueAccessor<'i>>,
|
||||
position: AirPos,
|
||||
) -> Self {
|
||||
let lambda = LambdaAST::try_from_accessors(accessors).ok();
|
||||
let lambda = LambdaAST::try_from_accessors(lambda).unwrap();
|
||||
Self {
|
||||
name,
|
||||
lambda,
|
||||
@ -72,7 +48,7 @@ impl<'i> CanonStream<'i> {
|
||||
}
|
||||
|
||||
impl<'i> CanonStreamWithLambda<'i> {
|
||||
pub fn new(name: &'i str, lambda: Option<LambdaAST<'i>>, position: AirPos) -> Self {
|
||||
pub fn new(name: &'i str, lambda: LambdaAST<'i>, position: AirPos) -> Self {
|
||||
Self {
|
||||
name,
|
||||
lambda,
|
||||
@ -93,82 +69,53 @@ impl<'i> Stream<'i> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i> Variable<'i> {
|
||||
impl<'i> ImmutableVariable<'i> {
|
||||
pub fn scalar(name: &'i str, position: AirPos) -> Self {
|
||||
Self::Scalar(Scalar::new(name, position))
|
||||
}
|
||||
|
||||
pub fn stream(name: &'i str, position: AirPos) -> Self {
|
||||
Self::Stream(Stream::new(name, position))
|
||||
pub fn canon_stream(name: &'i str, position: AirPos) -> Self {
|
||||
Self::CanonStream(CanonStream::new(name, position))
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &'i str {
|
||||
match self {
|
||||
Variable::Scalar(scalar) => scalar.name,
|
||||
Variable::Stream(stream) => stream.name,
|
||||
Variable::CanonStream(stream) => stream.name,
|
||||
ImmutableVariable::Scalar(scalar) => scalar.name,
|
||||
ImmutableVariable::CanonStream(stream) => stream.name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i> VariableWithLambda<'i> {
|
||||
pub fn scalar(name: &'i str, position: AirPos) -> Self {
|
||||
Self::Scalar(ScalarWithLambda::new(name, None, position))
|
||||
impl<'i> ImmutableVariableWithLambda<'i> {
|
||||
pub fn scalar(name: &'i str, lambda: LambdaAST<'i>, position: AirPos) -> Self {
|
||||
Self::Scalar(ScalarWithLambda::new(name, lambda, position))
|
||||
}
|
||||
|
||||
pub fn scalar_wl(name: &'i str, lambda: LambdaAST<'i>, position: AirPos) -> Self {
|
||||
Self::Scalar(ScalarWithLambda::new(name, Some(lambda), position))
|
||||
}
|
||||
|
||||
pub fn stream(name: &'i str, position: AirPos) -> Self {
|
||||
Self::Stream(StreamWithLambda::new(name, None, position))
|
||||
}
|
||||
|
||||
pub fn stream_wl(name: &'i str, lambda: LambdaAST<'i>, position: AirPos) -> Self {
|
||||
Self::Stream(StreamWithLambda::new(name, Some(lambda), position))
|
||||
}
|
||||
|
||||
pub fn canon_stream(name: &'i str, position: AirPos) -> Self {
|
||||
Self::CanonStream(CanonStreamWithLambda::new(name, None, position))
|
||||
}
|
||||
|
||||
pub fn canon_stream_wl(name: &'i str, lambda: LambdaAST<'i>, position: AirPos) -> Self {
|
||||
Self::CanonStream(CanonStreamWithLambda::new(name, Some(lambda), position))
|
||||
pub fn canon_stream(name: &'i str, lambda: LambdaAST<'i>, position: AirPos) -> Self {
|
||||
Self::CanonStream(CanonStreamWithLambda::new(name, lambda, position))
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &'i str {
|
||||
match self {
|
||||
VariableWithLambda::Scalar(scalar) => scalar.name,
|
||||
VariableWithLambda::Stream(stream) => stream.name,
|
||||
VariableWithLambda::CanonStream(canon_stream) => canon_stream.name,
|
||||
ImmutableVariableWithLambda::Scalar(scalar) => scalar.name,
|
||||
ImmutableVariableWithLambda::CanonStream(canon_stream) => canon_stream.name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lambda(&self) -> &Option<LambdaAST<'i>> {
|
||||
pub fn lambda(&self) -> &LambdaAST<'i> {
|
||||
match self {
|
||||
VariableWithLambda::Scalar(scalar) => &scalar.lambda,
|
||||
VariableWithLambda::Stream(stream) => &stream.lambda,
|
||||
VariableWithLambda::CanonStream(canon_stream) => &canon_stream.lambda,
|
||||
ImmutableVariableWithLambda::Scalar(scalar) => &scalar.lambda,
|
||||
ImmutableVariableWithLambda::CanonStream(canon_stream) => &canon_stream.lambda,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(test)]
|
||||
pub(crate) fn from_raw_value_path(
|
||||
name: &'i str,
|
||||
lambda: Vec<ValueAccessor<'i>>,
|
||||
lambda: Vec<air_lambda_parser::ValueAccessor<'i>>,
|
||||
position: AirPos,
|
||||
) -> Self {
|
||||
let scalar = ScalarWithLambda::from_value_path(name, lambda, position);
|
||||
let scalar = ScalarWithLambda::from_raw_lambda(name, lambda, position);
|
||||
Self::Scalar(scalar)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn from_raw_lambda_stream(
|
||||
name: &'i str,
|
||||
lambda: Vec<ValueAccessor<'i>>,
|
||||
position: AirPos,
|
||||
) -> Self {
|
||||
let stream = StreamWithLambda::from_value_path(name, lambda, position);
|
||||
Self::Stream(stream)
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,7 @@ impl fmt::Display for Scalar<'_> {
|
||||
|
||||
impl fmt::Display for ScalarWithLambda<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match &self.lambda {
|
||||
Some(lambda) => write!(f, "{}{}", self.name, lambda),
|
||||
None => write!(f, "{}", self.name),
|
||||
}
|
||||
write!(f, "{}{}", self.name, self.lambda)
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,43 +41,29 @@ impl fmt::Display for CanonStream<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for StreamWithLambda<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match &self.lambda {
|
||||
Some(lambda) => write!(f, "{}{}", self.name, lambda),
|
||||
None => write!(f, "{}", self.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CanonStreamWithLambda<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match &self.lambda {
|
||||
Some(lambda) => write!(f, "{}{}", self.name, lambda),
|
||||
None => write!(f, "{}", self.name),
|
||||
}
|
||||
write!(f, "{}{}", self.name, self.lambda)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Variable<'_> {
|
||||
impl fmt::Display for ImmutableVariable<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use Variable::*;
|
||||
use ImmutableVariable::*;
|
||||
|
||||
match self {
|
||||
Scalar(scalar) => write!(f, "{}", scalar),
|
||||
Stream(stream) => write!(f, "{}", stream),
|
||||
CanonStream(canon_stream) => write!(f, "{}", canon_stream),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for VariableWithLambda<'_> {
|
||||
impl fmt::Display for ImmutableVariableWithLambda<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use VariableWithLambda::*;
|
||||
use ImmutableVariableWithLambda::*;
|
||||
|
||||
match self {
|
||||
Scalar(scalar) => write!(f, "{}", scalar),
|
||||
Stream(stream) => write!(f, "{}", stream),
|
||||
CanonStream(canon_stream) => write!(f, "{}", canon_stream),
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ Instr: Box<Instruction<'input>> = {
|
||||
Box::new(Instruction::Call(call))
|
||||
},
|
||||
|
||||
<left: @L> "(" canon <peer_pk:CallInstrValue> <stream:StreamArgument> <canon_stream:CanonStreamArgument> ")" <right: @R> => {
|
||||
let canon = Canon::new(peer_pk, stream, canon_stream);
|
||||
<left: @L> "(" canon <peer_id:ResolvableToPeerIdVariable> <stream:StreamArgument> <canon_stream:CanonStreamArgument> ")" <right: @R> => {
|
||||
let canon = Canon::new(peer_id, stream, canon_stream);
|
||||
|
||||
let span = Span::new(left, right);
|
||||
validator.met_canon(&canon, span);
|
||||
@ -113,13 +113,13 @@ Instr: Box<Instruction<'input>> = {
|
||||
! => { errors.push(<>); Box::new(Instruction::Error) },
|
||||
}
|
||||
|
||||
Args: Vec<Value<'input>> = {
|
||||
Args: Vec<ImmutableValue<'input>> = {
|
||||
"[" <args:(<Arg>)*> "]" => args
|
||||
}
|
||||
|
||||
Triplet: Triplet<'input> = {
|
||||
<peer_pk:PeerId> "(" <service_id:ServiceId> <function_name:Function> ")" => Triplet {
|
||||
peer_pk,
|
||||
<peer_id:PeerId> "(" <service_id:ServiceId> <function_name:Function> ")" => Triplet {
|
||||
peer_id,
|
||||
service_id,
|
||||
function_name
|
||||
}
|
||||
@ -136,42 +136,42 @@ CallOutput: CallOutputValue<'input> = {
|
||||
};
|
||||
|
||||
FailBody: Fail<'input> = {
|
||||
<scalar:Scalar> => Fail::Scalar(ScalarWithLambda::new(scalar.0, None, scalar.1)),
|
||||
<scalar:ScalarWithLambda> => Fail::Scalar(ScalarWithLambda::new(scalar.0, Some(scalar.1), scalar.2)),
|
||||
<scalar:Scalar> => Fail::Scalar(Scalar::new(scalar.0, scalar.1)),
|
||||
<scalar:ScalarWithLambda> => Fail::ScalarWithLambda(ScalarWithLambda::new(scalar.0, scalar.1, scalar.2)),
|
||||
<ret_code:I64> <error_message:Literal> => Fail::Literal {
|
||||
ret_code,
|
||||
error_message,
|
||||
},
|
||||
<canon_stream:CanonStreamWithLambda> => Fail::CanonStream {
|
||||
name: canon_stream.0,
|
||||
lambda: canon_stream.1,
|
||||
},
|
||||
<canon_stream:CanonStreamWithLambda> => Fail::CanonStreamWithLambda(CanonStreamWithLambda::new(canon_stream.0, canon_stream.1, canon_stream.2)),
|
||||
<left: @L> <l:LastError> <right: @R> => {
|
||||
Fail::LastError
|
||||
}
|
||||
}
|
||||
|
||||
FoldScalarIterable: FoldScalarIterable<'input> = {
|
||||
<scalar:Scalar> => FoldScalarIterable::Scalar(ScalarWithLambda::new(scalar.0, None, scalar.1)),
|
||||
<scalar:ScalarWithLambda> => FoldScalarIterable::Scalar(ScalarWithLambda::new(scalar.0, Some(scalar.1), scalar.2)),
|
||||
<scalar:Scalar> => FoldScalarIterable::Scalar(Scalar::new(scalar.0, scalar.1)),
|
||||
<scalar:ScalarWithLambda> => FoldScalarIterable::ScalarWithLambda(ScalarWithLambda::new(scalar.0, scalar.1, scalar.2)),
|
||||
<canon_stream:CanonStream> => FoldScalarIterable::CanonStream(CanonStream::new(canon_stream.0, canon_stream.1)),
|
||||
"[" "]" => FoldScalarIterable::EmptyArray,
|
||||
};
|
||||
|
||||
Function = CallInstrValue;
|
||||
PeerId = CallInstrValue;
|
||||
ServiceId = CallInstrValue;
|
||||
PeerId = ResolvableToPeerIdVariable;
|
||||
Function = ResolvableToStringVariable;
|
||||
ServiceId = ResolvableToStringVariable;
|
||||
|
||||
// TODO: call triplet should receive only streams with lambdas
|
||||
CallInstrValue: CallInstrValue<'input> = {
|
||||
InitPeerId => CallInstrValue::InitPeerId,
|
||||
<l:Literal> => CallInstrValue::Literal(l),
|
||||
<scalar:Scalar> => CallInstrValue::Variable(VariableWithLambda::scalar(scalar.0, scalar.1)),
|
||||
<scalar:ScalarWithLambda> => CallInstrValue::Variable(VariableWithLambda::scalar_wl(scalar.0, scalar.1, scalar.2)),
|
||||
<stream:Stream> => CallInstrValue::Variable(VariableWithLambda::stream(stream.0, stream.1)),
|
||||
<stream:StreamWithLambda> => CallInstrValue::Variable(VariableWithLambda::stream_wl(stream.0, stream.1, stream.2)),
|
||||
<canon_stream:CanonStream> => CallInstrValue::Variable(VariableWithLambda::canon_stream(canon_stream.0, canon_stream.1)),
|
||||
<canon_stream:CanonStreamWithLambda> => CallInstrValue::Variable(VariableWithLambda::canon_stream_wl(canon_stream.0, canon_stream.1, canon_stream.2)),
|
||||
ResolvableToPeerIdVariable: ResolvableToPeerIdVariable<'input> = {
|
||||
InitPeerId => ResolvableToPeerIdVariable::InitPeerId,
|
||||
<literal:Literal> => ResolvableToPeerIdVariable::Literal(literal),
|
||||
<scalar:Scalar> => ResolvableToPeerIdVariable::Scalar(Scalar::new(scalar.0, scalar.1)),
|
||||
<scalar:ScalarWithLambda> => ResolvableToPeerIdVariable::ScalarWithLambda(ScalarWithLambda::new(scalar.0, scalar.1, scalar.2)),
|
||||
<canon_stream:CanonStreamWithLambda> => ResolvableToPeerIdVariable::CanonStreamWithLambda(CanonStreamWithLambda::new(canon_stream.0, canon_stream.1, canon_stream.2)),
|
||||
}
|
||||
|
||||
ResolvableToStringVariable: ResolvableToStringVariable<'input> = {
|
||||
<literal:Literal> => ResolvableToStringVariable::Literal(literal),
|
||||
<scalar:Scalar> => ResolvableToStringVariable::Scalar(Scalar::new(scalar.0, scalar.1)),
|
||||
<scalar:ScalarWithLambda> => ResolvableToStringVariable::ScalarWithLambda(ScalarWithLambda::new(scalar.0, scalar.1, scalar.2)),
|
||||
<canon_stream:CanonStreamWithLambda> => ResolvableToStringVariable::CanonStreamWithLambda(CanonStreamWithLambda::new(canon_stream.0, canon_stream.1, canon_stream.2)),
|
||||
}
|
||||
|
||||
NewArgument: NewArgument<'input> = {
|
||||
@ -187,22 +187,20 @@ Number: Number = {
|
||||
|
||||
Arg = Value;
|
||||
|
||||
Value: Value<'input> = {
|
||||
InitPeerId => Value::InitPeerId,
|
||||
<LastError> => Value::LastError(None),
|
||||
<le:LastErrorWithLambda> => Value::LastError(Some(le)),
|
||||
<l:Literal> => Value::Literal(l),
|
||||
Timestamp => Value::Timestamp,
|
||||
TTL => Value::TTL,
|
||||
<n:Number> => Value::Number(n),
|
||||
<b:Boolean> => Value::Boolean(b),
|
||||
"[" "]" => Value::EmptyArray,
|
||||
<scalar:Scalar> => Value::Variable(VariableWithLambda::scalar(scalar.0, scalar.1)),
|
||||
<scalar:ScalarWithLambda> => Value::Variable(VariableWithLambda::scalar_wl(scalar.0, scalar.1, scalar.2)),
|
||||
<stream:Stream> => Value::Variable(VariableWithLambda::stream(stream.0, stream.1)),
|
||||
<stream:StreamWithLambda> => Value::Variable(VariableWithLambda::stream_wl(stream.0, stream.1, stream.2)),
|
||||
<canon_stream:CanonStream> => Value::Variable(VariableWithLambda::canon_stream(canon_stream.0, canon_stream.1)),
|
||||
<canon_stream:CanonStreamWithLambda> => Value::Variable(VariableWithLambda::canon_stream_wl(canon_stream.0, canon_stream.1, canon_stream.2)),
|
||||
Value: ImmutableValue<'input> = {
|
||||
InitPeerId => ImmutableValue::InitPeerId,
|
||||
<LastError> => ImmutableValue::LastError(None),
|
||||
<le:LastErrorWithLambda> => ImmutableValue::LastError(Some(le)),
|
||||
<l:Literal> => ImmutableValue::Literal(l),
|
||||
Timestamp => ImmutableValue::Timestamp,
|
||||
TTL => ImmutableValue::TTL,
|
||||
<n:Number> => ImmutableValue::Number(n),
|
||||
<b:Boolean> => ImmutableValue::Boolean(b),
|
||||
"[" "]" => ImmutableValue::EmptyArray,
|
||||
<scalar:Scalar> => ImmutableValue::Variable(ImmutableVariable::scalar(scalar.0, scalar.1)),
|
||||
<scalar:ScalarWithLambda> => ImmutableValue::VariableWithLambda(ImmutableVariableWithLambda::scalar(scalar.0, scalar.1, scalar.2)),
|
||||
<canon_stream:CanonStream> => ImmutableValue::Variable(ImmutableVariable::canon_stream(canon_stream.0, canon_stream.1)),
|
||||
<canon_stream:CanonStreamWithLambda> => ImmutableValue::VariableWithLambda(ImmutableVariableWithLambda::canon_stream(canon_stream.0, canon_stream.1, canon_stream.2)),
|
||||
}
|
||||
|
||||
ApArgument: ApArgument<'input> = {
|
||||
@ -215,10 +213,10 @@ ApArgument: ApArgument<'input> = {
|
||||
<n:Number> => ApArgument::Number(n),
|
||||
<b:Boolean> => ApArgument::Boolean(b),
|
||||
"[" "]" => ApArgument::EmptyArray,
|
||||
<scalar:Scalar> => ApArgument::Scalar(ScalarWithLambda::new(scalar.0, None, scalar.1)),
|
||||
<scalar:ScalarWithLambda> => ApArgument::Scalar(ScalarWithLambda::new(scalar.0, Some(scalar.1), scalar.2)),
|
||||
<canon_stream:CanonStream> => ApArgument::CanonStream(CanonStreamWithLambda::new(canon_stream.0, None, canon_stream.1)),
|
||||
<canon_stream:CanonStreamWithLambda> => ApArgument::CanonStream(CanonStreamWithLambda::new(canon_stream.0, Some(canon_stream.1), canon_stream.2)),
|
||||
<scalar:Scalar> => ApArgument::Scalar(Scalar::new(scalar.0, scalar.1)),
|
||||
<scalar:ScalarWithLambda> => ApArgument::ScalarWithLambda(ScalarWithLambda::new(scalar.0, scalar.1, scalar.2)),
|
||||
<canon_stream:CanonStream> => ApArgument::CanonStream(CanonStream::new(canon_stream.0, canon_stream.1)),
|
||||
<canon_stream:CanonStreamWithLambda> => ApArgument::CanonStreamWithLambda(CanonStreamWithLambda::new(canon_stream.0, canon_stream.1, canon_stream.2)),
|
||||
}
|
||||
|
||||
StreamArgument: Stream<'input> = {
|
||||
@ -242,7 +240,6 @@ extern {
|
||||
Scalar => Token::Scalar { name:<&'input str>, position: <AirPos> },
|
||||
ScalarWithLambda => Token::ScalarWithLambda { name: <&'input str>, lambda: <LambdaAST<'input>>, position: <AirPos> },
|
||||
Stream => Token::Stream { name: <&'input str>, position: <AirPos> },
|
||||
StreamWithLambda => Token::StreamWithLambda {name: <&'input str>, lambda:<LambdaAST<'input>>, position: <AirPos>},
|
||||
CanonStream => Token::CanonStream { name: <&'input str>, position: <AirPos> },
|
||||
CanonStreamWithLambda => Token::CanonStreamWithLambda {name: <&'input str>, lambda:<LambdaAST<'input>>, position: <AirPos>},
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -215,25 +215,6 @@ fn canon_stream() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stream_with_functor() {
|
||||
let stream_name = "$stream";
|
||||
let stream_with_functor: String = f!("{stream_name}.length");
|
||||
|
||||
lexer_test(
|
||||
&stream_with_functor,
|
||||
Single(Ok((
|
||||
0.into(),
|
||||
Token::StreamWithLambda {
|
||||
name: stream_name,
|
||||
lambda: LambdaAST::Functor(Functor::Length),
|
||||
position: 0.into(),
|
||||
},
|
||||
stream_with_functor.len().into(),
|
||||
))),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn canon_stream_with_functor() {
|
||||
let canon_stream_name = "#canon_stream";
|
||||
|
@ -157,7 +157,7 @@ fn ap_with_canon_stream() {
|
||||
|
||||
let actual = parse(&source_code);
|
||||
let expected = ap(
|
||||
ApArgument::CanonStream(CanonStreamWithLambda::new(canon_stream, None, 13.into())),
|
||||
ApArgument::CanonStream(CanonStream::new(canon_stream, 13.into())),
|
||||
ApResult::Scalar(Scalar::new(scalar, 27.into())),
|
||||
);
|
||||
|
||||
@ -174,11 +174,9 @@ fn ap_with_canon_stream_with_lambda() {
|
||||
|
||||
let actual = parse(&source_code);
|
||||
let expected = ap(
|
||||
ApArgument::CanonStream(CanonStreamWithLambda::new(
|
||||
ApArgument::CanonStreamWithLambda(CanonStreamWithLambda::new(
|
||||
canon_stream,
|
||||
Some(
|
||||
LambdaAST::try_from_accessors(vec![ValueAccessor::ArrayAccess { idx: 0 }]).unwrap(),
|
||||
),
|
||||
LambdaAST::try_from_accessors(vec![ValueAccessor::ArrayAccess { idx: 0 }]).unwrap(),
|
||||
13.into(),
|
||||
)),
|
||||
ApResult::Scalar(Scalar::new(scalar, 33.into())),
|
||||
|
@ -34,16 +34,16 @@ fn parse_json_path() {
|
||||
|
||||
let instruction = parse(source_code);
|
||||
let expected = call(
|
||||
CallInstrValue::Variable(VariableWithLambda::from_raw_value_path(
|
||||
ResolvableToPeerIdVariable::ScalarWithLambda(ScalarWithLambda::from_raw_lambda(
|
||||
"peer_id",
|
||||
vec![ValueAccessor::FieldAccessByName { field_name: "a" }],
|
||||
15.into(),
|
||||
)),
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("function_name"),
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("function_name"),
|
||||
Rc::new(vec![
|
||||
Value::Literal("hello"),
|
||||
Value::Variable(VariableWithLambda::scalar("name", 68.into())),
|
||||
ImmutableValue::Literal("hello"),
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("name", 68.into())),
|
||||
]),
|
||||
CallOutputValue::Stream(Stream::new("$void", 74.into())),
|
||||
);
|
||||
@ -58,13 +58,13 @@ fn parse_empty_array() {
|
||||
|
||||
let actual = parse(source_code);
|
||||
let expected = call(
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("peer_id", 15.into())),
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("service_id", 24.into())),
|
||||
CallInstrValue::Literal("function_name"),
|
||||
ResolvableToPeerIdVariable::Scalar(Scalar::new("peer_id", 15.into())),
|
||||
ResolvableToStringVariable::Scalar(Scalar::new("service_id", 24.into())),
|
||||
ResolvableToStringVariable::Literal("function_name"),
|
||||
Rc::new(vec![
|
||||
Value::Literal(""),
|
||||
Value::EmptyArray,
|
||||
Value::Variable(VariableWithLambda::scalar("arg", 59.into())),
|
||||
ImmutableValue::Literal(""),
|
||||
ImmutableValue::EmptyArray,
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("arg", 59.into())),
|
||||
]),
|
||||
CallOutputValue::None,
|
||||
);
|
||||
@ -80,13 +80,13 @@ fn parse_empty_array_2() {
|
||||
|
||||
let actual = parse(source_code);
|
||||
let expected = call(
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("peer_id", 15.into())),
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("function_name"),
|
||||
ResolvableToPeerIdVariable::Scalar(Scalar::new("peer_id", 15.into())),
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("function_name"),
|
||||
Rc::new(vec![
|
||||
Value::Variable(VariableWithLambda::scalar("k", 55.into())),
|
||||
Value::EmptyArray,
|
||||
Value::EmptyArray,
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("k", 55.into())),
|
||||
ImmutableValue::EmptyArray,
|
||||
ImmutableValue::EmptyArray,
|
||||
]),
|
||||
CallOutputValue::None,
|
||||
);
|
||||
@ -146,36 +146,6 @@ fn parse_undefined_stream_without_json_path() {
|
||||
assert!(errors.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_undefined_stream_with_lambda() {
|
||||
let source_code = r#"
|
||||
(call "" ("" "") [$stream.$.json_path])
|
||||
"#;
|
||||
|
||||
let lexer = crate::AIRLexer::new(source_code);
|
||||
|
||||
let parser = crate::AIRParser::new();
|
||||
let mut errors = Vec::new();
|
||||
let mut validator = crate::parser::VariableValidator::new();
|
||||
parser
|
||||
.parse(source_code, &mut errors, &mut validator, lexer)
|
||||
.expect("parser shouldn't fail");
|
||||
|
||||
let errors = validator.finalize();
|
||||
|
||||
assert_eq!(errors.len(), 1);
|
||||
let error = &errors[0].error;
|
||||
let parser_error = match error {
|
||||
ParseError::User { error } => error,
|
||||
_ => panic!("unexpected error type"),
|
||||
};
|
||||
|
||||
assert!(matches!(
|
||||
parser_error,
|
||||
ParserError::UndefinedVariable { .. }
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_lambda_complex() {
|
||||
let source_code = r#"
|
||||
@ -187,18 +157,18 @@ fn parse_lambda_complex() {
|
||||
let instruction = parse(source_code);
|
||||
let expected = seq(
|
||||
call(
|
||||
CallInstrValue::Variable(VariableWithLambda::from_raw_value_path(
|
||||
ResolvableToPeerIdVariable::ScalarWithLambda(ScalarWithLambda::from_raw_lambda(
|
||||
"m",
|
||||
vec![ValueAccessor::ArrayAccess { idx: 1 }],
|
||||
32.into(),
|
||||
)),
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("function_name"),
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("function_name"),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::Scalar(Scalar::new("void", 75.into())),
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Variable(VariableWithLambda::from_raw_value_path(
|
||||
ResolvableToPeerIdVariable::ScalarWithLambda(ScalarWithLambda::from_raw_lambda(
|
||||
"m",
|
||||
vec![
|
||||
ValueAccessor::FieldAccessByName { field_name: "abc" },
|
||||
@ -211,8 +181,8 @@ fn parse_lambda_complex() {
|
||||
],
|
||||
99.into(),
|
||||
)),
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("function_name"),
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("function_name"),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::Scalar(Scalar::new("void", 162.into())),
|
||||
),
|
||||
@ -231,7 +201,7 @@ fn parse_lambda_with_scalars_complex() {
|
||||
let instruction = parse(source_code);
|
||||
let expected = seq(
|
||||
call(
|
||||
CallInstrValue::Variable(VariableWithLambda::from_raw_value_path(
|
||||
ResolvableToPeerIdVariable::ScalarWithLambda(ScalarWithLambda::from_raw_lambda(
|
||||
"m",
|
||||
vec![
|
||||
ValueAccessor::ArrayAccess { idx: 1 },
|
||||
@ -244,13 +214,13 @@ fn parse_lambda_with_scalars_complex() {
|
||||
],
|
||||
32.into(),
|
||||
)),
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("function_name"),
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("function_name"),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::Scalar(Scalar::new("void", 97.into())),
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Variable(VariableWithLambda::from_raw_value_path(
|
||||
ResolvableToPeerIdVariable::ScalarWithLambda(ScalarWithLambda::from_raw_lambda(
|
||||
"m",
|
||||
vec![
|
||||
ValueAccessor::FieldAccessByName { field_name: "abc" },
|
||||
@ -269,8 +239,8 @@ fn parse_lambda_with_scalars_complex() {
|
||||
],
|
||||
121.into(),
|
||||
)),
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("function_name"),
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("function_name"),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::Scalar(Scalar::new("void", 205.into())),
|
||||
),
|
||||
@ -285,17 +255,17 @@ fn json_path_square_braces() {
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = call(
|
||||
CallInstrValue::Variable(VariableWithLambda::from_raw_value_path(
|
||||
ResolvableToPeerIdVariable::ScalarWithLambda(ScalarWithLambda::from_raw_lambda(
|
||||
"u",
|
||||
vec![ValueAccessor::FieldAccessByName {
|
||||
field_name: "peer_id",
|
||||
}],
|
||||
15.into(),
|
||||
)),
|
||||
CallInstrValue::Literal("return"),
|
||||
CallInstrValue::Literal(""),
|
||||
ResolvableToStringVariable::Literal("return"),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![
|
||||
Value::Variable(VariableWithLambda::from_raw_value_path(
|
||||
ImmutableValue::VariableWithLambda(ImmutableVariableWithLambda::from_raw_value_path(
|
||||
"u",
|
||||
vec![
|
||||
ValueAccessor::ArrayAccess { idx: 1 },
|
||||
@ -306,7 +276,7 @@ fn json_path_square_braces() {
|
||||
],
|
||||
43.into(),
|
||||
)),
|
||||
Value::Variable(VariableWithLambda::from_raw_value_path(
|
||||
ImmutableValue::VariableWithLambda(ImmutableVariableWithLambda::from_raw_value_path(
|
||||
"u",
|
||||
vec![ValueAccessor::FieldAccessByName { field_name: "name" }],
|
||||
64.into(),
|
||||
@ -333,16 +303,16 @@ fn parse_init_peer_id() {
|
||||
let instruction = parse(&source_code);
|
||||
let expected = seq(
|
||||
call(
|
||||
CallInstrValue::Literal(peer_id),
|
||||
CallInstrValue::Literal("local_service_id"),
|
||||
CallInstrValue::Literal("local_fn_name"),
|
||||
ResolvableToPeerIdVariable::Literal(peer_id),
|
||||
ResolvableToStringVariable::Literal("local_service_id"),
|
||||
ResolvableToStringVariable::Literal("local_fn_name"),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
),
|
||||
call(
|
||||
CallInstrValue::InitPeerId,
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("fn_name"),
|
||||
ResolvableToPeerIdVariable::InitPeerId,
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("fn_name"),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
),
|
||||
@ -359,10 +329,10 @@ fn parse_timestamp() {
|
||||
|
||||
let instruction = parse(source_code);
|
||||
let expected = call(
|
||||
CallInstrValue::Literal("peer_id"),
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("fn_name"),
|
||||
Rc::new(vec![Value::Timestamp]),
|
||||
ResolvableToPeerIdVariable::Literal("peer_id"),
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("fn_name"),
|
||||
Rc::new(vec![ImmutableValue::Timestamp]),
|
||||
CallOutputValue::None,
|
||||
);
|
||||
|
||||
@ -377,10 +347,10 @@ fn parse_ttl() {
|
||||
|
||||
let instruction = parse(source_code);
|
||||
let expected = call(
|
||||
CallInstrValue::Literal("peer_id"),
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("fn_name"),
|
||||
Rc::new(vec![Value::TTL]),
|
||||
ResolvableToPeerIdVariable::Literal("peer_id"),
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("fn_name"),
|
||||
Rc::new(vec![ImmutableValue::TTL]),
|
||||
CallOutputValue::None,
|
||||
);
|
||||
|
||||
@ -400,10 +370,10 @@ fn parse_last_error() {
|
||||
let instruction = parse(&source_code);
|
||||
let expected = seq(
|
||||
call(
|
||||
CallInstrValue::InitPeerId,
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("fn_name"),
|
||||
Rc::new(vec![Value::LastError(None)]),
|
||||
ResolvableToPeerIdVariable::InitPeerId,
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("fn_name"),
|
||||
Rc::new(vec![ImmutableValue::LastError(None)]),
|
||||
CallOutputValue::None,
|
||||
),
|
||||
null(),
|
||||
@ -423,13 +393,12 @@ fn canon_stream_in_args() {
|
||||
|
||||
let instruction = parse(&source_code);
|
||||
let expected = call(
|
||||
CallInstrValue::InitPeerId,
|
||||
CallInstrValue::Literal(service_id),
|
||||
CallInstrValue::Literal(function_name),
|
||||
Rc::new(vec![Value::Variable(VariableWithLambda::canon_stream(
|
||||
canon_stream,
|
||||
66.into(),
|
||||
))]),
|
||||
ResolvableToPeerIdVariable::InitPeerId,
|
||||
ResolvableToStringVariable::Literal(service_id),
|
||||
ResolvableToStringVariable::Literal(function_name),
|
||||
Rc::new(vec![ImmutableValue::Variable(
|
||||
ImmutableVariable::canon_stream(canon_stream, 66.into()),
|
||||
)]),
|
||||
CallOutputValue::None,
|
||||
);
|
||||
|
||||
@ -445,16 +414,20 @@ fn canon_stream_in_triplet() {
|
||||
(call {canon_stream} ("{service_id}" "{function_name}") [])
|
||||
"#);
|
||||
|
||||
let instruction = parse(&source_code);
|
||||
let expected = call(
|
||||
CallInstrValue::Variable(VariableWithLambda::canon_stream(canon_stream, 19.into())),
|
||||
CallInstrValue::Literal(service_id),
|
||||
CallInstrValue::Literal(function_name),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
);
|
||||
let lexer = crate::AIRLexer::new(&source_code);
|
||||
|
||||
assert_eq!(instruction, expected);
|
||||
let parser = crate::AIRParser::new();
|
||||
let mut errors = Vec::new();
|
||||
let mut validator = crate::parser::VariableValidator::new();
|
||||
parser
|
||||
.parse(&source_code, &mut errors, &mut validator, lexer)
|
||||
.expect("parser shouldn't fail");
|
||||
|
||||
assert_eq!(errors.len(), 1);
|
||||
assert!(matches!(
|
||||
&errors[0].error,
|
||||
ParseError::UnrecognizedToken { .. }
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -469,7 +442,7 @@ fn canon_stream_with_lambda_in_triplet() {
|
||||
|
||||
let instruction = parse(&source_code);
|
||||
let expected = call(
|
||||
CallInstrValue::Variable(VariableWithLambda::canon_stream_wl(
|
||||
ResolvableToPeerIdVariable::CanonStreamWithLambda(CanonStreamWithLambda::new(
|
||||
canon_stream,
|
||||
LambdaAST::try_from_accessors(vec![
|
||||
ValueAccessor::ArrayAccess { idx: 0 },
|
||||
@ -478,8 +451,8 @@ fn canon_stream_with_lambda_in_triplet() {
|
||||
.unwrap(),
|
||||
19.into(),
|
||||
)),
|
||||
CallInstrValue::Literal(service_id),
|
||||
CallInstrValue::Literal(function_name),
|
||||
ResolvableToStringVariable::Literal(service_id),
|
||||
ResolvableToStringVariable::Literal(function_name),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
);
|
||||
@ -503,24 +476,24 @@ fn seq_par_call() {
|
||||
let expected = seq(
|
||||
par(
|
||||
call(
|
||||
CallInstrValue::Literal(peer_id),
|
||||
CallInstrValue::Literal("local_service_id"),
|
||||
CallInstrValue::Literal("local_fn_name"),
|
||||
ResolvableToPeerIdVariable::Literal(peer_id),
|
||||
ResolvableToStringVariable::Literal("local_service_id"),
|
||||
ResolvableToStringVariable::Literal("local_fn_name"),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::Scalar(Scalar::new("result_1", 108.into())),
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Literal(peer_id),
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("fn_name"),
|
||||
ResolvableToPeerIdVariable::Literal(peer_id),
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("fn_name"),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::Scalar(Scalar::new("g", 183.into())),
|
||||
),
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Literal(peer_id),
|
||||
CallInstrValue::Literal("local_service_id"),
|
||||
CallInstrValue::Literal("local_fn_name"),
|
||||
ResolvableToPeerIdVariable::Literal(peer_id),
|
||||
ResolvableToStringVariable::Literal("local_service_id"),
|
||||
ResolvableToStringVariable::Literal("local_fn_name"),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::Scalar(Scalar::new("result_2", 273.into())),
|
||||
),
|
||||
@ -558,47 +531,50 @@ fn seq_with_empty_and_dash() {
|
||||
seq(
|
||||
seq(
|
||||
call(
|
||||
CallInstrValue::Literal("set_variables"),
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
Rc::new(vec![Value::Literal("module-bytes")]),
|
||||
ResolvableToPeerIdVariable::Literal("set_variables"),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![ImmutableValue::Literal("module-bytes")]),
|
||||
CallOutputValue::Scalar(Scalar::new("module-bytes", 119.into())),
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Literal("set_variables"),
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
Rc::new(vec![Value::Literal("module_config")]),
|
||||
ResolvableToPeerIdVariable::Literal("set_variables"),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![ImmutableValue::Literal("module_config")]),
|
||||
CallOutputValue::Scalar(Scalar::new("module_config", 201.into())),
|
||||
),
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Literal("set_variables"),
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
Rc::new(vec![Value::Literal("blueprint")]),
|
||||
ResolvableToPeerIdVariable::Literal("set_variables"),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![ImmutableValue::Literal("blueprint")]),
|
||||
CallOutputValue::Scalar(Scalar::new("blueprint", 294.into())),
|
||||
),
|
||||
),
|
||||
seq(
|
||||
call(
|
||||
CallInstrValue::Literal("A"),
|
||||
CallInstrValue::Literal("add_module"),
|
||||
CallInstrValue::Literal(""),
|
||||
ResolvableToPeerIdVariable::Literal("A"),
|
||||
ResolvableToStringVariable::Literal("add_module"),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![
|
||||
Value::Variable(VariableWithLambda::scalar("module-bytes", 381.into())),
|
||||
Value::Variable(VariableWithLambda::scalar("module_config", 394.into())),
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("module-bytes", 381.into())),
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar(
|
||||
"module_config",
|
||||
394.into(),
|
||||
)),
|
||||
]),
|
||||
CallOutputValue::Scalar(Scalar::new("module", 409.into())),
|
||||
),
|
||||
seq(
|
||||
Instruction::Call(Call {
|
||||
triplet: Triplet {
|
||||
peer_pk: CallInstrValue::Literal("A"),
|
||||
service_id: CallInstrValue::Literal("add_blueprint"),
|
||||
function_name: CallInstrValue::Literal(""),
|
||||
peer_id: ResolvableToPeerIdVariable::Literal("A"),
|
||||
service_id: ResolvableToStringVariable::Literal("add_blueprint"),
|
||||
function_name: ResolvableToStringVariable::Literal(""),
|
||||
},
|
||||
args: Rc::new(vec![Value::Variable(VariableWithLambda::scalar(
|
||||
args: Rc::new(vec![ImmutableValue::Variable(ImmutableVariable::scalar(
|
||||
"blueprint",
|
||||
490.into(),
|
||||
))]),
|
||||
@ -606,20 +582,20 @@ fn seq_with_empty_and_dash() {
|
||||
}),
|
||||
seq(
|
||||
call(
|
||||
CallInstrValue::Literal("A"),
|
||||
CallInstrValue::Literal("create"),
|
||||
CallInstrValue::Literal(""),
|
||||
Rc::new(vec![Value::Variable(VariableWithLambda::scalar(
|
||||
ResolvableToPeerIdVariable::Literal("A"),
|
||||
ResolvableToStringVariable::Literal("create"),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![ImmutableValue::Variable(ImmutableVariable::scalar(
|
||||
"blueprint_id",
|
||||
589.into(),
|
||||
))]),
|
||||
CallOutputValue::Scalar(Scalar::new("service_id", 603.into())),
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Literal("remote_peer_id"),
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
Rc::new(vec![Value::Variable(VariableWithLambda::scalar(
|
||||
ResolvableToPeerIdVariable::Literal("remote_peer_id"),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![ImmutableValue::Variable(ImmutableVariable::scalar(
|
||||
"service_id",
|
||||
671.into(),
|
||||
))]),
|
||||
@ -642,9 +618,9 @@ fn no_output() {
|
||||
let actual = parse(source_code);
|
||||
|
||||
let expected = call(
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("peer", 15.into())),
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("service", 21.into())),
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("fname", 29.into())),
|
||||
ResolvableToPeerIdVariable::Scalar(Scalar::new("peer", 15.into())),
|
||||
ResolvableToStringVariable::Scalar(Scalar::new("service", 21.into())),
|
||||
ResolvableToStringVariable::Scalar(Scalar::new("fname", 29.into())),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
);
|
||||
|
@ -32,7 +32,7 @@ fn canon_with_literal_peer_id() {
|
||||
|
||||
let actual = parse(&source_code);
|
||||
let expected = canon(
|
||||
CallInstrValue::Literal(peer_id),
|
||||
ResolvableToPeerIdVariable::Literal(peer_id),
|
||||
Stream::new(stream, 26.into()),
|
||||
CanonStream::new(canon_stream, 34.into()),
|
||||
);
|
||||
@ -51,7 +51,7 @@ fn canon_with_variable_peer_id() {
|
||||
|
||||
let actual = parse(&source_code);
|
||||
let expected = canon(
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar(peer_id, 16.into())),
|
||||
ResolvableToPeerIdVariable::Scalar(Scalar::new(peer_id, 16.into())),
|
||||
Stream::new(stream, 24.into()),
|
||||
CanonStream::new(canon_stream, 32.into()),
|
||||
);
|
||||
|
@ -18,14 +18,14 @@ use crate::ast::*;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub(super) fn call<'i>(
|
||||
peer_pk: CallInstrValue<'i>,
|
||||
service_id: CallInstrValue<'i>,
|
||||
function_name: CallInstrValue<'i>,
|
||||
args: Rc<Vec<Value<'i>>>,
|
||||
peer_pk: ResolvableToPeerIdVariable<'i>,
|
||||
service_id: ResolvableToStringVariable<'i>,
|
||||
function_name: ResolvableToStringVariable<'i>,
|
||||
args: Rc<Vec<ImmutableValue<'i>>>,
|
||||
output: CallOutputValue<'i>,
|
||||
) -> Instruction<'i> {
|
||||
let triplet = Triplet {
|
||||
peer_pk,
|
||||
peer_id: peer_pk,
|
||||
service_id,
|
||||
function_name,
|
||||
};
|
||||
@ -73,10 +73,14 @@ pub(super) fn null() -> Instruction<'static> {
|
||||
Instruction::Null(Null)
|
||||
}
|
||||
|
||||
pub(super) fn fail_scalar(scalar: ScalarWithLambda) -> Instruction<'_> {
|
||||
pub(super) fn fail_scalar(scalar: Scalar) -> Instruction<'_> {
|
||||
Instruction::Fail(Fail::Scalar(scalar))
|
||||
}
|
||||
|
||||
pub(super) fn fail_scalar_wl(scalar: ScalarWithLambda) -> Instruction<'_> {
|
||||
Instruction::Fail(Fail::ScalarWithLambda(scalar))
|
||||
}
|
||||
|
||||
pub(super) fn fail_literals(ret_code: i64, error_message: &str) -> Instruction<'_> {
|
||||
Instruction::Fail(Fail::Literal {
|
||||
ret_code,
|
||||
@ -89,7 +93,7 @@ pub(super) fn fail_last_error() -> Instruction<'static> {
|
||||
}
|
||||
|
||||
pub(super) fn fold_scalar_variable<'i>(
|
||||
scalar: ScalarWithLambda<'i>,
|
||||
scalar: Scalar<'i>,
|
||||
iterator: Scalar<'i>,
|
||||
instruction: Instruction<'i>,
|
||||
last_instruction: Option<Instruction<'i>>,
|
||||
@ -104,6 +108,22 @@ pub(super) fn fold_scalar_variable<'i>(
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn fold_scalar_variable_wl<'i>(
|
||||
scalar: ScalarWithLambda<'i>,
|
||||
iterator: Scalar<'i>,
|
||||
instruction: Instruction<'i>,
|
||||
last_instruction: Option<Instruction<'i>>,
|
||||
span: Span,
|
||||
) -> Instruction<'i> {
|
||||
Instruction::FoldScalar(FoldScalar {
|
||||
iterable: FoldScalarIterable::ScalarWithLambda(scalar),
|
||||
iterator,
|
||||
instruction: Rc::new(instruction),
|
||||
last_instruction: last_instruction.map(Rc::new),
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn fold_scalar_canon_stream<'i>(
|
||||
canon_stream: CanonStream<'i>,
|
||||
iterator: Scalar<'i>,
|
||||
@ -152,8 +172,8 @@ pub(super) fn fold_stream<'i>(
|
||||
}
|
||||
|
||||
pub(super) fn match_<'i>(
|
||||
left_value: Value<'i>,
|
||||
right_value: Value<'i>,
|
||||
left_value: ImmutableValue<'i>,
|
||||
right_value: ImmutableValue<'i>,
|
||||
instruction: Instruction<'i>,
|
||||
) -> Instruction<'i> {
|
||||
Instruction::Match(Match {
|
||||
@ -164,8 +184,8 @@ pub(super) fn match_<'i>(
|
||||
}
|
||||
|
||||
pub(super) fn mismatch<'i>(
|
||||
left_value: Value<'i>,
|
||||
right_value: Value<'i>,
|
||||
left_value: ImmutableValue<'i>,
|
||||
right_value: ImmutableValue<'i>,
|
||||
instruction: Instruction<'i>,
|
||||
) -> Instruction<'i> {
|
||||
Instruction::MisMatch(MisMatch {
|
||||
@ -180,12 +200,12 @@ pub(super) fn ap<'i>(argument: ApArgument<'i>, result: ApResult<'i>) -> Instruct
|
||||
}
|
||||
|
||||
pub(super) fn canon<'i>(
|
||||
peer_pk: CallInstrValue<'i>,
|
||||
peer_pk: ResolvableToPeerIdVariable<'i>,
|
||||
stream: Stream<'i>,
|
||||
canon_stream: CanonStream<'i>,
|
||||
) -> Instruction<'i> {
|
||||
Instruction::Canon(Canon {
|
||||
peer_pk,
|
||||
peer_id: peer_pk,
|
||||
stream,
|
||||
canon_stream,
|
||||
})
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
use super::dsl::*;
|
||||
use super::parse;
|
||||
use crate::ast::Scalar;
|
||||
use crate::ast::ScalarWithLambda;
|
||||
|
||||
use air_lambda_ast::LambdaAST;
|
||||
@ -47,7 +48,7 @@ fn parse_fail_scalars() {
|
||||
(fail scalar)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = fail_scalar(ScalarWithLambda::new("scalar", None, 18.into()));
|
||||
let expected = fail_scalar(Scalar::new("scalar", 18.into()));
|
||||
assert_eq!(instruction, expected)
|
||||
}
|
||||
|
||||
@ -57,14 +58,12 @@ fn parse_fail_scalar_with_lambda() {
|
||||
(fail scalar.$.field_accessor)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = fail_scalar(ScalarWithLambda::new(
|
||||
let expected = fail_scalar_wl(ScalarWithLambda::new(
|
||||
"scalar",
|
||||
Some(
|
||||
LambdaAST::try_from_accessors(vec![ValueAccessor::FieldAccessByName {
|
||||
field_name: "field_accessor",
|
||||
}])
|
||||
.unwrap(),
|
||||
),
|
||||
LambdaAST::try_from_accessors(vec![ValueAccessor::FieldAccessByName {
|
||||
field_name: "field_accessor",
|
||||
}])
|
||||
.unwrap(),
|
||||
18.into(),
|
||||
));
|
||||
assert_eq!(instruction, expected)
|
||||
|
@ -272,7 +272,7 @@ fn parse_fold() {
|
||||
"#;
|
||||
let instruction = parse(&source_code);
|
||||
let expected = fold_scalar_variable(
|
||||
ScalarWithLambda::new("iterable", None, 15.into()),
|
||||
Scalar::new("iterable", 15.into()),
|
||||
Scalar::new("i", 24.into()),
|
||||
null(),
|
||||
None,
|
||||
@ -291,7 +291,7 @@ fn fold_with_scalar_and_last_instruction() {
|
||||
"#;
|
||||
let instruction = parse(&source_code);
|
||||
let expected = fold_scalar_variable(
|
||||
ScalarWithLambda::new("iterable", None, 15.into()),
|
||||
Scalar::new("iterable", 15.into()),
|
||||
Scalar::new("i", 24.into()),
|
||||
null(),
|
||||
Some(null()),
|
||||
@ -309,8 +309,8 @@ fn fold_json_path() {
|
||||
"#;
|
||||
|
||||
let instruction = parse(source_code);
|
||||
let expected = fold_scalar_variable(
|
||||
ScalarWithLambda::from_value_path(
|
||||
let expected = fold_scalar_variable_wl(
|
||||
ScalarWithLambda::from_raw_lambda(
|
||||
"members",
|
||||
vec![ValueAccessor::ArrayAccess { idx: 123321 }],
|
||||
33.into(),
|
||||
@ -405,8 +405,8 @@ fn comments() {
|
||||
;;; comme;?!.$. nt[][][][()()()null;$::!
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = fold_scalar_variable(
|
||||
ScalarWithLambda::from_value_path(
|
||||
let expected = fold_scalar_variable_wl(
|
||||
ScalarWithLambda::from_raw_lambda(
|
||||
"members",
|
||||
vec![
|
||||
ValueAccessor::FieldAccessByName {
|
||||
@ -436,7 +436,7 @@ fn parse_fold_with_xor_par_seq() {
|
||||
let instruction = parse(&source_code);
|
||||
let instr = binary_instruction(*name);
|
||||
let expected = fold_scalar_variable(
|
||||
ScalarWithLambda::new("iterable", None, 6.into()),
|
||||
Scalar::new("iterable", 6.into()),
|
||||
Scalar::new("i", 15.into()),
|
||||
instr(null(), null()),
|
||||
None,
|
||||
|
@ -31,8 +31,8 @@ fn parse_match() {
|
||||
"#;
|
||||
let instruction = parse(&source_code);
|
||||
let expected = match_(
|
||||
Value::Variable(VariableWithLambda::scalar("v1", 16.into())),
|
||||
Value::Variable(VariableWithLambda::scalar("v2", 19.into())),
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("v1", 16.into())),
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("v2", 19.into())),
|
||||
null(),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
@ -50,12 +50,12 @@ fn parse_match_with_canon_stream() {
|
||||
|
||||
let instruction = parse(&source_code);
|
||||
let expected = match_(
|
||||
Value::Variable(VariableWithLambda::canon_stream_wl(
|
||||
ImmutableValue::VariableWithLambda(ImmutableVariableWithLambda::canon_stream(
|
||||
canon_stream,
|
||||
LambdaAST::try_from_accessors(vec![ValueAccessor::ArrayAccess { idx: 0 }]).unwrap(),
|
||||
16.into(),
|
||||
)),
|
||||
Value::Variable(VariableWithLambda::scalar("v2", 36.into())),
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("v2", 36.into())),
|
||||
null(),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
@ -70,8 +70,8 @@ fn parse_match_with_init_peer_id() {
|
||||
"#;
|
||||
let instruction = parse(&source_code);
|
||||
let expected = match_(
|
||||
Value::Variable(VariableWithLambda::scalar("v1", 16.into())),
|
||||
Value::InitPeerId,
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("v1", 16.into())),
|
||||
ImmutableValue::InitPeerId,
|
||||
null(),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
@ -86,8 +86,8 @@ fn parse_match_with_timestamp() {
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = match_(
|
||||
Value::Timestamp,
|
||||
Value::Variable(VariableWithLambda::scalar("v1", 28.into())),
|
||||
ImmutableValue::Timestamp,
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("v1", 28.into())),
|
||||
null(),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
@ -102,8 +102,8 @@ fn parse_match_with_ttl() {
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = match_(
|
||||
Value::TTL,
|
||||
Value::Variable(VariableWithLambda::scalar("v1", 22.into())),
|
||||
ImmutableValue::TTL,
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("v1", 22.into())),
|
||||
null(),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
@ -118,8 +118,8 @@ fn parse_mismatch() {
|
||||
"#;
|
||||
let instruction = parse(&source_code);
|
||||
let expected = mismatch(
|
||||
Value::Variable(VariableWithLambda::scalar("v1", 19.into())),
|
||||
Value::Variable(VariableWithLambda::scalar("v2", 22.into())),
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("v1", 19.into())),
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("v2", 22.into())),
|
||||
null(),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
@ -133,8 +133,8 @@ fn match_with_bool() {
|
||||
)
|
||||
"#;
|
||||
|
||||
let left_value = Value::Variable(VariableWithLambda::scalar("isOnline", 17.into()));
|
||||
let right_value = Value::Boolean(true);
|
||||
let left_value = ImmutableValue::Variable(ImmutableVariable::scalar("isOnline", 17.into()));
|
||||
let right_value = ImmutableValue::Boolean(true);
|
||||
let null = null();
|
||||
let expected = match_(left_value, right_value, null);
|
||||
|
||||
@ -150,8 +150,8 @@ fn mismatch_with_bool() {
|
||||
)
|
||||
"#;
|
||||
|
||||
let left_value = Value::Boolean(true);
|
||||
let right_value = Value::Variable(VariableWithLambda::scalar("isOnline", 25.into()));
|
||||
let left_value = ImmutableValue::Boolean(true);
|
||||
let right_value = ImmutableValue::Variable(ImmutableVariable::scalar("isOnline", 25.into()));
|
||||
let null = null();
|
||||
let expected = mismatch(left_value, right_value, null);
|
||||
|
||||
@ -167,8 +167,8 @@ fn match_with_empty_array() {
|
||||
)
|
||||
"#;
|
||||
|
||||
let left_value = Value::Variable(VariableWithLambda::scalar("variable", 17.into()));
|
||||
let right_value = Value::EmptyArray;
|
||||
let left_value = ImmutableValue::Variable(ImmutableVariable::scalar("variable", 17.into()));
|
||||
let right_value = ImmutableValue::EmptyArray;
|
||||
let instr = null();
|
||||
let expected = match_(left_value, right_value, instr);
|
||||
|
||||
@ -181,8 +181,8 @@ fn match_with_empty_array() {
|
||||
)
|
||||
"#;
|
||||
|
||||
let left_value = Value::EmptyArray;
|
||||
let right_value = Value::Variable(VariableWithLambda::scalar("variable", 20.into()));
|
||||
let left_value = ImmutableValue::EmptyArray;
|
||||
let right_value = ImmutableValue::Variable(ImmutableVariable::scalar("variable", 20.into()));
|
||||
let instr = null();
|
||||
let expected = match_(left_value, right_value, instr);
|
||||
|
||||
@ -198,8 +198,8 @@ fn mismatch_with_empty_array() {
|
||||
)
|
||||
"#;
|
||||
|
||||
let left_value = Value::Variable(VariableWithLambda::scalar("variable", 20.into()));
|
||||
let right_value = Value::EmptyArray;
|
||||
let left_value = ImmutableValue::Variable(ImmutableVariable::scalar("variable", 20.into()));
|
||||
let right_value = ImmutableValue::EmptyArray;
|
||||
let instr = null();
|
||||
let expected = mismatch(left_value, right_value, instr);
|
||||
|
||||
@ -212,8 +212,8 @@ fn mismatch_with_empty_array() {
|
||||
)
|
||||
"#;
|
||||
|
||||
let left_value = Value::EmptyArray;
|
||||
let right_value = Value::Variable(VariableWithLambda::scalar("variable", 23.into()));
|
||||
let left_value = ImmutableValue::EmptyArray;
|
||||
let right_value = ImmutableValue::Variable(ImmutableVariable::scalar("variable", 23.into()));
|
||||
let instr = null();
|
||||
let expected = mismatch(left_value, right_value, instr);
|
||||
|
||||
|
@ -32,16 +32,16 @@ fn parse_seq() {
|
||||
let instruction = parse(source_code);
|
||||
let expected = par(
|
||||
call(
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
ResolvableToPeerIdVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
ResolvableToPeerIdVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
),
|
||||
@ -64,24 +64,24 @@ fn parse_par_par() {
|
||||
let expected = par(
|
||||
par(
|
||||
call(
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
ResolvableToPeerIdVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
ResolvableToPeerIdVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
),
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
ResolvableToPeerIdVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
ResolvableToStringVariable::Literal(""),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
),
|
||||
|
@ -32,20 +32,20 @@ fn parse_seq() {
|
||||
let instruction = parse(source_code);
|
||||
let expected = seq(
|
||||
call(
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("peer_id", 32.into())),
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("service_id", 41.into())),
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("function_name", 52.into())),
|
||||
Rc::new(vec![Value::EmptyArray, Value::EmptyArray]),
|
||||
ResolvableToPeerIdVariable::Scalar(Scalar::new("peer_id", 32.into())),
|
||||
ResolvableToStringVariable::Scalar(Scalar::new("service_id", 41.into())),
|
||||
ResolvableToStringVariable::Scalar(Scalar::new("function_name", 52.into())),
|
||||
Rc::new(vec![ImmutableValue::EmptyArray, ImmutableValue::EmptyArray]),
|
||||
CallOutputValue::Scalar(Scalar::new("output", 75.into())),
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Literal("peer_id"),
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("function_name"),
|
||||
ResolvableToPeerIdVariable::Literal("peer_id"),
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("function_name"),
|
||||
Rc::new(vec![
|
||||
Value::Literal("hello"),
|
||||
Value::EmptyArray,
|
||||
Value::Variable(VariableWithLambda::scalar("name", 154.into())),
|
||||
ImmutableValue::Literal("hello"),
|
||||
ImmutableValue::EmptyArray,
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("name", 154.into())),
|
||||
]),
|
||||
CallOutputValue::None,
|
||||
),
|
||||
@ -68,27 +68,27 @@ fn parse_seq_seq() {
|
||||
let expected = seq(
|
||||
seq(
|
||||
call(
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("peer_id", 53.into())),
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("service_id", 62.into())),
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("function_name", 73.into())),
|
||||
ResolvableToPeerIdVariable::Scalar(Scalar::new("peer_id", 53.into())),
|
||||
ResolvableToStringVariable::Scalar(Scalar::new("service_id", 62.into())),
|
||||
ResolvableToStringVariable::Scalar(Scalar::new("function_name", 73.into())),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("peer_id", 114.into())),
|
||||
CallInstrValue::Literal("service_B"),
|
||||
CallInstrValue::Variable(VariableWithLambda::scalar("function_name", 135.into())),
|
||||
ResolvableToPeerIdVariable::Scalar(Scalar::new("peer_id", 114.into())),
|
||||
ResolvableToStringVariable::Literal("service_B"),
|
||||
ResolvableToStringVariable::Scalar(Scalar::new("function_name", 135.into())),
|
||||
Rc::new(vec![]),
|
||||
CallOutputValue::None,
|
||||
),
|
||||
),
|
||||
call(
|
||||
CallInstrValue::Literal("peer_id"),
|
||||
CallInstrValue::Literal("service_id"),
|
||||
CallInstrValue::Literal("function_name"),
|
||||
ResolvableToPeerIdVariable::Literal("peer_id"),
|
||||
ResolvableToStringVariable::Literal("service_id"),
|
||||
ResolvableToStringVariable::Literal("function_name"),
|
||||
Rc::new(vec![
|
||||
Value::Literal("hello"),
|
||||
Value::Variable(VariableWithLambda::scalar("name", 236.into())),
|
||||
ImmutableValue::Literal("hello"),
|
||||
ImmutableValue::Variable(ImmutableVariable::scalar("name", 236.into())),
|
||||
]),
|
||||
CallOutputValue::Stream(Stream::new("$output", 242.into())),
|
||||
),
|
||||
|
@ -25,8 +25,8 @@ use air_lambda_ast::LambdaAST;
|
||||
use air_lambda_ast::ValueAccessor;
|
||||
use lalrpop_util::ErrorRecovery;
|
||||
use lalrpop_util::ParseError;
|
||||
|
||||
use multimap::MultiMap;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
|
||||
@ -66,9 +66,9 @@ impl<'i> VariableValidator<'i> {
|
||||
}
|
||||
|
||||
pub(super) fn met_call(&mut self, call: &Call<'i>, span: Span) {
|
||||
self.met_call_instr_value(&call.triplet.peer_pk, span);
|
||||
self.met_call_instr_value(&call.triplet.service_id, span);
|
||||
self.met_call_instr_value(&call.triplet.function_name, span);
|
||||
self.met_peer_id_resolvable_value(&call.triplet.peer_id, span);
|
||||
self.met_string_resolvable_value(&call.triplet.service_id, span);
|
||||
self.met_string_resolvable_value(&call.triplet.function_name, span);
|
||||
|
||||
self.met_args(call.args.deref(), span);
|
||||
|
||||
@ -99,13 +99,9 @@ impl<'i> VariableValidator<'i> {
|
||||
use FoldScalarIterable::*;
|
||||
|
||||
match &fold.iterable {
|
||||
Scalar(variable) => {
|
||||
self.met_variable_name(variable.name, span);
|
||||
self.met_maybe_lambda(&variable.lambda, span);
|
||||
}
|
||||
CanonStream(canon_stream) => {
|
||||
self.met_variable_name(canon_stream.name, span);
|
||||
}
|
||||
Scalar(scalar) => self.met_scalar(scalar, span),
|
||||
ScalarWithLambda(scalar) => self.met_scalar_wl(scalar, span),
|
||||
CanonStream(canon_stream) => self.met_canon_stream(canon_stream, span),
|
||||
EmptyArray => {}
|
||||
};
|
||||
self.met_iterator_definition(&fold.iterator, span);
|
||||
@ -142,13 +138,11 @@ impl<'i> VariableValidator<'i> {
|
||||
| ApArgument::Literal(_)
|
||||
| ApArgument::EmptyArray
|
||||
| ApArgument::LastError(_) => {}
|
||||
ApArgument::Scalar(scalar) => {
|
||||
self.met_variable_name(scalar.name, span);
|
||||
self.met_maybe_lambda(&scalar.lambda, span);
|
||||
}
|
||||
ApArgument::CanonStream(canon_stream) => {
|
||||
self.met_variable_name(canon_stream.name, span);
|
||||
self.met_maybe_lambda(&canon_stream.lambda, span);
|
||||
ApArgument::Scalar(scalar) => self.met_scalar(scalar, span),
|
||||
ApArgument::ScalarWithLambda(scalar) => self.met_scalar_wl(scalar, span),
|
||||
ApArgument::CanonStream(canon_stream) => self.met_canon_stream(canon_stream, span),
|
||||
ApArgument::CanonStreamWithLambda(canon_stream) => {
|
||||
self.met_canon_stream_wl(canon_stream, span)
|
||||
}
|
||||
}
|
||||
self.met_variable_name_definition(ap.result.name(), span);
|
||||
@ -164,34 +158,78 @@ impl<'i> VariableValidator<'i> {
|
||||
.build()
|
||||
}
|
||||
|
||||
fn met_args(&mut self, args: &[Value<'i>], span: Span) {
|
||||
fn met_args(&mut self, args: &[ImmutableValue<'i>], span: Span) {
|
||||
for arg in args {
|
||||
self.met_instr_arg_value(arg, span);
|
||||
}
|
||||
}
|
||||
|
||||
fn met_call_instr_value(&mut self, instr_value: &CallInstrValue<'i>, span: Span) {
|
||||
if let CallInstrValue::Variable(variable) = instr_value {
|
||||
self.met_variable_wl(variable, span);
|
||||
fn met_peer_id_resolvable_value(
|
||||
&mut self,
|
||||
variable: &ResolvableToPeerIdVariable<'i>,
|
||||
span: Span,
|
||||
) {
|
||||
use ResolvableToPeerIdVariable::*;
|
||||
|
||||
match variable {
|
||||
InitPeerId | Literal(_) => {}
|
||||
Scalar(scalar) => self.met_scalar(scalar, span),
|
||||
ScalarWithLambda(scalar) => self.met_scalar_wl(scalar, span),
|
||||
CanonStreamWithLambda(stream) => self.met_canon_stream_wl(stream, span),
|
||||
}
|
||||
}
|
||||
|
||||
fn met_instr_arg_value(&mut self, instr_arg_value: &Value<'i>, span: Span) {
|
||||
if let Value::Variable(variable) = instr_arg_value {
|
||||
// skipping streams without lambdas here allows treating non-defined streams as empty arrays
|
||||
if let VariableWithLambda::Stream(stream) = variable {
|
||||
if stream.lambda.is_none() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
fn met_string_resolvable_value(
|
||||
&mut self,
|
||||
variable: &ResolvableToStringVariable<'i>,
|
||||
span: Span,
|
||||
) {
|
||||
use ResolvableToStringVariable::*;
|
||||
|
||||
self.met_variable_wl(variable, span);
|
||||
match variable {
|
||||
Literal(_) => {}
|
||||
Scalar(scalar) => self.met_scalar(scalar, span),
|
||||
ScalarWithLambda(scalar) => self.met_scalar_wl(scalar, span),
|
||||
CanonStreamWithLambda(stream) => self.met_canon_stream_wl(stream, span),
|
||||
}
|
||||
}
|
||||
|
||||
fn met_variable_wl(&mut self, variable: &VariableWithLambda<'i>, span: Span) {
|
||||
fn met_instr_arg_value(&mut self, instr_arg_value: &ImmutableValue<'i>, span: Span) {
|
||||
use ImmutableValue::*;
|
||||
|
||||
match instr_arg_value {
|
||||
InitPeerId | LastError(_) | Timestamp | TTL | Literal(_) | Number(_) | Boolean(_)
|
||||
| EmptyArray => {}
|
||||
Variable(variable) => self.met_variable(variable, span),
|
||||
VariableWithLambda(variable) => self.met_variable_wl(variable, span),
|
||||
}
|
||||
}
|
||||
|
||||
fn met_variable(&mut self, variable: &ImmutableVariable<'i>, span: Span) {
|
||||
self.met_variable_name(variable.name(), span);
|
||||
self.met_maybe_lambda(variable.lambda(), span);
|
||||
}
|
||||
|
||||
fn met_variable_wl(&mut self, variable: &ImmutableVariableWithLambda<'i>, span: Span) {
|
||||
self.met_variable_name(variable.name(), span);
|
||||
self.met_lambda(variable.lambda(), span);
|
||||
}
|
||||
|
||||
fn met_scalar(&mut self, scalar: &Scalar<'i>, span: Span) {
|
||||
self.met_variable_name(scalar.name, span);
|
||||
}
|
||||
|
||||
fn met_scalar_wl(&mut self, scalar: &ScalarWithLambda<'i>, span: Span) {
|
||||
self.met_variable_name(scalar.name, span);
|
||||
self.met_lambda(&scalar.lambda, span);
|
||||
}
|
||||
|
||||
fn met_canon_stream(&mut self, stream: &CanonStream<'i>, span: Span) {
|
||||
self.met_variable_name(stream.name, span);
|
||||
}
|
||||
|
||||
fn met_canon_stream_wl(&mut self, stream: &CanonStreamWithLambda<'i>, span: Span) {
|
||||
self.met_variable_name(stream.name, span);
|
||||
self.met_lambda(&stream.lambda, span);
|
||||
}
|
||||
|
||||
fn met_variable_name(&mut self, name: &'i str, span: Span) {
|
||||
@ -200,14 +238,6 @@ impl<'i> VariableValidator<'i> {
|
||||
}
|
||||
}
|
||||
|
||||
fn met_maybe_lambda(&mut self, lambda: &Option<LambdaAST<'i>>, span: Span) {
|
||||
let lambda = match lambda {
|
||||
Some(lambda) => lambda,
|
||||
None => return,
|
||||
};
|
||||
self.met_lambda(lambda, span)
|
||||
}
|
||||
|
||||
fn met_lambda(&mut self, lambda: &LambdaAST<'i>, span: Span) {
|
||||
let accessors = match lambda {
|
||||
LambdaAST::ValuePath(accessors) => accessors,
|
||||
@ -256,17 +286,18 @@ impl<'i> VariableValidator<'i> {
|
||||
}
|
||||
}
|
||||
|
||||
fn met_matchable(&mut self, matchable: &Value<'i>, span: Span) {
|
||||
fn met_matchable(&mut self, matchable: &ImmutableValue<'i>, span: Span) {
|
||||
match matchable {
|
||||
Value::InitPeerId
|
||||
| Value::Timestamp
|
||||
| Value::TTL
|
||||
| Value::Number(_)
|
||||
| Value::Boolean(_)
|
||||
| Value::Literal(_)
|
||||
| Value::LastError(_)
|
||||
| Value::EmptyArray => {}
|
||||
Value::Variable(variable) => self.met_variable_wl(variable, span),
|
||||
ImmutableValue::InitPeerId
|
||||
| ImmutableValue::Timestamp
|
||||
| ImmutableValue::TTL
|
||||
| ImmutableValue::Number(_)
|
||||
| ImmutableValue::Boolean(_)
|
||||
| ImmutableValue::Literal(_)
|
||||
| ImmutableValue::LastError(_)
|
||||
| ImmutableValue::EmptyArray => {}
|
||||
ImmutableValue::Variable(variable) => self.met_variable(variable, span),
|
||||
ImmutableValue::VariableWithLambda(variable) => self.met_variable_wl(variable, span),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ fn fmt_indent(output: &mut impl io::Write, indent: usize) -> io::Result<()> {
|
||||
write!(output, "{:indent$}", "", indent = indent)
|
||||
}
|
||||
|
||||
struct CallArgs<'ctx, 'i>(&'ctx [ast::Value<'i>]);
|
||||
struct CallArgs<'ctx, 'i>(&'ctx [ast::ImmutableValue<'i>]);
|
||||
|
||||
impl<'ctx, 'i> Display for CallArgs<'ctx, 'i> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
@ -65,7 +65,7 @@ impl<'ctx, 'i> Display for CallTriplet<'ctx, 'i> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_fmt(format_args!(
|
||||
"{} ({}, {})",
|
||||
self.0.peer_pk, self.0.service_id, self.0.function_name
|
||||
self.0.peer_id, self.0.service_id, self.0.function_name
|
||||
))
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user