mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-04 15:20:16 +00:00
Use $ to identify streams instead of [] (#79)
This commit is contained in:
parent
9bdd2e3501
commit
45fc92ae3d
72
Cargo.lock
generated
72
Cargo.lock
generated
@ -13,7 +13,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "air-parser"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"codespan",
|
||||
"codespan-reporting",
|
||||
@ -40,9 +40,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.38"
|
||||
version = "1.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
|
||||
checksum = "81cddc5f91628367664cc7c69714ff08deee8a3efc54623011c772544d7b2767"
|
||||
|
||||
[[package]]
|
||||
name = "aqua-interpreter-interface"
|
||||
@ -82,7 +82,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aquamarine"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"fluence 0.4.2",
|
||||
"interpreter-lib",
|
||||
@ -240,9 +240,9 @@ checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.2"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
@ -481,9 +481,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.1.5"
|
||||
version = "1.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9d58633299b24b515ac72a3f869f8b91306a3cec616a602843a383acd6f9e97"
|
||||
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"csv-core",
|
||||
@ -503,9 +503,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.1.19"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19"
|
||||
checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
@ -980,9 +980,9 @@ checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.6.1"
|
||||
version = "1.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
|
||||
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
@ -1000,7 +1000,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "interpreter-lib"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"air-parser",
|
||||
"aqua-interpreter-interface 0.3.1",
|
||||
@ -1156,9 +1156,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.87"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213"
|
||||
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
@ -1211,9 +1211,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
|
||||
checksum = "cc14fc54a812b4472b4113facc3e44d099fbc0ea2ce0551fa5c703f8edfbfd38"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
@ -1552,14 +1552,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.3"
|
||||
version = "1.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
|
||||
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1573,9 +1572,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.22"
|
||||
version = "0.6.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
|
||||
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||
|
||||
[[package]]
|
||||
name = "rust-argon2"
|
||||
@ -1703,9 +1702,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.3"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
|
||||
checksum = "cbce6d4507c7e4a3962091436e56e95290cb71fa302d0d270e32130b75fbff27"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
@ -1739,9 +1738,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.61"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed22b90a0e734a23a7610f4283ac9e5acfb96cbb30dfefa540d66f866f1c09c5"
|
||||
checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1803,15 +1802,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.43"
|
||||
@ -1852,9 +1842,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.12.0"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
||||
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
|
||||
|
||||
[[package]]
|
||||
name = "typetag"
|
||||
@ -1909,9 +1899,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.2"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
@ -1921,9 +1911,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.1"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
|
||||
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "air-parser"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
|
@ -28,24 +28,24 @@ use air_parser::AIRParser;
|
||||
|
||||
const SOURCE_CODE_BAD: &'static str = r#"(seq
|
||||
(seq
|
||||
(call node ("identity" "") [] void[])
|
||||
(call node ("identity" "") [] $void)
|
||||
(call provider (service_id "{fname}") {arg_list} result)
|
||||
)
|
||||
(seq
|
||||
(call node ("identity" "") [] void[])
|
||||
(call "{LOCAL_VM}" ("return" "result") [result] void[])
|
||||
(call node ("identity" "") [] $void)
|
||||
(call "{LOCAL_VM}" ("return" "result") [result] $void)
|
||||
)
|
||||
)"#;
|
||||
|
||||
const SOURCE_CODE_GOOD: &'static str = r#"
|
||||
(seq
|
||||
(seq
|
||||
(call node ("identity" "") [] void[])
|
||||
(call node ("identity" "") [] $void)
|
||||
(call provider (service_id "fname") [arg list] result)
|
||||
)
|
||||
(seq
|
||||
(call node ("identity" "") [] void[])
|
||||
(call "local_vm" ("return" "result") [result] void[])
|
||||
(call node ("identity" "") [] $void)
|
||||
(call "local_vm" ("return" "result") [result] $void)
|
||||
)
|
||||
)"#;
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
use crate::parser::ast::*;
|
||||
use crate::parser::air_parser::into_variable_and_path;
|
||||
use crate::parser::air_parser::make_flattened_error;
|
||||
use crate::parser::ParserError;
|
||||
use crate::parser::VariableValidator;
|
||||
use crate::parser::Span;
|
||||
use crate::parser::lexer::Token;
|
||||
use crate::parser::lexer::Number;
|
||||
use crate::parser::lexer::Variable;
|
||||
|
||||
use lalrpop_util::ErrorRecovery;
|
||||
use std::rc::Rc;
|
||||
@ -16,10 +16,10 @@ grammar<'err, 'input, 'v>(input: &'input str, errors: &'err mut Vec<ErrorRecover
|
||||
pub AIR = Instr;
|
||||
|
||||
Instr: Box<Instruction<'input>> = {
|
||||
<left: @L> "(" call <p:PeerPart> <f:FPart> <args:Args> <output:Output?> ")" <right: @R> => {
|
||||
<left: @L> "(" call <peer_part:PeerPart> <function_part:FPart> <args:Args> <output:Output?> ")" <right: @R> => {
|
||||
let output = output.unwrap_or(CallOutputValue::None);
|
||||
let args = Rc::new(args);
|
||||
let call = Call { peer_part: p, function_part: f, args, output };
|
||||
let call = Call { peer_part, function_part, args, output };
|
||||
let span = Span { left, right };
|
||||
validator.met_call(&call, span);
|
||||
|
||||
@ -82,8 +82,8 @@ PeerPart: PeerPart<'input> = {
|
||||
}
|
||||
|
||||
Output: CallOutputValue<'input> = {
|
||||
<s:Alphanumeric> => CallOutputValue::Scalar(s),
|
||||
<a:Accumulator> => CallOutputValue::Accumulator(a),
|
||||
<a:Alphanumeric> => CallOutputValue::Variable(Variable::Scalar(a)),
|
||||
<s:Stream> => CallOutputValue::Variable(Variable::Stream(s)),
|
||||
};
|
||||
|
||||
Function = CallInstrValue;
|
||||
@ -91,13 +91,16 @@ PeerId = CallInstrValue;
|
||||
ServiceId = CallInstrValue;
|
||||
|
||||
CallInstrValue: CallInstrValue<'input> = {
|
||||
<s:Literal> => CallInstrValue::Literal(s),
|
||||
<s:Alphanumeric> => CallInstrValue::Variable(s),
|
||||
<l: @L> <v:JsonPath> <r: @R> => {
|
||||
let (variable, path) = into_variable_and_path(v.0, v.1, v.2);
|
||||
let should_flatten = v.2;
|
||||
<l:Literal> => CallInstrValue::Literal(l),
|
||||
<a:Alphanumeric> => CallInstrValue::Variable(Variable::Scalar(a)),
|
||||
<s:Stream> => CallInstrValue::Variable(Variable::Stream(s)),
|
||||
<l: @L> <j:JsonPath> <r: @R> => {
|
||||
let variable = j.0;
|
||||
let path = j.1;
|
||||
let should_flatten = j.2;
|
||||
// Due the json path constraints json path should be flattened in a call triplet.
|
||||
if !should_flatten {
|
||||
let token = Token::JsonPath(v.0, v.1, v.2);
|
||||
let token = Token::VariableWithJsonPath(variable.clone(), path, should_flatten);
|
||||
errors.push(make_flattened_error(l, token, r));
|
||||
}
|
||||
CallInstrValue::JsonPath { variable, path, should_flatten }
|
||||
@ -109,12 +112,9 @@ Arg = CallInstrArgValue;
|
||||
|
||||
CallInstrArgValue: CallInstrArgValue<'input> = {
|
||||
<s:Literal> => CallInstrArgValue::Literal(s),
|
||||
<s:Alphanumeric> => CallInstrArgValue::Variable(s),
|
||||
<v:JsonPath> => {
|
||||
let (variable, path) = into_variable_and_path(v.0, v.1, v.2);
|
||||
let should_flatten = v.2;
|
||||
CallInstrArgValue::JsonPath { variable, path, should_flatten }
|
||||
},
|
||||
<v:Alphanumeric> => CallInstrArgValue::Variable(Variable::Scalar(v)),
|
||||
<v:Stream> => CallInstrArgValue::Variable(Variable::Stream(v)),
|
||||
<j:JsonPath> => CallInstrArgValue::JsonPath { variable: j.0, path: j.1, should_flatten: j.2 },
|
||||
<n:Number> => CallInstrArgValue::Number(n),
|
||||
<b:Boolean> => CallInstrArgValue::Boolean(b),
|
||||
InitPeerId => CallInstrArgValue::InitPeerId,
|
||||
@ -122,25 +122,18 @@ CallInstrArgValue: CallInstrArgValue<'input> = {
|
||||
}
|
||||
|
||||
Iterable: IterableValue<'input> = {
|
||||
<s:Alphanumeric> => IterableValue::Variable(s),
|
||||
<v:JsonPath> => {
|
||||
let (variable, path) = into_variable_and_path(v.0, v.1, v.2);
|
||||
|
||||
let should_flatten = v.2;
|
||||
IterableValue::JsonPath { variable, path, should_flatten }
|
||||
},
|
||||
<v:Alphanumeric> => IterableValue::Variable(Variable::Scalar(v)),
|
||||
<v:Stream> => IterableValue::Variable(Variable::Stream(v)),
|
||||
<j:JsonPath> => IterableValue::JsonPath { variable: j.0, path: j.1, should_flatten: j.2 },
|
||||
}
|
||||
|
||||
Matchable: MatchableValue<'input> = {
|
||||
<s:Alphanumeric> => MatchableValue::Variable(s),
|
||||
<v:Alphanumeric> => MatchableValue::Variable(Variable::Scalar(v)),
|
||||
<v:Stream> => MatchableValue::Variable(Variable::Stream(v)),
|
||||
<s:Literal> => MatchableValue::Literal(s),
|
||||
<b:Boolean> => MatchableValue::Boolean(b),
|
||||
<n:Number> => MatchableValue::Number(n),
|
||||
<v:JsonPath> => {
|
||||
let (variable, path) = into_variable_and_path(v.0, v.1, v.2);
|
||||
let should_flatten = v.2;
|
||||
MatchableValue::JsonPath { variable, path, should_flatten }
|
||||
},
|
||||
<j:JsonPath> => MatchableValue::JsonPath { variable: j.0, path: j.1, should_flatten: j.2 },
|
||||
}
|
||||
|
||||
extern {
|
||||
@ -153,10 +146,10 @@ extern {
|
||||
"[" => Token::OpenSquareBracket,
|
||||
"]" => Token::CloseSquareBracket,
|
||||
|
||||
Alphanumeric => Token::Alphanumeric(<&'input str>),
|
||||
Literal => Token::StringLiteral(<&'input str>),
|
||||
JsonPath => Token::JsonPath(<&'input str>, <usize>, <bool>),
|
||||
Accumulator => Token::Accumulator(<&'input str>),
|
||||
Alphanumeric => Token::Alphanumeric(<&'input str>),
|
||||
Stream => Token::Stream(<&'input str>),
|
||||
JsonPath => Token::VariableWithJsonPath(<Variable<'input>>, <&'input str>, <bool>),
|
||||
Number => Token::Number(<Number>),
|
||||
Boolean => Token::Boolean(<bool>),
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -148,7 +148,7 @@ fn lexical_error_to_label(file_id: usize, error: LexerError) -> Label<usize> {
|
||||
IsNotAlphanumeric(start, end) => {
|
||||
Label::primary(file_id, start..end).with_message(error.to_string())
|
||||
}
|
||||
EmptyAccName(start, end) => {
|
||||
EmptyStreamName(start, end) => {
|
||||
Label::primary(file_id, start..end).with_message(error.to_string())
|
||||
}
|
||||
EmptyVariableOrConst(start, end) => {
|
||||
@ -175,16 +175,6 @@ fn lexical_error_to_label(file_id: usize, error: LexerError) -> Label<usize> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn into_variable_and_path(str: &str, pos: usize, should_flatten: bool) -> (&str, &str) {
|
||||
let json_path = if should_flatten {
|
||||
&str[pos + 1..str.len() - 1]
|
||||
} else {
|
||||
&str[pos + 1..]
|
||||
};
|
||||
|
||||
(&str[0..pos], json_path)
|
||||
}
|
||||
|
||||
pub(super) fn make_flattened_error(
|
||||
start_pos: usize,
|
||||
token: Token<'_>,
|
||||
|
@ -17,6 +17,7 @@
|
||||
mod traits;
|
||||
|
||||
pub use crate::parser::lexer::Number;
|
||||
pub use crate::parser::lexer::Variable;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@ -62,9 +63,9 @@ pub struct Call<'i> {
|
||||
pub enum CallInstrValue<'i> {
|
||||
InitPeerId,
|
||||
Literal(&'i str),
|
||||
Variable(&'i str),
|
||||
Variable(Variable<'i>),
|
||||
JsonPath {
|
||||
variable: &'i str,
|
||||
variable: Variable<'i>,
|
||||
path: &'i str,
|
||||
should_flatten: bool,
|
||||
},
|
||||
@ -77,9 +78,9 @@ pub enum CallInstrArgValue<'i> {
|
||||
Literal(&'i str),
|
||||
Number(Number),
|
||||
Boolean(bool),
|
||||
Variable(&'i str),
|
||||
Variable(Variable<'i>),
|
||||
JsonPath {
|
||||
variable: &'i str,
|
||||
variable: Variable<'i>,
|
||||
path: &'i str,
|
||||
should_flatten: bool,
|
||||
},
|
||||
@ -87,9 +88,9 @@ pub enum CallInstrArgValue<'i> {
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub enum IterableValue<'i> {
|
||||
Variable(&'i str),
|
||||
Variable(Variable<'i>),
|
||||
JsonPath {
|
||||
variable: &'i str,
|
||||
variable: Variable<'i>,
|
||||
path: &'i str,
|
||||
should_flatten: bool,
|
||||
},
|
||||
@ -100,9 +101,9 @@ pub enum MatchableValue<'i> {
|
||||
Literal(&'i str),
|
||||
Number(Number),
|
||||
Boolean(bool),
|
||||
Variable(&'i str),
|
||||
Variable(Variable<'i>),
|
||||
JsonPath {
|
||||
variable: &'i str,
|
||||
variable: Variable<'i>,
|
||||
path: &'i str,
|
||||
should_flatten: bool,
|
||||
},
|
||||
@ -110,8 +111,7 @@ pub enum MatchableValue<'i> {
|
||||
|
||||
#[derive(Serialize, Debug, PartialEq, Clone)]
|
||||
pub enum CallOutputValue<'i> {
|
||||
Scalar(&'i str),
|
||||
Accumulator(&'i str),
|
||||
Variable(Variable<'i>),
|
||||
None,
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,8 @@ impl fmt::Display for CallInstrArgValue<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn print_json_path(
|
||||
variable: &str,
|
||||
fn print_json_path<'a>(
|
||||
variable: &Variable<'a>,
|
||||
path: &str,
|
||||
should_flatten: &bool,
|
||||
f: &mut fmt::Formatter,
|
||||
@ -104,8 +104,7 @@ impl fmt::Display for CallOutputValue<'_> {
|
||||
use CallOutputValue::*;
|
||||
|
||||
match self {
|
||||
Scalar(str) => write!(f, "{}", str),
|
||||
Accumulator(str) => write!(f, "{}[]", str),
|
||||
Variable(variable) => write!(f, "{}", variable),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
use super::errors::LexerError;
|
||||
use super::is_aqua_alphanumeric;
|
||||
use super::token::Token;
|
||||
use super::LexerResult;
|
||||
|
||||
@ -191,31 +190,10 @@ fn string_to_token(input: &str, start_pos: usize) -> LexerResult<Token> {
|
||||
TRUE_VALUE => Ok(Token::Boolean(true)),
|
||||
FALSE_VALUE => Ok(Token::Boolean(false)),
|
||||
|
||||
str if str.ends_with(ACC_END_TAG) => try_parse_accumulator(str, start_pos),
|
||||
str => super::call_variable_parser::try_parse_call_variable(str, start_pos),
|
||||
}
|
||||
}
|
||||
|
||||
fn try_parse_accumulator(maybe_acc: &str, start: usize) -> LexerResult<Token> {
|
||||
const ACC_END_TAG_SIZE: usize = 2;
|
||||
|
||||
let str_len = maybe_acc.len();
|
||||
if str_len == ACC_END_TAG_SIZE {
|
||||
return Err(LexerError::EmptyAccName(start, start));
|
||||
}
|
||||
|
||||
// this slice is safe here because str's been checked for ending with "[]"
|
||||
let maybe_acc = &maybe_acc[0..str_len - ACC_END_TAG_SIZE];
|
||||
|
||||
for (pos, ch) in maybe_acc.chars().enumerate() {
|
||||
if !is_aqua_alphanumeric(ch) {
|
||||
return Err(LexerError::IsNotAlphanumeric(start + pos, start + pos));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Token::Accumulator(maybe_acc))
|
||||
}
|
||||
|
||||
const CALL_INSTR: &str = "call";
|
||||
const SEQ_INSTR: &str = "seq";
|
||||
const PAR_INSTR: &str = "par";
|
||||
@ -231,5 +209,3 @@ const LAST_ERROR: &str = "%last_error%";
|
||||
|
||||
const TRUE_VALUE: &str = "true";
|
||||
const FALSE_VALUE: &str = "false";
|
||||
|
||||
const ACC_END_TAG: &str = "[]";
|
||||
|
@ -17,6 +17,7 @@
|
||||
use super::LexerError;
|
||||
use super::LexerResult;
|
||||
use super::Token;
|
||||
use super::Variable;
|
||||
|
||||
use std::convert::TryInto;
|
||||
use std::iter::Peekable;
|
||||
@ -36,6 +37,7 @@ struct ParserState {
|
||||
pub(self) digit_met: bool,
|
||||
pub(self) flattening_met: bool,
|
||||
pub(self) is_first_char: bool,
|
||||
pub(self) is_first_stream_tag: bool,
|
||||
pub(self) current_char: char,
|
||||
pub(self) current_pos: usize,
|
||||
}
|
||||
@ -61,6 +63,7 @@ impl<'input> CallVariableParser<'input> {
|
||||
digit_met: false,
|
||||
flattening_met: false,
|
||||
is_first_char: true,
|
||||
is_first_stream_tag: false,
|
||||
current_char,
|
||||
current_pos,
|
||||
};
|
||||
@ -164,7 +167,7 @@ impl<'input> CallVariableParser<'input> {
|
||||
}
|
||||
|
||||
fn try_parse_as_variable(&mut self) -> LexerResult<()> {
|
||||
if self.try_parse_as_json_path_start()? {
|
||||
if self.try_parse_as_stream_start()? || self.try_parse_as_json_path_start()? {
|
||||
return Ok(());
|
||||
} else if self.is_json_path_started() {
|
||||
self.try_parse_as_json_path()?;
|
||||
@ -175,6 +178,20 @@ impl<'input> CallVariableParser<'input> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_parse_as_stream_start(&mut self) -> LexerResult<bool> {
|
||||
if self.current_pos() == 0 && self.current_char() == STREAM_START_TAG {
|
||||
if self.string_to_parse.len() == 1 {
|
||||
let error_pos = self.pos_in_string_to_parse();
|
||||
return Err(LexerError::EmptyStreamName(error_pos, error_pos));
|
||||
}
|
||||
|
||||
self.state.is_first_stream_tag = true;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn try_parse_as_json_path_start(&mut self) -> LexerResult<bool> {
|
||||
self.try_parse_first_met_dot()
|
||||
}
|
||||
@ -253,6 +270,15 @@ impl<'input> CallVariableParser<'input> {
|
||||
self.current_pos() == self.string_to_parse.len() - 1
|
||||
}
|
||||
|
||||
fn to_variable<'v>(&self, variable_name: &'v str) -> Variable<'v> {
|
||||
if self.state.is_first_stream_tag {
|
||||
// TODO: cut the stream tag after the refactoring.
|
||||
Variable::Stream(variable_name)
|
||||
} else {
|
||||
Variable::Scalar(variable_name)
|
||||
}
|
||||
}
|
||||
|
||||
fn to_token(&self) -> LexerResult<Token<'input>> {
|
||||
use super::token::UnparsedNumber;
|
||||
|
||||
@ -267,12 +293,42 @@ impl<'input> CallVariableParser<'input> {
|
||||
let number: super::Number = number.try_into()?;
|
||||
Ok(number.into())
|
||||
}
|
||||
(false, false) => Ok(Token::Alphanumeric(self.string_to_parse)),
|
||||
(false, true) => Ok(Token::JsonPath(
|
||||
self.string_to_parse,
|
||||
self.state.first_dot_met_pos.unwrap(),
|
||||
self.state.flattening_met,
|
||||
)),
|
||||
(false, false) => {
|
||||
if self.state.is_first_stream_tag {
|
||||
Ok(Token::Stream(&self.string_to_parse))
|
||||
} else {
|
||||
Ok(Token::Alphanumeric(&self.string_to_parse))
|
||||
}
|
||||
}
|
||||
(false, true) => {
|
||||
let json_path_start_pos = self.state.first_dot_met_pos.unwrap();
|
||||
let should_flatten = self.state.flattening_met;
|
||||
let (variable, json_path) = to_variable_and_path(
|
||||
&self.string_to_parse,
|
||||
json_path_start_pos,
|
||||
should_flatten,
|
||||
);
|
||||
let variable = self.to_variable(variable);
|
||||
|
||||
Ok(Token::VariableWithJsonPath(
|
||||
variable,
|
||||
json_path,
|
||||
should_flatten,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const STREAM_START_TAG: char = '$';
|
||||
|
||||
fn to_variable_and_path(str: &str, pos: usize, should_flatten: bool) -> (&str, &str) {
|
||||
let json_path = if should_flatten {
|
||||
// -1 to not include the flattening symbol ! to the resulted json path
|
||||
&str[pos + 1..str.len() - 1]
|
||||
} else {
|
||||
&str[pos + 1..]
|
||||
};
|
||||
|
||||
(&str[0..pos], json_path)
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ pub enum LexerError {
|
||||
#[error("only alphanumeric, '_', and '-' characters are allowed in this position")]
|
||||
IsNotAlphanumeric(usize, usize),
|
||||
|
||||
#[error("an accumulator name should be non empty")]
|
||||
EmptyAccName(usize, usize),
|
||||
#[error("a stream name should be non empty")]
|
||||
EmptyStreamName(usize, usize),
|
||||
|
||||
#[error("this variable or constant shouldn't have empty name")]
|
||||
EmptyVariableOrConst(usize, usize),
|
||||
|
@ -27,6 +27,7 @@ pub use air_lexer::AIRLexer;
|
||||
pub use errors::LexerError;
|
||||
pub use token::Number;
|
||||
pub use token::Token;
|
||||
pub use token::Variable;
|
||||
|
||||
pub(super) type LexerResult<T> = std::result::Result<T, LexerError>;
|
||||
|
||||
|
@ -19,6 +19,7 @@ use super::AIRLexer;
|
||||
use super::LexerError;
|
||||
use super::Number;
|
||||
use super::Token;
|
||||
use super::Variable;
|
||||
|
||||
fn run_lexer(input: &str) -> Vec<Spanned<Token<'_>, usize, LexerError>> {
|
||||
let lexer = AIRLexer::new(input);
|
||||
@ -152,17 +153,10 @@ fn init_peer_id() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accumulator() {
|
||||
const ACC: &str = "accumulator____asdasd[]";
|
||||
fn stream() {
|
||||
const STREAM: &str = "$stream____asdasd";
|
||||
|
||||
lexer_test(
|
||||
ACC,
|
||||
Single(Ok((
|
||||
0,
|
||||
Token::Accumulator(&ACC[0..ACC.len() - 2]),
|
||||
ACC.len(),
|
||||
))),
|
||||
);
|
||||
lexer_test(STREAM, Single(Ok((0, Token::Stream(STREAM), STREAM.len()))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -268,14 +262,15 @@ fn too_big_float_number() {
|
||||
|
||||
#[test]
|
||||
fn json_path() {
|
||||
// this json path contains all allowed in json path charactes
|
||||
// this json path contains all allowed in json path characters
|
||||
const JSON_PATH: &str = r#"value.$[$@[]():?.*,"]"#;
|
||||
let variable = Variable::Scalar("value");
|
||||
|
||||
lexer_test(
|
||||
JSON_PATH,
|
||||
Single(Ok((
|
||||
0,
|
||||
Token::JsonPath(JSON_PATH, 5, false),
|
||||
Token::VariableWithJsonPath(variable, r#"$[$@[]():?.*,"]"#, false),
|
||||
JSON_PATH.len(),
|
||||
))),
|
||||
);
|
||||
|
@ -17,7 +17,7 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Token<'input> {
|
||||
OpenRoundBracket,
|
||||
CloseRoundBracket,
|
||||
@ -26,8 +26,8 @@ pub enum Token<'input> {
|
||||
|
||||
StringLiteral(&'input str),
|
||||
Alphanumeric(&'input str),
|
||||
JsonPath(&'input str, usize, bool),
|
||||
Accumulator(&'input str),
|
||||
Stream(&'input str),
|
||||
VariableWithJsonPath(Variable<'input>, &'input str, bool),
|
||||
Number(Number),
|
||||
Boolean(bool),
|
||||
|
||||
@ -45,6 +45,12 @@ pub enum Token<'input> {
|
||||
MisMatch,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Hash, Serialize, Deserialize)]
|
||||
pub enum Variable<'input> {
|
||||
Scalar(&'input str),
|
||||
Stream(&'input str),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub enum Number {
|
||||
Int(i64),
|
||||
@ -64,6 +70,17 @@ impl fmt::Display for Number {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Variable<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use Variable::*;
|
||||
|
||||
match self {
|
||||
Scalar(name) => write!(f, "{}", name),
|
||||
Stream(name) => write!(f, "&{}", name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Number> for Token<'_> {
|
||||
fn from(value: Number) -> Self {
|
||||
Token::Number(value)
|
||||
|
@ -17,7 +17,12 @@
|
||||
use crate::ast;
|
||||
use crate::parser::AIRParser;
|
||||
use crate::parser::ParserError;
|
||||
use ast::Call;
|
||||
use ast::CallInstrArgValue;
|
||||
use ast::CallInstrValue;
|
||||
use ast::Instruction;
|
||||
use ast::Variable::Scalar;
|
||||
use ast::Variable::Stream;
|
||||
|
||||
use fstrings::f;
|
||||
use lalrpop_util::ParseError;
|
||||
@ -32,15 +37,12 @@ fn parse(source_code: &str) -> Instruction {
|
||||
let mut validator = crate::parser::VariableValidator::new();
|
||||
parser
|
||||
.parse(source_code, &mut errors, &mut validator, lexer)
|
||||
.expect("parsing should be successfull")
|
||||
.expect("parsing should be successful")
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_seq() {
|
||||
use ast::Call;
|
||||
use ast::CallInstrArgValue;
|
||||
use ast::CallInstrValue;
|
||||
use ast::CallOutputValue::*;
|
||||
use ast::FunctionPart::*;
|
||||
use ast::PeerPart::*;
|
||||
@ -54,17 +56,17 @@ fn parse_seq() {
|
||||
let instruction = parse(source_code);
|
||||
let expected = seq(
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(CallInstrValue::Variable("peerid")),
|
||||
function_part: FuncName(CallInstrValue::Variable("function")),
|
||||
peer_part: PeerPk(CallInstrValue::Variable(Scalar("peerid"))),
|
||||
function_part: FuncName(CallInstrValue::Variable(Scalar("function"))),
|
||||
args: Rc::new(vec![]),
|
||||
output: Scalar("output"),
|
||||
output: Variable(Scalar("output")),
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(CallInstrValue::Literal("id")),
|
||||
function_part: FuncName(CallInstrValue::Literal("f")),
|
||||
args: Rc::new(vec![
|
||||
CallInstrArgValue::Literal("hello"),
|
||||
CallInstrArgValue::Variable("name"),
|
||||
CallInstrArgValue::Variable(Scalar("name")),
|
||||
]),
|
||||
output: None,
|
||||
}),
|
||||
@ -74,9 +76,6 @@ fn parse_seq() {
|
||||
|
||||
#[test]
|
||||
fn parse_seq_seq() {
|
||||
use ast::Call;
|
||||
use ast::CallInstrArgValue;
|
||||
use ast::CallInstrValue;
|
||||
use ast::CallOutputValue::*;
|
||||
use ast::FunctionPart::*;
|
||||
use ast::PeerPart::*;
|
||||
@ -87,26 +86,26 @@ fn parse_seq_seq() {
|
||||
(call peerid function [])
|
||||
(call (peerid serviceA) ("serviceB" function) [])
|
||||
)
|
||||
(call "id" "f" ["hello" name] output[])
|
||||
(call "id" "f" ["hello" name] $output)
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = seq(
|
||||
seq(
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(CallInstrValue::Variable("peerid")),
|
||||
function_part: FuncName(CallInstrValue::Variable("function")),
|
||||
peer_part: PeerPk(CallInstrValue::Variable(Scalar("peerid"))),
|
||||
function_part: FuncName(CallInstrValue::Variable(Scalar("function"))),
|
||||
args: Rc::new(vec![]),
|
||||
output: None,
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPkWithServiceId(
|
||||
CallInstrValue::Variable("peerid"),
|
||||
CallInstrValue::Variable("serviceA"),
|
||||
CallInstrValue::Variable(Scalar("peerid")),
|
||||
CallInstrValue::Variable(Scalar("serviceA")),
|
||||
),
|
||||
function_part: ServiceIdWithFuncName(
|
||||
CallInstrValue::Literal("serviceB"),
|
||||
CallInstrValue::Variable("function"),
|
||||
CallInstrValue::Variable(Scalar("function")),
|
||||
),
|
||||
args: Rc::new(vec![]),
|
||||
output: None,
|
||||
@ -117,9 +116,9 @@ fn parse_seq_seq() {
|
||||
function_part: FuncName(CallInstrValue::Literal("f")),
|
||||
args: Rc::new(vec![
|
||||
CallInstrArgValue::Literal("hello"),
|
||||
CallInstrArgValue::Variable("name"),
|
||||
CallInstrArgValue::Variable(Scalar("name")),
|
||||
]),
|
||||
output: Accumulator("output"),
|
||||
output: Variable(Stream("$output")),
|
||||
}),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
@ -127,29 +126,26 @@ fn parse_seq_seq() {
|
||||
|
||||
#[test]
|
||||
fn parse_json_path() {
|
||||
use ast::Call;
|
||||
use ast::CallInstrArgValue;
|
||||
use ast::CallInstrValue;
|
||||
use ast::CallOutputValue::*;
|
||||
use ast::FunctionPart::*;
|
||||
use ast::PeerPart::*;
|
||||
|
||||
let source_code = r#"
|
||||
(call id.$.a! "f" ["hello" name] void[])
|
||||
(call id.$.a! "f" ["hello" name] $void)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = Instruction::Call(Call {
|
||||
peer_part: PeerPk(CallInstrValue::JsonPath {
|
||||
variable: "id",
|
||||
variable: Scalar("id"),
|
||||
path: "$.a",
|
||||
should_flatten: true,
|
||||
}),
|
||||
function_part: FuncName(CallInstrValue::Literal("f")),
|
||||
args: Rc::new(vec![
|
||||
CallInstrArgValue::Literal("hello"),
|
||||
CallInstrArgValue::Variable("name"),
|
||||
CallInstrArgValue::Variable(Scalar("name")),
|
||||
]),
|
||||
output: Accumulator("void"),
|
||||
output: Variable(Stream("$void")),
|
||||
});
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
@ -157,7 +153,7 @@ fn parse_json_path() {
|
||||
#[test]
|
||||
fn parse_undefined_variable() {
|
||||
let source_code = r#"
|
||||
(call id.$.a "f" ["hello" name] void[])
|
||||
(call id.$.a "f" ["hello" name] $void)
|
||||
"#;
|
||||
|
||||
let lexer = crate::AIRLexer::new(source_code);
|
||||
@ -190,7 +186,7 @@ fn parse_undefined_iterable() {
|
||||
(call "" ("" "") [] iterable)
|
||||
(fold iterable i
|
||||
(seq
|
||||
(call "" ("" "") ["hello" ""] void[])
|
||||
(call "" ("" "") ["hello" ""] $void)
|
||||
(next j)
|
||||
)
|
||||
)
|
||||
@ -221,8 +217,6 @@ fn parse_undefined_iterable() {
|
||||
|
||||
#[test]
|
||||
fn parse_json_path_complex() {
|
||||
use ast::Call;
|
||||
use ast::CallInstrValue;
|
||||
use ast::CallOutputValue::*;
|
||||
use ast::FunctionPart::*;
|
||||
use ast::PeerPart::*;
|
||||
@ -237,23 +231,23 @@ fn parse_json_path_complex() {
|
||||
let expected = seq(
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(CallInstrValue::JsonPath {
|
||||
variable: "m",
|
||||
variable: Scalar("m"),
|
||||
path: "$.[1]",
|
||||
should_flatten: true,
|
||||
}),
|
||||
function_part: FuncName(CallInstrValue::Literal("f")),
|
||||
args: Rc::new(vec![]),
|
||||
output: Scalar("void"),
|
||||
output: Variable(Scalar("void")),
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(CallInstrValue::JsonPath {
|
||||
variable: "m",
|
||||
variable: Scalar("m"),
|
||||
path: r#"$.abc["c"].cde[a][0].cde["bcd"]"#,
|
||||
should_flatten: true,
|
||||
}),
|
||||
function_part: FuncName(CallInstrValue::Literal("f")),
|
||||
args: Rc::new(vec![]),
|
||||
output: Scalar("void"),
|
||||
output: Variable(Scalar("void")),
|
||||
}),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
@ -261,20 +255,17 @@ fn parse_json_path_complex() {
|
||||
|
||||
#[test]
|
||||
fn json_path_square_braces() {
|
||||
use ast::Call;
|
||||
use ast::CallInstrArgValue;
|
||||
use ast::CallInstrValue;
|
||||
use ast::CallOutputValue::*;
|
||||
use ast::FunctionPart::*;
|
||||
use ast::PeerPart::*;
|
||||
|
||||
let source_code = r#"
|
||||
(call u.$["peer_id"]! ("return" "") [u.$["peer_id"].cde[0]["abc"].abc u.$["name"]] void[])
|
||||
(call u.$["peer_id"]! ("return" "") [u.$["peer_id"].cde[0]["abc"].abc u.$["name"]] $void)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = Instruction::Call(Call {
|
||||
peer_part: PeerPk(CallInstrValue::JsonPath {
|
||||
variable: "u",
|
||||
variable: Scalar("u"),
|
||||
path: r#"$["peer_id"]"#,
|
||||
should_flatten: true,
|
||||
}),
|
||||
@ -284,17 +275,17 @@ fn json_path_square_braces() {
|
||||
),
|
||||
args: Rc::new(vec![
|
||||
CallInstrArgValue::JsonPath {
|
||||
variable: "u",
|
||||
variable: Scalar("u"),
|
||||
path: r#"$["peer_id"].cde[0]["abc"].abc"#,
|
||||
should_flatten: false,
|
||||
},
|
||||
CallInstrArgValue::JsonPath {
|
||||
variable: "u",
|
||||
variable: Scalar("u"),
|
||||
path: r#"$["name"]"#,
|
||||
should_flatten: false,
|
||||
},
|
||||
]),
|
||||
output: Accumulator("void"),
|
||||
output: Variable(Stream("$void")),
|
||||
});
|
||||
|
||||
assert_eq!(instruction, expected);
|
||||
@ -344,8 +335,12 @@ fn parse_fold() {
|
||||
(null)
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = fold(ast::IterableValue::Variable("iterable"), "i", null());
|
||||
let instruction = parse(&source_code);
|
||||
let expected = fold(
|
||||
ast::IterableValue::Variable(Scalar("iterable")),
|
||||
"i",
|
||||
null(),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
@ -358,8 +353,8 @@ fn parse_match() {
|
||||
(null)
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = match_(Variable("v1"), Variable("v2"), null());
|
||||
let instruction = parse(&source_code);
|
||||
let expected = match_(Variable(Scalar("v1")), Variable(Scalar("v2")), null());
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
@ -372,8 +367,8 @@ fn parse_mismatch() {
|
||||
(null)
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = mismatch(Variable("v1"), Variable("v2"), null());
|
||||
let instruction = parse(&source_code);
|
||||
let expected = mismatch(Variable(Scalar("v1")), Variable(Scalar("v2")), null());
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
@ -389,7 +384,7 @@ fn parse_fold_with_xor_par_seq() {
|
||||
let instruction = parse(&source_code);
|
||||
let instr = binary_instruction(*name);
|
||||
let expected = fold(
|
||||
ast::IterableValue::Variable("iterable"),
|
||||
ast::IterableValue::Variable(Scalar("iterable")),
|
||||
"i",
|
||||
instr(null(), null()),
|
||||
);
|
||||
@ -505,7 +500,7 @@ fn seq_par_call() {
|
||||
CallInstrValue::Literal("local_fn_name"),
|
||||
),
|
||||
args: Rc::new(vec![]),
|
||||
output: Scalar("result_1"),
|
||||
output: Variable(Scalar("result_1")),
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(CallInstrValue::Literal(&peer_id)),
|
||||
@ -514,7 +509,7 @@ fn seq_par_call() {
|
||||
CallInstrValue::Literal("fn_name"),
|
||||
),
|
||||
args: Rc::new(vec![]),
|
||||
output: Scalar("g"),
|
||||
output: Variable(Scalar("g")),
|
||||
}),
|
||||
),
|
||||
Instruction::Call(Call {
|
||||
@ -524,7 +519,7 @@ fn seq_par_call() {
|
||||
CallInstrValue::Literal("local_fn_name"),
|
||||
),
|
||||
args: Rc::new(vec![]),
|
||||
output: Scalar("result_2"),
|
||||
output: Variable(Scalar("result_2")),
|
||||
}),
|
||||
);
|
||||
|
||||
@ -572,7 +567,7 @@ fn seq_with_empty_and_dash() {
|
||||
CallInstrValue::Literal(""),
|
||||
),
|
||||
args: Rc::new(vec![CallInstrArgValue::Literal("module-bytes")]),
|
||||
output: Scalar("module-bytes"),
|
||||
output: Variable(Scalar("module-bytes")),
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(CallInstrValue::Literal("set_variables")),
|
||||
@ -581,7 +576,7 @@ fn seq_with_empty_and_dash() {
|
||||
CallInstrValue::Literal(""),
|
||||
),
|
||||
args: Rc::new(vec![CallInstrArgValue::Literal("module_config")]),
|
||||
output: Scalar("module_config"),
|
||||
output: Variable(Scalar("module_config")),
|
||||
}),
|
||||
),
|
||||
Instruction::Call(Call {
|
||||
@ -591,7 +586,7 @@ fn seq_with_empty_and_dash() {
|
||||
CallInstrValue::Literal(""),
|
||||
),
|
||||
args: Rc::new(vec![CallInstrArgValue::Literal("blueprint")]),
|
||||
output: Scalar("blueprint"),
|
||||
output: Variable(Scalar("blueprint")),
|
||||
}),
|
||||
),
|
||||
seq(
|
||||
@ -602,10 +597,10 @@ fn seq_with_empty_and_dash() {
|
||||
CallInstrValue::Literal(""),
|
||||
),
|
||||
args: Rc::new(vec![
|
||||
CallInstrArgValue::Variable("module-bytes"),
|
||||
CallInstrArgValue::Variable("module_config"),
|
||||
CallInstrArgValue::Variable(Scalar("module-bytes")),
|
||||
CallInstrArgValue::Variable(Scalar("module_config")),
|
||||
]),
|
||||
output: Scalar("module"),
|
||||
output: Variable(Scalar("module")),
|
||||
}),
|
||||
seq(
|
||||
Instruction::Call(Call {
|
||||
@ -614,8 +609,8 @@ fn seq_with_empty_and_dash() {
|
||||
CallInstrValue::Literal("add_blueprint"),
|
||||
CallInstrValue::Literal(""),
|
||||
),
|
||||
args: Rc::new(vec![CallInstrArgValue::Variable("blueprint")]),
|
||||
output: Scalar("blueprint_id"),
|
||||
args: Rc::new(vec![CallInstrArgValue::Variable(Scalar("blueprint"))]),
|
||||
output: Variable(Scalar("blueprint_id")),
|
||||
}),
|
||||
seq(
|
||||
Instruction::Call(Call {
|
||||
@ -624,8 +619,8 @@ fn seq_with_empty_and_dash() {
|
||||
CallInstrValue::Literal("create"),
|
||||
CallInstrValue::Literal(""),
|
||||
),
|
||||
args: Rc::new(vec![CallInstrArgValue::Variable("blueprint_id")]),
|
||||
output: Scalar("service_id"),
|
||||
args: Rc::new(vec![CallInstrArgValue::Variable(Scalar("blueprint_id"))]),
|
||||
output: Variable(Scalar("service_id")),
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(CallInstrValue::Literal("remote_peer_id")),
|
||||
@ -633,8 +628,8 @@ fn seq_with_empty_and_dash() {
|
||||
CallInstrValue::Literal(""),
|
||||
CallInstrValue::Literal(""),
|
||||
),
|
||||
args: Rc::new(vec![CallInstrArgValue::Variable("service_id")]),
|
||||
output: Scalar("client_result"),
|
||||
args: Rc::new(vec![CallInstrArgValue::Variable(Scalar("service_id"))]),
|
||||
output: Variable(Scalar("client_result")),
|
||||
}),
|
||||
),
|
||||
),
|
||||
@ -654,7 +649,7 @@ fn match_with_bool() {
|
||||
)
|
||||
"#;
|
||||
|
||||
let left_value = Variable("isOnline");
|
||||
let left_value = Variable(Scalar("isOnline"));
|
||||
let right_value = Boolean(true);
|
||||
let null = null();
|
||||
let expected = match_(left_value, right_value, null);
|
||||
@ -674,7 +669,7 @@ fn mismatch_with_bool() {
|
||||
"#;
|
||||
|
||||
let left_value = Boolean(true);
|
||||
let right_value = Variable("isOnline");
|
||||
let right_value = Variable(Scalar("isOnline"));
|
||||
let null = null();
|
||||
let expected = mismatch(left_value, right_value, null);
|
||||
|
||||
@ -695,10 +690,10 @@ fn no_output() {
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = Instruction::Call(Call {
|
||||
peer_part: PeerPk(CallInstrValue::Variable("peer")),
|
||||
peer_part: PeerPk(CallInstrValue::Variable(Scalar("peer"))),
|
||||
function_part: ServiceIdWithFuncName(
|
||||
CallInstrValue::Variable("service"),
|
||||
CallInstrValue::Variable("fname"),
|
||||
CallInstrValue::Variable(Scalar("service")),
|
||||
CallInstrValue::Variable(Scalar("fname")),
|
||||
),
|
||||
args: Rc::new(vec![]),
|
||||
output: None,
|
||||
@ -719,7 +714,7 @@ fn fold_json_path() {
|
||||
let instruction = parse(source_code);
|
||||
let expected = Instruction::Fold(Fold {
|
||||
iterable: JsonPath {
|
||||
variable: "members",
|
||||
variable: Scalar("members"),
|
||||
path: "$.[\"users\"]",
|
||||
should_flatten: false,
|
||||
},
|
||||
@ -742,7 +737,7 @@ fn comments() {
|
||||
let instruction = parse(source_code);
|
||||
let expected = Instruction::Fold(Fold {
|
||||
iterable: JsonPath {
|
||||
variable: "members",
|
||||
variable: Scalar("members"),
|
||||
path: "$.[\"users\"]",
|
||||
should_flatten: false,
|
||||
},
|
||||
|
@ -143,7 +143,12 @@ impl<'i> VariableValidator<'i> {
|
||||
}
|
||||
}
|
||||
|
||||
fn met_variable(&mut self, name: &'i str, span: Span) {
|
||||
fn met_variable(&mut self, variable: &Variable<'i>, span: Span) {
|
||||
let name = match variable {
|
||||
Variable::Scalar(name) => name,
|
||||
Variable::Stream(name) => name,
|
||||
};
|
||||
|
||||
if !self.contains_variable(name, span) {
|
||||
self.unresolved_variables.insert(name, span);
|
||||
}
|
||||
@ -168,8 +173,8 @@ impl<'i> VariableValidator<'i> {
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
let variable_name = match call_output {
|
||||
CallOutputValue::Scalar(variable) => variable,
|
||||
CallOutputValue::Accumulator(accumulator) => accumulator,
|
||||
CallOutputValue::Variable(Variable::Scalar(name)) => name,
|
||||
CallOutputValue::Variable(Variable::Stream(name)) => name,
|
||||
CallOutputValue::None => return,
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "interpreter-lib"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
||||
|
@ -35,16 +35,16 @@ fn chat_sent_message_benchmark() -> Result<InterpreterOutcome, AquamarineVMError
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq
|
||||
(call "Relay1" ("identity" "") [] void1[])
|
||||
(call "Relay1" ("identity" "") [] $void1)
|
||||
(seq
|
||||
(call "Remote" ("552196ea-b9b2-4761-98d4-8e7dba77fac4" "add") [] void2[])
|
||||
(call "Remote" ("552196ea-b9b2-4761-98d4-8e7dba77fac4" "add") [] $void2)
|
||||
(seq
|
||||
(call "Remote" ("920e3ba3-cbdf-4ae3-8972-0fa2f31fffd9" "get_users") [] members)
|
||||
(fold members m
|
||||
(par
|
||||
(seq
|
||||
(call m.$.[1] ("identity" "") [] void[])
|
||||
(call m.$.[0] ("fgemb3" "add") [] void3[])
|
||||
(call m.$.[1] ("identity" "") [] $void)
|
||||
(call m.$.[0] ("fgemb3" "add") [] $void3)
|
||||
)
|
||||
(next m)
|
||||
)
|
||||
|
@ -34,7 +34,7 @@ pub struct ResolvedCallResult {
|
||||
|
||||
pub(crate) enum AValue<'i> {
|
||||
JValueRef(ResolvedCallResult),
|
||||
JValueAccumulatorRef(RefCell<Vec<ResolvedCallResult>>),
|
||||
JValueStreamRef(RefCell<Vec<ResolvedCallResult>>),
|
||||
JValueFoldCursor(FoldState<'i>),
|
||||
}
|
||||
|
||||
@ -42,9 +42,9 @@ impl<'i> Display for AValue<'i> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
AValue::JValueRef(value) => write!(f, "{:?}", value)?,
|
||||
AValue::JValueAccumulatorRef(acc) => {
|
||||
AValue::JValueStreamRef(stream) => {
|
||||
write!(f, "[ ")?;
|
||||
for value in acc.borrow().iter() {
|
||||
for value in stream.borrow().iter() {
|
||||
write!(f, "{:?} ", value)?;
|
||||
}
|
||||
write!(f, "]")?;
|
||||
|
@ -26,18 +26,18 @@ use std::fmt::Formatter;
|
||||
|
||||
pub type ExecutionTrace = std::collections::VecDeque<ExecutedState>;
|
||||
|
||||
/// Encapsulates all necessary state regarding to the call pathes1.
|
||||
/// Encapsulates all necessary state regarding to the call paths.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub(crate) struct ExecutionTraceCtx {
|
||||
/// Contains trace (serialized tree of states) after merging current and previous data,
|
||||
/// interpreter used it to realize which instructions've been already executed.
|
||||
/// interpreter used it to realize which instructions have been already executed.
|
||||
pub(crate) current_trace: ExecutionTrace,
|
||||
|
||||
/// Size of a current considered subtree inside current path.
|
||||
pub(crate) current_subtree_size: usize,
|
||||
|
||||
// TODO: consider change it to Vec for optimization
|
||||
/// Accumulator for resulted path produced by the interpreter after execution.
|
||||
/// Stream for resulted path produced by the interpreter after execution.
|
||||
pub(crate) new_trace: ExecutionTrace,
|
||||
}
|
||||
|
||||
|
@ -79,12 +79,14 @@ impl<'a, 'i> Triplet<'a, 'i> {
|
||||
/// Resolve value to string by either resolving variable from `ExecutionCtx`, taking literal value, or etc.
|
||||
// TODO: return Rc<String> to avoid excess cloning
|
||||
fn resolve_to_string<'i>(value: &CallInstrValue<'i>, ctx: &ExecutionCtx<'i>) -> ExecutionResult<String> {
|
||||
use crate::execution::utils::get_variable_name;
|
||||
use crate::execution::utils::resolve_to_jvaluable;
|
||||
|
||||
let resolved = match value {
|
||||
CallInstrValue::InitPeerId => ctx.init_peer_id.clone(),
|
||||
CallInstrValue::Literal(value) => value.to_string(),
|
||||
CallInstrValue::Variable(name) => {
|
||||
CallInstrValue::Variable(variable) => {
|
||||
let name = get_variable_name(variable);
|
||||
let resolved = resolve_to_jvaluable(name, ctx)?;
|
||||
let jvalue = resolved.into_jvalue();
|
||||
jvalue_to_string(jvalue)?
|
||||
@ -97,7 +99,9 @@ fn resolve_to_string<'i>(value: &CallInstrValue<'i>, ctx: &ExecutionCtx<'i>) ->
|
||||
// this is checked on the parsing stage
|
||||
debug_assert!(*should_flatten);
|
||||
|
||||
let resolved = resolve_to_jvaluable(variable, ctx)?;
|
||||
let name = get_variable_name(variable);
|
||||
|
||||
let resolved = resolve_to_jvaluable(name, ctx)?;
|
||||
let resolved = resolved.apply_json_path(path)?;
|
||||
vec_to_string(resolved, path)?
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ use super::ExecutionResult;
|
||||
use crate::contexts::execution::ResolvedCallResult;
|
||||
use crate::contexts::execution_trace::*;
|
||||
use crate::exec_err;
|
||||
use crate::execution::Variable;
|
||||
use crate::log_targets::EXECUTED_STATE_CHANGING;
|
||||
use crate::JValue;
|
||||
|
||||
@ -43,7 +44,7 @@ pub(super) fn set_local_call_result<'i>(
|
||||
let executed_result = ResolvedCallResult { result, triplet };
|
||||
|
||||
match output {
|
||||
CallOutputValue::Scalar(name) => {
|
||||
CallOutputValue::Variable(Variable::Scalar(name)) => {
|
||||
if let Some(fold_block_name) = exec_ctx.met_folds.back() {
|
||||
let fold_state = match exec_ctx.data_cache.get_mut(*fold_block_name) {
|
||||
Some(AValue::JValueFoldCursor(fold_state)) => fold_state,
|
||||
@ -74,15 +75,15 @@ pub(super) fn set_local_call_result<'i>(
|
||||
}
|
||||
};
|
||||
}
|
||||
CallOutputValue::Accumulator(name) => {
|
||||
CallOutputValue::Variable(Variable::Stream(name)) => {
|
||||
match exec_ctx.data_cache.entry(name.to_string()) {
|
||||
Occupied(mut entry) => match entry.get_mut() {
|
||||
// if result is an array, insert result to the end of the array
|
||||
AValue::JValueAccumulatorRef(values) => values.borrow_mut().push(executed_result),
|
||||
AValue::JValueStreamRef(values) => values.borrow_mut().push(executed_result),
|
||||
v => return exec_err!(IncompatibleAValueType(format!("{}", v), String::from("Array"))),
|
||||
},
|
||||
Vacant(entry) => {
|
||||
entry.insert(AValue::JValueAccumulatorRef(RefCell::new(vec![executed_result])));
|
||||
entry.insert(AValue::JValueStreamRef(RefCell::new(vec![executed_result])));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
use crate::contexts::execution::ExecutionCtx;
|
||||
use crate::execution::air::ExecutionResult;
|
||||
use crate::execution::utils::get_variable_name;
|
||||
use crate::execution::utils::resolve_to_jvaluable;
|
||||
use crate::JValue;
|
||||
|
||||
@ -41,10 +42,12 @@ pub(crate) fn are_matchable_eq<'ctx>(
|
||||
(Number(value), matchable) => compare_matchable(matchable, exec_ctx, make_number_comparator(value)),
|
||||
(matchable, Number(value)) => compare_matchable(matchable, exec_ctx, make_number_comparator(value)),
|
||||
|
||||
(Variable(left_name), Variable(right_name)) => {
|
||||
(Variable(left_variable), Variable(right_variable)) => {
|
||||
let left_name = get_variable_name(left_variable);
|
||||
let left_jvaluable = resolve_to_jvaluable(left_name, exec_ctx)?;
|
||||
let left_value = left_jvaluable.as_jvalue();
|
||||
|
||||
let right_name = get_variable_name(right_variable);
|
||||
let right_jvaluable = resolve_to_jvaluable(right_name, exec_ctx)?;
|
||||
let right_value = right_jvaluable.as_jvalue();
|
||||
|
||||
@ -67,10 +70,12 @@ pub(crate) fn are_matchable_eq<'ctx>(
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let left_jvaluable = resolve_to_jvaluable(lv, exec_ctx)?;
|
||||
let left_name = get_variable_name(lv);
|
||||
let left_jvaluable = resolve_to_jvaluable(left_name, exec_ctx)?;
|
||||
let left_value = left_jvaluable.apply_json_path(lp)?;
|
||||
|
||||
let right_jvaluable = resolve_to_jvaluable(rv, exec_ctx)?;
|
||||
let right_name = get_variable_name(rv);
|
||||
let right_jvaluable = resolve_to_jvaluable(right_name, exec_ctx)?;
|
||||
let right_value = right_jvaluable.apply_json_path(rp)?;
|
||||
|
||||
Ok(left_value == right_value)
|
||||
@ -102,7 +107,8 @@ fn compare_matchable<'ctx>(
|
||||
let jvalue = (*bool).into();
|
||||
Ok(comparator(Cow::Owned(jvalue)))
|
||||
}
|
||||
Variable(name) => {
|
||||
Variable(variable) => {
|
||||
let name = get_variable_name(variable);
|
||||
let jvaluable = resolve_to_jvaluable(name, exec_ctx)?;
|
||||
let jvalue = jvaluable.as_jvalue();
|
||||
Ok(comparator(jvalue))
|
||||
@ -112,7 +118,8 @@ fn compare_matchable<'ctx>(
|
||||
path,
|
||||
should_flatten,
|
||||
} => {
|
||||
let jvaluable = resolve_to_jvaluable(variable, exec_ctx)?;
|
||||
let var_name = get_variable_name(variable);
|
||||
let jvaluable = resolve_to_jvaluable(var_name, exec_ctx)?;
|
||||
let jvalues = jvaluable.apply_json_path(path)?;
|
||||
|
||||
let jvalue = if *should_flatten {
|
||||
|
@ -186,7 +186,7 @@ mod tests {
|
||||
(call "set_variable" ("" "") [] Iterable)
|
||||
(fold Iterable i
|
||||
(seq
|
||||
(call "A" ("" "") [i] acc[])
|
||||
(call "A" ("" "") [i] $acc)
|
||||
(next i)
|
||||
)
|
||||
)
|
||||
@ -220,7 +220,7 @@ mod tests {
|
||||
(fold Iterable i
|
||||
(seq
|
||||
(next i)
|
||||
(call "A" ("" "") [i] acc[])
|
||||
(call "A" ("" "") [i] $acc)
|
||||
)
|
||||
)
|
||||
)"#,
|
||||
@ -257,7 +257,7 @@ mod tests {
|
||||
(seq
|
||||
(fold Iterable2 j
|
||||
(seq
|
||||
(call "A" ("" "") [i] acc[])
|
||||
(call "A" ("" "") [i] $acc)
|
||||
(next j)
|
||||
)
|
||||
)
|
||||
@ -300,7 +300,7 @@ mod tests {
|
||||
(seq
|
||||
(fold Iterable2 i
|
||||
(seq
|
||||
(call "A" ("" "") [i] acc[])
|
||||
(call "A" ("" "") [i] $acc)
|
||||
(next i)
|
||||
)
|
||||
)
|
||||
@ -329,7 +329,7 @@ mod tests {
|
||||
(call "set_variable" ("" "") [] Iterable)
|
||||
(fold Iterable i
|
||||
(seq
|
||||
(call "A" ("" "") [i] acc[])
|
||||
(call "A" ("" "") [i] $acc)
|
||||
(next i)
|
||||
)
|
||||
)
|
||||
@ -358,7 +358,7 @@ mod tests {
|
||||
(call "unknown_peer" ("" "") [] lazy_def_variable)
|
||||
(fold iterable i
|
||||
(seq
|
||||
(call "A" ("" "") [lazy_def_variable.$.hash!] acc[])
|
||||
(call "A" ("" "") [lazy_def_variable.$.hash!] $acc)
|
||||
(next i)
|
||||
)
|
||||
)
|
||||
@ -390,7 +390,7 @@ mod tests {
|
||||
(call "set_variable" ("" "") [] iterable)
|
||||
(fold iterable.$.array! i
|
||||
(seq
|
||||
(call "A" ("" "") [i] acc[])
|
||||
(call "A" ("" "") [i] $acc)
|
||||
(next i)
|
||||
)
|
||||
)
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
use super::*;
|
||||
use crate::exec_err;
|
||||
use crate::execution::utils::get_variable_name;
|
||||
use crate::JValue;
|
||||
use crate::ResolvedTriplet;
|
||||
use crate::SecurityTetraplet;
|
||||
@ -36,12 +37,18 @@ pub(super) fn construct_iterable_value<'ctx>(
|
||||
exec_ctx: &ExecutionCtx<'ctx>,
|
||||
) -> ExecutionResult<Option<IterableValue>> {
|
||||
match ast_iterable {
|
||||
ast::IterableValue::Variable(name) => handle_instruction_variable(exec_ctx, name),
|
||||
ast::IterableValue::Variable(variable) => {
|
||||
let name = get_variable_name(variable);
|
||||
handle_instruction_variable(exec_ctx, name)
|
||||
}
|
||||
ast::IterableValue::JsonPath {
|
||||
variable,
|
||||
path,
|
||||
should_flatten,
|
||||
} => handle_instruction_json_path(exec_ctx, variable, path, *should_flatten),
|
||||
} => {
|
||||
let name = get_variable_name(variable);
|
||||
handle_instruction_json_path(exec_ctx, name, path, *should_flatten)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,13 +58,13 @@ fn handle_instruction_variable<'ctx>(
|
||||
) -> ExecutionResult<Option<IterableValue>> {
|
||||
let iterable: Option<IterableValue> = match exec_ctx.data_cache.get(variable_name) {
|
||||
Some(AValue::JValueRef(call_result)) => from_call_result(call_result.clone())?,
|
||||
Some(AValue::JValueAccumulatorRef(acc)) => {
|
||||
let acc = acc.borrow();
|
||||
if acc.is_empty() {
|
||||
Some(AValue::JValueStreamRef(stream)) => {
|
||||
let stream = stream.borrow();
|
||||
if stream.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let call_results = acc.iter().cloned().collect::<Vec<_>>();
|
||||
let call_results = stream.iter().cloned().collect::<Vec<_>>();
|
||||
let foldable = IterableVecResolvedCall::init(call_results);
|
||||
Some(Box::new(foldable))
|
||||
}
|
||||
@ -103,28 +110,28 @@ fn handle_instruction_json_path<'ctx>(
|
||||
json_path: &str,
|
||||
should_flatten: bool,
|
||||
) -> ExecutionResult<Option<IterableValue>> {
|
||||
use ExecutionError::JValueAccJsonPathError;
|
||||
use ExecutionError::JValueStreamJsonPathError;
|
||||
|
||||
match exec_ctx.data_cache.get(variable_name) {
|
||||
Some(AValue::JValueRef(variable)) => {
|
||||
let jvalues = apply_json_path(&variable.result, json_path)?;
|
||||
from_jvalues(jvalues, variable.triplet.clone(), json_path, should_flatten)
|
||||
}
|
||||
Some(AValue::JValueAccumulatorRef(acc)) => {
|
||||
let acc = acc.borrow();
|
||||
if acc.is_empty() {
|
||||
Some(AValue::JValueStreamRef(stream)) => {
|
||||
let stream = stream.borrow();
|
||||
if stream.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let acc_iter = acc.iter().map(|v| v.result.deref());
|
||||
let acc_iter = stream.iter().map(|v| v.result.deref());
|
||||
let (jvalues, tetraplet_indices) = select_with_iter(acc_iter, &json_path)
|
||||
.map_err(|e| JValueAccJsonPathError(acc.clone(), json_path.to_string(), e))?;
|
||||
.map_err(|e| JValueStreamJsonPathError(stream.clone(), json_path.to_string(), e))?;
|
||||
|
||||
let jvalues = construct_iterable_jvalues(jvalues, should_flatten)?;
|
||||
let tetraplets = tetraplet_indices
|
||||
.into_iter()
|
||||
.map(|id| SecurityTetraplet {
|
||||
triplet: acc[id].triplet.clone(),
|
||||
triplet: stream[id].triplet.clone(),
|
||||
json_path: json_path.to_string(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -196,8 +196,8 @@ fn is_joinable_error_type(exec_error: &ExecutionError) -> bool {
|
||||
log_join!(" waiting for an argument with path '{}' on jvalue '{:?}'", json_path, value);
|
||||
true
|
||||
}
|
||||
JValueAccJsonPathError(acc, json_path, _) => {
|
||||
log_join!(" waiting for an argument with path '{}' on accumulator '{:?}'", json_path, acc);
|
||||
JValueStreamJsonPathError(stream, json_path, _) => {
|
||||
log_join!(" waiting for an argument with path '{}' on stream '{:?}'", json_path, stream);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
|
@ -21,7 +21,7 @@ use crate::foldable_prev;
|
||||
use crate::JValue;
|
||||
use crate::SecurityTetraplet;
|
||||
|
||||
/// Used for iterating over a result of applied to an accumulator json path.
|
||||
/// Used for iterating over a result of applied to an stream json path.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub(crate) struct IterableVecJsonPathResult {
|
||||
pub(crate) jvalues: Vec<JValue>,
|
||||
|
@ -21,7 +21,7 @@ use crate::foldable_next;
|
||||
use crate::foldable_prev;
|
||||
use crate::SecurityTetraplet;
|
||||
|
||||
/// Used for iterating over accumulator with JValues.
|
||||
/// Used for iterating over stream with JValues.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub(crate) struct IterableVecResolvedCall {
|
||||
pub(crate) call_results: Vec<ResolvedCallResult>,
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::ExecutionError::JValueAccJsonPathError;
|
||||
use super::ExecutionError::JValueStreamJsonPathError;
|
||||
use super::ExecutionResult;
|
||||
use super::JValuable;
|
||||
use crate::contexts::execution::ResolvedCallResult;
|
||||
@ -29,8 +29,9 @@ use std::ops::Deref;
|
||||
impl JValuable for std::cell::Ref<'_, Vec<ResolvedCallResult>> {
|
||||
fn apply_json_path(&self, json_path: &str) -> ExecutionResult<Vec<&JValue>> {
|
||||
let acc_iter = self.iter().map(|r| r.result.deref());
|
||||
let (selected_values, _) = select_with_iter(acc_iter, json_path)
|
||||
.map_err(|e| JValueAccJsonPathError(self.iter().cloned().collect::<Vec<_>>(), json_path.to_string(), e))?;
|
||||
let (selected_values, _) = select_with_iter(acc_iter, json_path).map_err(|e| {
|
||||
JValueStreamJsonPathError(self.iter().cloned().collect::<Vec<_>>(), json_path.to_string(), e)
|
||||
})?;
|
||||
|
||||
Ok(selected_values)
|
||||
}
|
||||
@ -41,8 +42,9 @@ impl JValuable for std::cell::Ref<'_, Vec<ResolvedCallResult>> {
|
||||
) -> ExecutionResult<(Vec<&JValue>, Vec<SecurityTetraplet>)> {
|
||||
let acc_iter = self.iter().map(|r| r.result.deref());
|
||||
|
||||
let (selected_values, tetraplet_indices) = select_with_iter(acc_iter, json_path)
|
||||
.map_err(|e| JValueAccJsonPathError(self.iter().cloned().collect::<Vec<_>>(), json_path.to_string(), e))?;
|
||||
let (selected_values, tetraplet_indices) = select_with_iter(acc_iter, json_path).map_err(|e| {
|
||||
JValueStreamJsonPathError(self.iter().cloned().collect::<Vec<_>>(), json_path.to_string(), e)
|
||||
})?;
|
||||
|
||||
let tetraplets = tetraplet_indices
|
||||
.into_iter()
|
||||
|
@ -52,9 +52,9 @@ pub(crate) enum ExecutionError {
|
||||
#[error("variable with path '{1}' not found in '{0}' with an error: '{2}'")]
|
||||
JValueJsonPathError(JValue, String, JsonPathError),
|
||||
|
||||
/// An error occurred while trying to apply json path to this accumulator with JValue's.
|
||||
/// An error occurred while trying to apply json path to this stream with JValue's.
|
||||
#[error("variable with path '{1}' not found in '{0:?}' with error: '{2}'")]
|
||||
JValueAccJsonPathError(Vec<ResolvedCallResult>, String, JsonPathError),
|
||||
JValueStreamJsonPathError(Vec<ResolvedCallResult>, String, JsonPathError),
|
||||
|
||||
/// Provided JValue has incompatible with target type.
|
||||
#[error("expected JValue type '{1}', but got '{0}' JValue")]
|
||||
@ -108,7 +108,7 @@ impl ExecutionError {
|
||||
VariableNotFound(_) => 4,
|
||||
MultipleVariablesFound(_) => 5,
|
||||
JValueJsonPathError(..) => 6,
|
||||
JValueAccJsonPathError(..) => 7,
|
||||
JValueStreamJsonPathError(..) => 7,
|
||||
IncompatibleJValueType(..) => 8,
|
||||
IncompatibleAValueType(..) => 9,
|
||||
MultipleValuesInJsonPath(_) => 10,
|
||||
|
@ -26,6 +26,7 @@ pub(super) use errors::ExecutionError;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub(self) type ExecutionResult<T> = std::result::Result<T, Rc<ExecutionError>>;
|
||||
pub(self) use air_parser::ast::Variable;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! exec_err {
|
||||
|
@ -16,5 +16,6 @@
|
||||
|
||||
mod resolve;
|
||||
|
||||
pub(crate) use resolve::get_variable_name;
|
||||
pub(crate) use resolve::resolve_to_args;
|
||||
pub(crate) use resolve::resolve_to_jvaluable;
|
||||
|
@ -35,12 +35,18 @@ pub(crate) fn resolve_to_args<'i>(
|
||||
CallInstrArgValue::Literal(value) => prepare_consts(value.to_string(), ctx),
|
||||
CallInstrArgValue::Boolean(value) => prepare_consts(*value, ctx),
|
||||
CallInstrArgValue::Number(value) => prepare_consts(value, ctx),
|
||||
CallInstrArgValue::Variable(name) => prepare_variable(name, ctx),
|
||||
CallInstrArgValue::Variable(variable) => {
|
||||
let name = get_variable_name(variable);
|
||||
prepare_variable(name, ctx)
|
||||
}
|
||||
CallInstrArgValue::JsonPath {
|
||||
variable,
|
||||
path,
|
||||
should_flatten,
|
||||
} => prepare_json_path(variable, path, *should_flatten, ctx),
|
||||
} => {
|
||||
let name = get_variable_name(variable);
|
||||
prepare_json_path(name, path, *should_flatten, ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,10 +127,19 @@ pub(crate) fn resolve_to_jvaluable<'name, 'i, 'ctx>(
|
||||
|
||||
match value {
|
||||
AValue::JValueRef(value) => Ok(Box::new(value.clone())),
|
||||
AValue::JValueAccumulatorRef(acc) => Ok(Box::new(acc.borrow())),
|
||||
AValue::JValueStreamRef(stream) => Ok(Box::new(stream.borrow())),
|
||||
AValue::JValueFoldCursor(fold_state) => {
|
||||
let peeked_value = fold_state.iterable.peek().unwrap();
|
||||
Ok(Box::new(peeked_value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use air_parser::ast::Variable;
|
||||
|
||||
pub(crate) fn get_variable_name<'a>(variable: &'a Variable<'_>) -> &'a str {
|
||||
match variable {
|
||||
Variable::Scalar(name) => name,
|
||||
Variable::Stream(name) => name,
|
||||
}
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ fn executed_trace_par_seq_fold_call() {
|
||||
(call "some_peer_id_1" ("local_service_id" "local_fn_name") [] IterableResultPeer1)
|
||||
(fold IterableResultPeer1 i
|
||||
(par
|
||||
(call "some_peer_id_2" ("local_service_id" "local_fn_name") [i] acc[])
|
||||
(call "some_peer_id_2" ("local_service_id" "local_fn_name") [i] $acc)
|
||||
(next i)
|
||||
)
|
||||
)
|
||||
@ -330,7 +330,7 @@ fn executed_trace_par_seq_fold_in_cycle_call() {
|
||||
(call "some_peer_id_1" ("local_service_id" "local_fn_name") [] IterableResultPeer1)
|
||||
(fold IterableResultPeer1 i
|
||||
(par
|
||||
(call "some_peer_id_2" ("local_service_id" "local_fn_name") [i] acc[])
|
||||
(call "some_peer_id_2" ("local_service_id" "local_fn_name") [i] $acc)
|
||||
(next i)
|
||||
)
|
||||
)
|
||||
|
@ -51,19 +51,19 @@ fn data_merge() {
|
||||
(seq
|
||||
(fold neighborhood i
|
||||
(par
|
||||
(call i ("add_provider" "") [] void[])
|
||||
(call i ("add_provider" "") [] $void)
|
||||
(next i)
|
||||
)
|
||||
)
|
||||
(fold neighborhood i
|
||||
(par
|
||||
(call i ("get_providers" "") [] providers[])
|
||||
(call i ("get_providers" "") [] $providers)
|
||||
(next i)
|
||||
)
|
||||
)
|
||||
)
|
||||
(seq
|
||||
(call "A" ("identity" "") [] void[])
|
||||
(call "A" ("identity" "") [] $void)
|
||||
(call "B" ("" "") [] none)
|
||||
)
|
||||
)
|
||||
@ -189,16 +189,16 @@ fn acc_merge() {
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq
|
||||
(call "A" ("add_provider" "") [] void[])
|
||||
(call "A" ("add_provider" "") [] $void)
|
||||
(seq
|
||||
(call "A" ("add_provider" "") [] void[])
|
||||
(call "A" ("add_provider" "") [] $void)
|
||||
(seq
|
||||
(call "A" ("get_providers" "") [] providers[])
|
||||
(call "A" ("get_providers" "") [] $providers)
|
||||
(seq
|
||||
(call "A" ("get_providers" "") [] providers[])
|
||||
(call "A" ("get_providers" "") [] $providers)
|
||||
(seq
|
||||
(call "B" ("" "2") [providers] void[])
|
||||
(call "B" ("" "3") [void] void[])
|
||||
(call "B" ("" "2") [$providers] $void)
|
||||
(call "B" ("" "3") [$void] $void)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -130,12 +130,12 @@ fn flattening_streams() {
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call "{0}" ("" "") [] stream[])
|
||||
(call "{0}" ("" "") [] stream[])
|
||||
(call "{0}" ("" "") [] $stream)
|
||||
(call "{0}" ("" "") [] $stream)
|
||||
)
|
||||
(call "{0}" ("" "") [] stream[])
|
||||
(call "{0}" ("" "") [] $stream)
|
||||
)
|
||||
(fold stream.$.[0,1,2] v
|
||||
(fold $stream.$.[0,1,2] v
|
||||
(seq
|
||||
(call v.$.peer_id! (v.$.service_id! v.$.function_name!) [v.$.args[0]! v.$.args[1]!])
|
||||
(next v)
|
||||
@ -180,12 +180,12 @@ fn test_handling_non_flattening_values() {
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call "{0}" ("" "") [] stream[])
|
||||
(call "{0}" ("" "") [] stream[])
|
||||
(call "{0}" ("" "") [] $stream)
|
||||
(call "{0}" ("" "") [] $stream)
|
||||
)
|
||||
(call "{0}" ("" "") [] stream[])
|
||||
(call "{0}" ("" "") [] $stream)
|
||||
)
|
||||
(fold stream.$.[0,1,2]! v
|
||||
(fold $stream.$.[0,1,2]! v
|
||||
(seq
|
||||
(call v.$.peer_id! (v.$.service_id! v.$.function_name!) [v.$.args[0]! v.$.args[1]!])
|
||||
(next v)
|
||||
|
@ -49,16 +49,16 @@ fn join_chat() {
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq
|
||||
(call "Relay1" ("identity" "") [] void1[])
|
||||
(call "Relay1" ("identity" "") [] $void1)
|
||||
(seq
|
||||
(call "Remote" ("552196ea-b9b2-4761-98d4-8e7dba77fac4" "add") [] void2[])
|
||||
(call "Remote" ("552196ea-b9b2-4761-98d4-8e7dba77fac4" "add") [] $void2)
|
||||
(seq
|
||||
(call "Remote" ("920e3ba3-cbdf-4ae3-8972-0fa2f31fffd9" "get_users") [] members)
|
||||
(fold members m
|
||||
(par
|
||||
(seq
|
||||
(call m.$.[1]! ("identity" "") [] void[])
|
||||
(call m.$.[0]! ("fgemb3" "add") [] void3[])
|
||||
(call m.$.[1]! ("identity" "") [] $void)
|
||||
(call m.$.[0]! ("fgemb3" "add") [] $void3)
|
||||
)
|
||||
(next m)
|
||||
)
|
||||
@ -210,14 +210,14 @@ fn join() {
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq
|
||||
(call "Relay1" ("identity" "") [] void1[])
|
||||
(call "Relay1" ("identity" "") [] $void1)
|
||||
(seq
|
||||
(call "Remote" ("920e3ba3-cbdf-4ae3-8972-0fa2f31fffd9" "get_users") [] members)
|
||||
(fold members m
|
||||
(par
|
||||
(seq
|
||||
(call "Relay1" ("identity" "") [] void[])
|
||||
(call "A" ("fgemb3" "add") [m] void3[])
|
||||
(call "Relay1" ("identity" "") [] $void)
|
||||
(call "A" ("fgemb3" "add") [m] $void3)
|
||||
)
|
||||
(next m)
|
||||
)
|
||||
|
@ -18,7 +18,7 @@
|
||||
)
|
||||
)
|
||||
(seq
|
||||
(call "{1}" ("op" "identity") ["XOR: create_greeting_service failed"] fail[])
|
||||
(call "{1}" ("op" "identity") ["XOR: create_greeting_service failed"] $fail)
|
||||
(call "{2}" ("return" "") [%last_error%])
|
||||
)
|
||||
)
|
||||
|
@ -8,15 +8,15 @@
|
||||
(seq
|
||||
(fold neighs_top n
|
||||
(seq
|
||||
(call n ("dht" "neighborhood") [n] neighs_inner[])
|
||||
(call n ("dht" "neighborhood") [n] $neighs_inner)
|
||||
(next n)
|
||||
)
|
||||
)
|
||||
(fold neighs_inner ns
|
||||
(fold $neighs_inner ns
|
||||
(seq
|
||||
(fold ns n
|
||||
(seq
|
||||
(call n ("op" "identify") [] services[])
|
||||
(call n ("op" "identify") [] $services)
|
||||
(next n)
|
||||
)
|
||||
)
|
||||
|
@ -81,7 +81,7 @@ fn simple_fold() {
|
||||
(call "{}" ("{}" "{}") [] IterableResultPeer1)
|
||||
(fold IterableResultPeer1 i
|
||||
(par
|
||||
(call i ("local_service_id" "local_fn_name") [i "some_text_literal"] acc[])
|
||||
(call i ("local_service_id" "local_fn_name") [i "some_text_literal"] $acc)
|
||||
(next i)
|
||||
)
|
||||
)
|
||||
@ -155,7 +155,7 @@ fn fold_json_path() {
|
||||
(call "{}" ("{}" "{}") [] IterableResultPeer1)
|
||||
(fold IterableResultPeer1.$.arg i
|
||||
(par
|
||||
(call "{}" ("local_service_id" "local_fn_name") [i "some_text_literal"] acc[])
|
||||
(call "{}" ("local_service_id" "local_fn_name") [i "some_text_literal"] $acc)
|
||||
(next i)
|
||||
)
|
||||
)
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "aquamarine"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user