mirror of
https://github.com/fluencelabs/aquavm
synced 2025-03-15 20:40:50 +00:00
support empty array literal in fold (#230)
This commit is contained in:
parent
c00b453a48
commit
a64a4fc0a6
@ -24,14 +24,21 @@ use crate::joinable;
|
|||||||
use crate::log_instruction;
|
use crate::log_instruction;
|
||||||
|
|
||||||
use air_parser::ast::FoldScalar;
|
use air_parser::ast::FoldScalar;
|
||||||
|
use air_parser::ast::FoldScalarIterable;
|
||||||
use air_parser::ast::Instruction;
|
use air_parser::ast::Instruction;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
impl<'i> ExecutableInstruction<'i> for FoldScalar<'i> {
|
impl<'i> ExecutableInstruction<'i> for FoldScalar<'i> {
|
||||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
|
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
|
||||||
log_instruction!(fold, exec_ctx, trace_ctx);
|
log_instruction!(fold, exec_ctx, trace_ctx);
|
||||||
|
|
||||||
let scalar_iterable = joinable!(construct_scalar_iterable_value(&self.iterable, exec_ctx), exec_ctx)?;
|
let scalar = match &self.iterable {
|
||||||
|
FoldScalarIterable::Scalar(scalar) => scalar,
|
||||||
|
// just do nothing on an empty array
|
||||||
|
FoldScalarIterable::EmptyArray => return Ok(()),
|
||||||
|
};
|
||||||
|
let scalar_iterable = joinable!(construct_scalar_iterable_value(scalar, exec_ctx), exec_ctx)?;
|
||||||
|
|
||||||
match scalar_iterable {
|
match scalar_iterable {
|
||||||
// just exit on empty iterable
|
// just exit on empty iterable
|
||||||
|
@ -163,7 +163,7 @@ fn inner_fold_with_same_iterator() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_fold() {
|
fn empty_iterable_fold() {
|
||||||
let mut vm = create_avm(echo_call_service(), "A");
|
let mut vm = create_avm(echo_call_service(), "A");
|
||||||
let mut set_variable_vm = create_avm(set_variable_call_service(json!([])), "set_variable");
|
let mut set_variable_vm = create_avm(set_variable_call_service(json!([])), "set_variable");
|
||||||
|
|
||||||
@ -188,6 +188,24 @@ fn empty_fold() {
|
|||||||
assert_eq!(actual_trace[0], expected_state);
|
assert_eq!(actual_trace[0], expected_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_literal_array_fold() {
|
||||||
|
let mut vm = create_avm(echo_call_service(), "A");
|
||||||
|
|
||||||
|
let empty_fold = r#"
|
||||||
|
(fold [] i
|
||||||
|
(seq
|
||||||
|
(call "A" ("" "") [i] $acc)
|
||||||
|
(next i)
|
||||||
|
)
|
||||||
|
)"#;
|
||||||
|
|
||||||
|
let result = checked_call_vm!(vm, "", empty_fold, "", "");
|
||||||
|
let actual_trace = trace_from_result(&result);
|
||||||
|
|
||||||
|
assert!(actual_trace.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_fold_json_path() {
|
fn empty_fold_json_path() {
|
||||||
let mut vm = create_avm(echo_call_service(), "A");
|
let mut vm = create_avm(echo_call_service(), "A");
|
||||||
|
@ -92,3 +92,10 @@ pub enum Number {
|
|||||||
Int(i64),
|
Int(i64),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum FoldScalarIterable<'i> {
|
||||||
|
#[serde(borrow)]
|
||||||
|
Scalar(ScalarWithLambda<'i>),
|
||||||
|
EmptyArray,
|
||||||
|
}
|
||||||
|
@ -117,6 +117,17 @@ impl fmt::Display for Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for FoldScalarIterable<'_> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
use FoldScalarIterable::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Scalar(variable) => write!(f, "{}", variable),
|
||||||
|
EmptyArray => write!(f, "[]"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Number> for serde_json::Value {
|
impl From<Number> for serde_json::Value {
|
||||||
fn from(number: Number) -> Self {
|
fn from(number: Number) -> Self {
|
||||||
(&number).into()
|
(&number).into()
|
||||||
|
@ -99,7 +99,8 @@ pub enum Fail<'i> {
|
|||||||
/// (fold scalar_iterable iterator instruction)
|
/// (fold scalar_iterable iterator instruction)
|
||||||
#[derive(Serialize, Debug, PartialEq)]
|
#[derive(Serialize, Debug, PartialEq)]
|
||||||
pub struct FoldScalar<'i> {
|
pub struct FoldScalar<'i> {
|
||||||
pub iterable: ScalarWithLambda<'i>,
|
#[serde(borrow)]
|
||||||
|
pub iterable: FoldScalarIterable<'i>,
|
||||||
#[serde(borrow)]
|
#[serde(borrow)]
|
||||||
pub iterator: Scalar<'i>,
|
pub iterator: Scalar<'i>,
|
||||||
pub instruction: Rc<Instruction<'i>>,
|
pub instruction: Rc<Instruction<'i>>,
|
||||||
|
@ -93,7 +93,7 @@ impl<'i> MisMatch<'i> {
|
|||||||
|
|
||||||
impl<'i> FoldScalar<'i> {
|
impl<'i> FoldScalar<'i> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
iterable: ScalarWithLambda<'i>,
|
iterable: FoldScalarIterable<'i>,
|
||||||
iterator: Scalar<'i>,
|
iterator: Scalar<'i>,
|
||||||
instruction: Instruction<'i>,
|
instruction: Instruction<'i>,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
@ -147,9 +147,10 @@ FailBody: Fail<'input> = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FoldScalarIterable: ScalarWithLambda<'input> = {
|
FoldScalarIterable: FoldScalarIterable<'input> = {
|
||||||
<scalar:Scalar> => ScalarWithLambda::new(scalar.0, None, scalar.1),
|
<scalar:Scalar> => FoldScalarIterable::Scalar(ScalarWithLambda::new(scalar.0, None, scalar.1)),
|
||||||
<scalar:ScalarWithLambda> => ScalarWithLambda::new(scalar.0, Some(scalar.1), scalar.2),
|
<scalar:ScalarWithLambda> => FoldScalarIterable::Scalar(ScalarWithLambda::new(scalar.0, Some(scalar.1), scalar.2)),
|
||||||
|
"[" "]" => FoldScalarIterable::EmptyArray,
|
||||||
};
|
};
|
||||||
|
|
||||||
Function = CallInstrValue;
|
Function = CallInstrValue;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -84,16 +84,29 @@ pub(super) fn fail_last_error() -> Instruction<'static> {
|
|||||||
Instruction::Fail(Fail::LastError)
|
Instruction::Fail(Fail::LastError)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn fold_scalar<'i>(
|
pub(super) fn fold_scalar_variable<'i>(
|
||||||
iterable: ScalarWithLambda<'i>,
|
scalar: ScalarWithLambda<'i>,
|
||||||
iterator: Scalar<'i>,
|
iterator: Scalar<'i>,
|
||||||
instruction: Instruction<'i>,
|
instruction: Instruction<'i>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Instruction<'i> {
|
) -> Instruction<'i> {
|
||||||
Instruction::FoldScalar(FoldScalar {
|
Instruction::FoldScalar(FoldScalar {
|
||||||
iterable,
|
iterable: FoldScalarIterable::Scalar(scalar),
|
||||||
iterator,
|
iterator,
|
||||||
instruction: std::rc::Rc::new(instruction),
|
instruction: Rc::new(instruction),
|
||||||
|
span,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn fold_scalar_empty_array<'i>(
|
||||||
|
iterator: Scalar<'i>,
|
||||||
|
instruction: Instruction<'i>,
|
||||||
|
span: Span,
|
||||||
|
) -> Instruction<'i> {
|
||||||
|
Instruction::FoldScalar(FoldScalar {
|
||||||
|
iterable: FoldScalarIterable::EmptyArray,
|
||||||
|
iterator,
|
||||||
|
instruction: Rc::new(instruction),
|
||||||
span,
|
span,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -107,7 +120,7 @@ pub(super) fn fold_stream<'i>(
|
|||||||
Instruction::FoldStream(FoldStream {
|
Instruction::FoldStream(FoldStream {
|
||||||
iterable,
|
iterable,
|
||||||
iterator,
|
iterator,
|
||||||
instruction: std::rc::Rc::new(instruction),
|
instruction: Rc::new(instruction),
|
||||||
span,
|
span,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ fn parse_fold() {
|
|||||||
)
|
)
|
||||||
"#;
|
"#;
|
||||||
let instruction = parse(&source_code);
|
let instruction = parse(&source_code);
|
||||||
let expected = fold_scalar(
|
let expected = fold_scalar_variable(
|
||||||
ScalarWithLambda::new("iterable", None, 15),
|
ScalarWithLambda::new("iterable", None, 15),
|
||||||
Scalar::new("i", 24),
|
Scalar::new("i", 24),
|
||||||
null(),
|
null(),
|
||||||
@ -168,7 +168,7 @@ fn fold_json_path() {
|
|||||||
"#;
|
"#;
|
||||||
|
|
||||||
let instruction = parse(source_code);
|
let instruction = parse(source_code);
|
||||||
let expected = fold_scalar(
|
let expected = fold_scalar_variable(
|
||||||
ScalarWithLambda::from_raw_lambda(
|
ScalarWithLambda::from_raw_lambda(
|
||||||
"members",
|
"members",
|
||||||
vec![ValueAccessor::ArrayAccess { idx: 123321 }],
|
vec![ValueAccessor::ArrayAccess { idx: 123321 }],
|
||||||
@ -181,6 +181,19 @@ fn fold_json_path() {
|
|||||||
assert_eq!(instruction, expected);
|
assert_eq!(instruction, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fold_empty_array_iterable() {
|
||||||
|
let source_code = r#"
|
||||||
|
(fold [] m
|
||||||
|
(null)
|
||||||
|
)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let instruction = parse(source_code);
|
||||||
|
let expected = fold_scalar_empty_array(Scalar::new("m", 18), null(), Span::new(9, 48));
|
||||||
|
assert_eq!(instruction, expected);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fold_on_stream() {
|
fn fold_on_stream() {
|
||||||
let source_code = r#"
|
let source_code = r#"
|
||||||
@ -205,7 +218,7 @@ fn comments() {
|
|||||||
;;; comme;?!.$. nt[][][][()()()null;$::!
|
;;; comme;?!.$. nt[][][][()()()null;$::!
|
||||||
"#;
|
"#;
|
||||||
let instruction = parse(source_code);
|
let instruction = parse(source_code);
|
||||||
let expected = fold_scalar(
|
let expected = fold_scalar_variable(
|
||||||
ScalarWithLambda::from_raw_lambda(
|
ScalarWithLambda::from_raw_lambda(
|
||||||
"members",
|
"members",
|
||||||
vec![
|
vec![
|
||||||
@ -234,7 +247,7 @@ fn parse_fold_with_xor_par_seq() {
|
|||||||
let source_code = source_fold_with(name);
|
let source_code = source_fold_with(name);
|
||||||
let instruction = parse(&source_code);
|
let instruction = parse(&source_code);
|
||||||
let instr = binary_instruction(*name);
|
let instr = binary_instruction(*name);
|
||||||
let expected = fold_scalar(
|
let expected = fold_scalar_variable(
|
||||||
ScalarWithLambda::new("iterable", None, 6),
|
ScalarWithLambda::new("iterable", None, 6),
|
||||||
Scalar::new("i", 15),
|
Scalar::new("i", 15),
|
||||||
instr(null(), null()),
|
instr(null(), null()),
|
||||||
|
@ -83,7 +83,12 @@ impl<'i> VariableValidator<'i> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn met_fold_scalar(&mut self, fold: &FoldScalar<'i>, span: Span) {
|
pub(super) fn met_fold_scalar(&mut self, fold: &FoldScalar<'i>, span: Span) {
|
||||||
self.met_variable_name(fold.iterable.name, span);
|
use FoldScalarIterable::*;
|
||||||
|
|
||||||
|
match &fold.iterable {
|
||||||
|
Scalar(variable) => self.met_variable_name(variable.name, span),
|
||||||
|
EmptyArray => {}
|
||||||
|
};
|
||||||
self.met_iterator_definition(&fold.iterator, span);
|
self.met_iterator_definition(&fold.iterator, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user