mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-04 15:20:16 +00:00
LALRPOP parser for AIR (#13)
This commit is contained in:
parent
12398697f2
commit
1786ab8f4b
386
Cargo.lock
generated
386
Cargo.lock
generated
@ -9,6 +9,18 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "air-parser"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"codespan",
|
||||
"codespan-reporting",
|
||||
"fstrings",
|
||||
"lalrpop",
|
||||
"lalrpop-util",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
@ -20,9 +32,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.33"
|
||||
version = "1.0.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c"
|
||||
checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7"
|
||||
|
||||
[[package]]
|
||||
name = "aqua-test-module"
|
||||
@ -80,6 +92,15 @@ version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "ascii-canvas"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff8eb72df928aafb99fe5d37b383f2fe25bd2a765e3e5f7c365916b6f2463a29"
|
||||
dependencies = [
|
||||
"term",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
@ -97,6 +118,12 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.1"
|
||||
@ -107,12 +134,38 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "0.3.7"
|
||||
@ -128,6 +181,27 @@ dependencies = [
|
||||
"digest 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"byte-tools",
|
||||
"byteorder",
|
||||
"generic-array 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
|
||||
dependencies = [
|
||||
"byte-tools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "boolinator"
|
||||
version = "2.4.0"
|
||||
@ -152,6 +226,12 @@ version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.4"
|
||||
@ -212,10 +292,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "475bd7aa7680b4ed8f6bb59745e882bcbaeb39326532bb79ffb1716480d9a274"
|
||||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.2"
|
||||
name = "codespan"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce90df4c658c62f12d78f7508cf92f9173e5184a539c10bfe54a3107b3ffd0f2"
|
||||
checksum = "8ebaf6bb6a863ad6aa3a18729e9710c53d75df03306714d9cc1f7357a00cd789"
|
||||
dependencies = [
|
||||
"codespan-reporting",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e0762455306b1ed42bc651ef6a2197aabda5e1d4a43c34d5eab5c1a3634e81d"
|
||||
dependencies = [
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
@ -326,7 +425,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
"crossbeam-utils 0.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -337,7 +436,7 @@ checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
"crossbeam-utils 0.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -348,12 +447,23 @@ checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"const_fn",
|
||||
"crossbeam-utils",
|
||||
"crossbeam-utils 0.8.0",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if 0.1.10",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.0"
|
||||
@ -408,6 +518,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
|
||||
|
||||
[[package]]
|
||||
name = "difference"
|
||||
version = "2.0.0"
|
||||
@ -432,12 +548,44 @@ dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "docopt"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"serde",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.7.1"
|
||||
@ -481,6 +629,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
||||
[[package]]
|
||||
name = "fce"
|
||||
version = "0.1.9"
|
||||
@ -523,6 +677,12 @@ dependencies = [
|
||||
"wasmer-runtime-core-fl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
||||
|
||||
[[package]]
|
||||
name = "fluence"
|
||||
version = "0.2.8"
|
||||
@ -618,6 +778,28 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fstrings"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7845a0f15da505ac36baad0486612dab57f8b8d34e19c5470a265bbcdd572ae6"
|
||||
dependencies = [
|
||||
"fstrings-proc-macro",
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fstrings-proc-macro"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63b58c0e7581dc33478a32299182cbe5ae3b8c028be26728a47fb0a113c92d9d"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.55"
|
||||
@ -650,7 +832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check 0.9.2",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -806,6 +988,40 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop"
|
||||
version = "0.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60fb56191fb8ed5311597e5750debe6779c9fdb487dbaa5ff302592897d7a2c8"
|
||||
dependencies = [
|
||||
"ascii-canvas",
|
||||
"atty",
|
||||
"bit-set",
|
||||
"diff",
|
||||
"docopt",
|
||||
"ena",
|
||||
"itertools",
|
||||
"lalrpop-util",
|
||||
"petgraph",
|
||||
"regex",
|
||||
"regex-syntax",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"sha2",
|
||||
"string_cache",
|
||||
"term",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop-util"
|
||||
version = "0.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6771161eff561647fad8bb7e745e002c304864fb8f436b52b30acda51fca4408"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
@ -901,6 +1117,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "new_debug_unreachable"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.15.0"
|
||||
@ -914,16 +1136,6 @@ dependencies = [
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "4.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"version_check 0.1.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "5.1.2"
|
||||
@ -932,7 +1144,7 @@ checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
|
||||
dependencies = [
|
||||
"lexical-core",
|
||||
"memchr",
|
||||
"version_check 0.9.2",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -966,6 +1178,12 @@ version = "11.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a170cebd8021a008ea92e4db85a72f80b35df514ec664b296fdcbb654eac0b2c"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||
|
||||
[[package]]
|
||||
name = "output_vt100"
|
||||
version = "0.1.2"
|
||||
@ -1015,6 +1233,25 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.2.15"
|
||||
@ -1029,9 +1266,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.9"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
|
||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
|
||||
[[package]]
|
||||
name = "precomputed-hash"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
@ -1045,6 +1288,12 @@ dependencies = [
|
||||
"output_vt100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
@ -1152,7 +1401,7 @@ checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"crossbeam-utils 0.8.0",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
]
|
||||
@ -1164,10 +1413,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.1"
|
||||
name = "redox_users"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8963b85b8ce3074fecffde43b4b0dded83ce2f367dc8d363afc56679f3ee820b"
|
||||
checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
"rust-argon2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@ -1186,9 +1446,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.20"
|
||||
version = "0.6.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c"
|
||||
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
|
||||
|
||||
[[package]]
|
||||
name = "rust-argon2"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"blake2b_simd",
|
||||
"constant_time_eq",
|
||||
"crossbeam-utils 0.7.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
@ -1303,15 +1575,23 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_sexpr"
|
||||
version = "0.1.0"
|
||||
name = "sha2"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5318bfeed779c64075ce317c81462ed54dc00021be1c6b34957d798e11a68bdb"
|
||||
checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
|
||||
dependencies = [
|
||||
"nom 4.2.3",
|
||||
"serde",
|
||||
"block-buffer",
|
||||
"digest 0.8.1",
|
||||
"fake-simd",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.4.2"
|
||||
@ -1328,6 +1608,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
name = "stepper-lib"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"air-parser",
|
||||
"aqua-test-utils",
|
||||
"aquamarine-vm",
|
||||
"boolinator",
|
||||
@ -1342,10 +1623,28 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_sexpr",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2940c75beb4e3bf3a494cef919a747a2cb81e52571e212bfbd185074add7208a"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"new_debug_unreachable",
|
||||
"phf_shared",
|
||||
"precomputed-hash",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.3.0"
|
||||
@ -1369,6 +1668,17 @@ version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d"
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"dirs",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.0"
|
||||
@ -1503,12 +1813,6 @@ dependencies = [
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.2"
|
||||
@ -1683,7 +1987,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1de496e366bd1c198942248fc1de4b94e4647b263dd60099d5f7776f0d621656"
|
||||
dependencies = [
|
||||
"log",
|
||||
"nom 5.1.2",
|
||||
"nom",
|
||||
"safe-transmute",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -1,5 +1,6 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"crates/air-parser",
|
||||
"crates/test-module",
|
||||
"crates/test-utils",
|
||||
"stepper",
|
||||
|
Binary file not shown.
17
crates/air-parser/Cargo.toml
Normal file
17
crates/air-parser/Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "air-parser"
|
||||
version = "0.1.0"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
||||
[build-dependencies]
|
||||
lalrpop = { version = "0.19.1", features = ["lexer"] }
|
||||
|
||||
[dependencies]
|
||||
lalrpop-util = { version = "0.19.1", features = ["lexer"] }
|
||||
regex = "1.4.1"
|
||||
codespan = "0.9.5"
|
||||
codespan-reporting = "0.9.5"
|
||||
|
||||
[dev-dependencies]
|
||||
fstrings = "0.2.3"
|
24
crates/air-parser/build.rs
Normal file
24
crates/air-parser/build.rs
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
extern crate lalrpop;
|
||||
|
||||
fn main() {
|
||||
lalrpop::Configuration::new()
|
||||
.generate_in_source_tree()
|
||||
.process()
|
||||
.unwrap();
|
||||
}
|
95
crates/air-parser/src/ast.rs
Normal file
95
crates/air-parser/src/ast.rs
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Instruction<'i> {
|
||||
Null(Null),
|
||||
Call(Call<'i>),
|
||||
Seq(Seq<'i>),
|
||||
Par(Par<'i>),
|
||||
Xor(Xor<'i>),
|
||||
Fold(Fold<'i>),
|
||||
Next(Next<'i>),
|
||||
Error,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum PeerPart<'i> {
|
||||
PeerPk(Value<'i>),
|
||||
PeerPkWithServiceId(Value<'i>, Value<'i>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum FunctionPart<'i> {
|
||||
FuncName(Value<'i>),
|
||||
ServiceIdWithFuncName(Value<'i>, Value<'i>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Call<'i> {
|
||||
pub peer_part: PeerPart<'i>,
|
||||
pub function_part: FunctionPart<'i>,
|
||||
pub args: Vec<Value<'i>>,
|
||||
pub output: CallOutput<'i>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum Value<'i> {
|
||||
Variable(&'i str),
|
||||
Literal(&'i str),
|
||||
JsonPath { variable: &'i str, path: &'i str },
|
||||
CurrentPeerId,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum CallOutput<'i> {
|
||||
Scalar(&'i str),
|
||||
Accumulator(&'i str),
|
||||
}
|
||||
|
||||
impl<'i> CallOutput<'i> {
|
||||
pub fn name(&self) -> &'i str {
|
||||
use CallOutput::*;
|
||||
|
||||
match self {
|
||||
Scalar(name) | Accumulator(name) => name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Seq<'i>(pub Box<Instruction<'i>>, pub Box<Instruction<'i>>);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Par<'i>(pub Box<Instruction<'i>>, pub Box<Instruction<'i>>);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Xor<'i>(pub Box<Instruction<'i>>, pub Box<Instruction<'i>>);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Fold<'i> {
|
||||
pub iterable: &'i str,
|
||||
pub iterator: &'i str,
|
||||
pub instruction: Rc<Instruction<'i>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Next<'i>(pub &'i str);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Null;
|
90
crates/air-parser/src/lalrpop/aqua.lalrpop
Normal file
90
crates/air-parser/src/lalrpop/aqua.lalrpop
Normal file
@ -0,0 +1,90 @@
|
||||
use crate::ast::*;
|
||||
use crate::lalrpop::parser::InstructionError;
|
||||
|
||||
use lalrpop_util::ErrorRecovery;
|
||||
use std::rc::Rc;
|
||||
|
||||
grammar<'err>(errors: &'err mut Vec<ErrorRecovery<usize, Token<'input>, InstructionError>>);
|
||||
|
||||
extern {
|
||||
type Error = InstructionError;
|
||||
}
|
||||
|
||||
pub Instr: Box<Instruction<'input>> = {
|
||||
"(" "seq" <l:Instr> <r:Instr> ")" => Box::new(Instruction::Seq(Seq(l, r))),
|
||||
"(" "par" <l:Instr> <r:Instr> ")" => Box::new(Instruction::Par(Par(l, r))),
|
||||
"(" "xor" <l:Instr> <r:Instr> ")" => Box::new(Instruction::Xor(Xor(l, r))),
|
||||
|
||||
"(" "call" <peer:PeerPart> <f:FPart> <args:Args> <output:Output> ")" =>
|
||||
Box::new(Instruction::Call(Call{peer, f, args, output})),
|
||||
|
||||
"(" "fold" <iterable:Alphanumeric> <iterator:Alphanumeric> <i:Instr> ")" => {
|
||||
let instruction = Rc::new(*i);
|
||||
Box::new(Instruction::Fold(Fold{ iterable, iterator, instruction }))
|
||||
},
|
||||
|
||||
"(" "next" <i:Alphanumeric> ")" => Box::new(Instruction::Next(Next(i))),
|
||||
"(" "null" ")" => Box::new(Instruction::Null(Null)),
|
||||
! => { errors.push(<>); Box::new(Instruction::Error) },
|
||||
}
|
||||
|
||||
Args: Vec<Value<'input>> = {
|
||||
"[" <args:(<Arg>)*> "]" => args
|
||||
}
|
||||
|
||||
|
||||
FPart: FunctionPart<'input> = {
|
||||
<f:Function> => FunctionPart::FuncName(f),
|
||||
"(" <sid:ServiceId> <f:Function> ")" => FunctionPart::ServiceIdWithFuncName(sid, f),
|
||||
}
|
||||
|
||||
|
||||
PeerPart: PeerPart<'input> = {
|
||||
<pid:PeerId> => PeerPart::PeerPk(pid),
|
||||
"(" <pid:PeerId> <sid:ServiceId> ")" => PeerPart::PeerPkWithServiceId(pid, sid),
|
||||
}
|
||||
|
||||
// TODO: make output one of _ () "" and absence
|
||||
Output: CallOutput<'input> = {
|
||||
<o:Alphanumeric> => CallOutput::Scalar(o),
|
||||
<o:ACCUMULATOR> => CallOutput::Accumulator(&o[..o.len()-2]),
|
||||
};
|
||||
|
||||
Function = Value;
|
||||
PeerId = Value;
|
||||
ServiceId = Value;
|
||||
Arg = Value;
|
||||
|
||||
Value: Value<'input> = {
|
||||
"\"" "\"" => Value::Literal(""), // TODO: signal absence somehow?
|
||||
"\"" <v: Alphanumeric> "\"" => Value::Literal(v),
|
||||
<v:Alphanumeric> => Value::Variable(v),
|
||||
<v:JSON_PATH> => {
|
||||
let mut path = v.splitn(2, ".");
|
||||
let variable = path.next().expect("must contain dot");
|
||||
let path = path.next().expect("contain component after dot");
|
||||
Value::JsonPath { variable, path }
|
||||
},
|
||||
CURRENT_PEER_ID => Value::CurrentPeerId,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Alphanumeric = ALPHANUMERIC;
|
||||
|
||||
match {
|
||||
r"[\w_-]+" => ALPHANUMERIC,
|
||||
r"[\w_-]+\[\]" => ACCUMULATOR,
|
||||
r"[\w_-]+\.\$[^ ]+" => JSON_PATH,
|
||||
"%current_peer_id%" => CURRENT_PEER_ID,
|
||||
"seq",
|
||||
"call",
|
||||
"null",
|
||||
"par",
|
||||
"xor",
|
||||
"fold",
|
||||
"next",
|
||||
} else {
|
||||
_
|
||||
}
|
||||
|
2132
crates/air-parser/src/lalrpop/aqua.rs
Normal file
2132
crates/air-parser/src/lalrpop/aqua.rs
Normal file
File diff suppressed because one or more lines are too long
119
crates/air-parser/src/lalrpop/parser.rs
Normal file
119
crates/air-parser/src/lalrpop/parser.rs
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::aqua;
|
||||
use crate::ast::Instruction;
|
||||
use crate::lalrpop::aqua::Token;
|
||||
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
use codespan_reporting::files::SimpleFiles;
|
||||
use codespan_reporting::term;
|
||||
use codespan_reporting::term::termcolor::{Buffer, ColorChoice, StandardStream};
|
||||
use lalrpop_util::{ErrorRecovery, ParseError};
|
||||
|
||||
use std::fmt::Formatter;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Represents custom parsing errors. Isn't used yet.
|
||||
pub enum InstructionError {
|
||||
#[allow(dead_code)]
|
||||
InvalidPeerId,
|
||||
}
|
||||
|
||||
impl std::error::Error for InstructionError {}
|
||||
impl std::fmt::Display for InstructionError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "InstructionError")
|
||||
}
|
||||
}
|
||||
|
||||
// Caching parser to cache internal regexes, which are expensive to instantiate
|
||||
// See also https://github.com/lalrpop/lalrpop/issues/269
|
||||
thread_local!(static PARSER: aqua::InstrParser = aqua::InstrParser::new());
|
||||
|
||||
/// Parse AIR `source_code` to `Box<Instruction>`
|
||||
pub fn parse(source_code: &str) -> Result<Box<Instruction>, String> {
|
||||
let mut files = SimpleFiles::new();
|
||||
let file_id = files.add("script.aqua", source_code);
|
||||
|
||||
PARSER.with(|parser| {
|
||||
let mut errors = Vec::new();
|
||||
match parser.parse(&mut errors, source_code) {
|
||||
Ok(r) if errors.is_empty() => Ok(r),
|
||||
Ok(_) => Err(report_errors(file_id, files, errors)),
|
||||
Err(err) => Err(report_errors(
|
||||
file_id,
|
||||
files,
|
||||
vec![ErrorRecovery {
|
||||
error: err,
|
||||
dropped_tokens: vec![],
|
||||
}],
|
||||
)),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn report_errors(
|
||||
file_id: usize,
|
||||
files: SimpleFiles<&str, &str>,
|
||||
errors: Vec<ErrorRecovery<usize, Token, InstructionError>>,
|
||||
) -> String {
|
||||
let labels: Vec<Label<usize>> = errors
|
||||
.into_iter()
|
||||
.map(|err| match err.error {
|
||||
ParseError::UnrecognizedToken {
|
||||
token: (start, _, end),
|
||||
expected,
|
||||
} => Label::primary(file_id, start..end)
|
||||
.with_message(format!("expected {}", pretty_expected(expected))),
|
||||
ParseError::InvalidToken { location } => {
|
||||
Label::primary(file_id, location..(location + 1)).with_message("unexpected token")
|
||||
}
|
||||
ParseError::ExtraToken {
|
||||
token: (start, _, end),
|
||||
} => Label::primary(file_id, start..end).with_message("extra token"),
|
||||
ParseError::UnrecognizedEOF { location, expected } => {
|
||||
Label::primary(file_id, location..(location + 1))
|
||||
.with_message(format!("expected {}", pretty_expected(expected)))
|
||||
}
|
||||
// TODO: capture start & end in user error; maybe return it as a separate Diagnostic::error?
|
||||
ParseError::User { error } => {
|
||||
Label::primary(file_id, 0..0).with_message(error.to_string())
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let diagnostic = Diagnostic::error().with_labels(labels);
|
||||
let config = codespan_reporting::term::Config::default();
|
||||
|
||||
// Write to stderr
|
||||
let writer = StandardStream::stderr(ColorChoice::Auto);
|
||||
term::emit(&mut writer.lock(), &config, &files, &diagnostic).expect("term emit to stderr");
|
||||
|
||||
// Return as a string
|
||||
let mut buffer = Buffer::no_color();
|
||||
term::emit(&mut buffer, &config, &files, &diagnostic).expect("term emit to buffer");
|
||||
String::from_utf8_lossy(buffer.as_slice())
|
||||
.as_ref()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn pretty_expected(expected: Vec<String>) -> String {
|
||||
if expected.is_empty() {
|
||||
"<nothing>".to_string()
|
||||
} else {
|
||||
expected.join(" or ")
|
||||
}
|
||||
}
|
364
crates/air-parser/src/lalrpop/tests.rs
Normal file
364
crates/air-parser/src/lalrpop/tests.rs
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::ast::*;
|
||||
use CallOutput::*;
|
||||
use FunctionPart::*;
|
||||
use PeerPart::*;
|
||||
use Value::*;
|
||||
|
||||
use fstrings::f;
|
||||
|
||||
fn parse(source_code: &str) -> Instruction {
|
||||
*super::parse(source_code).expect("parsing failed")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_seq() {
|
||||
let source_code = r#"
|
||||
(seq
|
||||
(call peerid function [] void)
|
||||
(call "id" "f" ["hello" name] void[])
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = seq(
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Variable("peerid")),
|
||||
function_part: FuncName(Variable("function")),
|
||||
args: vec![],
|
||||
output: Scalar("void"),
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Literal("id")),
|
||||
function_part: FuncName(Literal("f")),
|
||||
args: vec![Literal("hello"), Variable("name")],
|
||||
output: Accumulator("void"),
|
||||
}),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_seq_seq() {
|
||||
let source_code = r#"
|
||||
(seq
|
||||
(seq
|
||||
(call peerid function [] void)
|
||||
(call (peerid serviceA) ("serviceB" function) [] void)
|
||||
)
|
||||
(call "id" "f" ["hello" name] void[])
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = seq(
|
||||
seq(
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Variable("peerid")),
|
||||
function_part: FuncName(Variable("function")),
|
||||
args: vec![],
|
||||
output: Scalar("void"),
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPkWithServiceId(Variable("peerid"), Variable("serviceA")),
|
||||
function_part: ServiceIdWithFuncName(Literal("serviceB"), Variable("function")),
|
||||
args: vec![],
|
||||
output: Scalar("void"),
|
||||
}),
|
||||
),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Literal("id")),
|
||||
function_part: FuncName(Literal("f")),
|
||||
args: vec![Literal("hello"), Variable("name")],
|
||||
output: Accumulator("void"),
|
||||
}),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_json_path() {
|
||||
let source_code = r#"
|
||||
(call id.$.a "f" ["hello" name] void[])
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = Instruction::Call(Call {
|
||||
peer_part: PeerPk(JsonPath {
|
||||
variable: "id",
|
||||
path: "$.a",
|
||||
}),
|
||||
function_part: FuncName(Literal("f")),
|
||||
args: vec![Literal("hello"), Variable("name")],
|
||||
output: Accumulator("void"),
|
||||
});
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_json_path_complex() {
|
||||
let source_code = r#"
|
||||
(seq
|
||||
(call m.$.[1] "f" [] void)
|
||||
(call m.$.abc.cde[a][0].cde "f" [] void)
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = seq(
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(JsonPath {
|
||||
variable: "m",
|
||||
path: "$.[1]",
|
||||
}),
|
||||
function_part: FuncName(Literal("f")),
|
||||
args: vec![],
|
||||
output: Scalar("void"),
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(JsonPath {
|
||||
variable: "m",
|
||||
path: "$.abc.cde[a][0].cde",
|
||||
}),
|
||||
function_part: FuncName(Literal("f")),
|
||||
args: vec![],
|
||||
output: Scalar("void"),
|
||||
}),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_null() {
|
||||
let source_code = r#"
|
||||
(seq
|
||||
(null)
|
||||
|
||||
( null )
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(source_code);
|
||||
let expected = Instruction::Seq(Seq(Box::new(null()), Box::new(null())));
|
||||
assert_eq!(instruction, expected)
|
||||
}
|
||||
|
||||
fn source_seq_with(name: &'static str) -> String {
|
||||
f!(r#"
|
||||
(seq
|
||||
({name}
|
||||
(seq (null) (null))
|
||||
(null)
|
||||
)
|
||||
({name} (null) (seq (null) (null)) )
|
||||
)
|
||||
"#)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_seq_par_xor_seq() {
|
||||
for name in &["xor", "par", "seq"] {
|
||||
let source_code = source_seq_with(name);
|
||||
let instruction = parse(&source_code.as_ref());
|
||||
let instr = binary_instruction(*name);
|
||||
let expected = seq(instr(seqnn(), null()), instr(null(), seqnn()));
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_fold() {
|
||||
let source_code = r#"
|
||||
(fold iterable i
|
||||
(null)
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(&source_code.as_ref());
|
||||
let expected = fold("iterable", "i", null());
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
fn source_fold_with(name: &str) -> String {
|
||||
f!(r#"(fold iterable i
|
||||
({name} (null) (null))
|
||||
)"#)
|
||||
}
|
||||
#[test]
|
||||
fn parse_fold_with_xor_par_seq() {
|
||||
for name in &["xor", "par", "seq"] {
|
||||
let source_code = source_fold_with(name);
|
||||
let instruction = parse(&source_code.as_ref());
|
||||
let instr = binary_instruction(*name);
|
||||
let expected = fold("iterable", "i", instr(null(), null()));
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seq_par_call() {
|
||||
let source_code = r#"
|
||||
(seq
|
||||
(par
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_1)
|
||||
(call "remote_peer_id" ("service_id" "fn_name") [] g)
|
||||
)
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_2)
|
||||
)"#;
|
||||
let instruction = parse(&source_code.as_ref());
|
||||
let expected = seq(
|
||||
par(
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(CurrentPeerId),
|
||||
function_part: ServiceIdWithFuncName(
|
||||
Literal("local_service_id"),
|
||||
Literal("local_fn_name"),
|
||||
),
|
||||
args: vec![],
|
||||
output: Scalar("result_1"),
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Literal("remote_peer_id")),
|
||||
function_part: ServiceIdWithFuncName(Literal("service_id"), Literal("fn_name")),
|
||||
args: vec![],
|
||||
output: Scalar("g"),
|
||||
}),
|
||||
),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(CurrentPeerId),
|
||||
function_part: ServiceIdWithFuncName(
|
||||
Literal("local_service_id"),
|
||||
Literal("local_fn_name"),
|
||||
),
|
||||
args: vec![],
|
||||
output: Scalar("result_2"),
|
||||
}),
|
||||
);
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seq_with_empty_and_dash() {
|
||||
let source_code = r#"
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call "set_variables" ("" "") ["module-bytes"] module-bytes)
|
||||
(call "set_variables" ("" "") ["module_config"] module_config)
|
||||
)
|
||||
(call "set_variables" ("" "") ["blueprint"] blueprint)
|
||||
)
|
||||
(seq
|
||||
(call "A" ("add_module" "") [module-bytes module_config] module)
|
||||
(seq
|
||||
(call "A" ("add_blueprint" "") [blueprint] blueprint_id)
|
||||
(seq
|
||||
(call "A" ("create" "") [blueprint_id] service_id)
|
||||
(call "remote_peer_id" ("" "") [service_id] client_result)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
"#;
|
||||
let instruction = parse(&source_code.as_ref());
|
||||
let expected = seq(
|
||||
seq(
|
||||
seq(
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Literal("set_variables")),
|
||||
function_part: ServiceIdWithFuncName(Literal(""), Literal("")),
|
||||
args: vec![Literal("module-bytes")],
|
||||
output: Scalar("module-bytes"),
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Literal("set_variables")),
|
||||
function_part: ServiceIdWithFuncName(Literal(""), Literal("")),
|
||||
args: vec![Literal("module_config")],
|
||||
output: Scalar("module_config"),
|
||||
}),
|
||||
),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Literal("set_variables")),
|
||||
function_part: ServiceIdWithFuncName(Literal(""), Literal("")),
|
||||
args: vec![Literal("blueprint")],
|
||||
output: Scalar("blueprint"),
|
||||
}),
|
||||
),
|
||||
seq(
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Literal("A")),
|
||||
function_part: ServiceIdWithFuncName(Literal("add_module"), Literal("")),
|
||||
args: vec![Variable("module-bytes"), Variable("module_config")],
|
||||
output: Scalar("module"),
|
||||
}),
|
||||
seq(
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Literal("A")),
|
||||
function_part: ServiceIdWithFuncName(Literal("add_blueprint"), Literal("")),
|
||||
args: vec![Variable("blueprint")],
|
||||
output: Scalar("blueprint_id"),
|
||||
}),
|
||||
seq(
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Literal("A")),
|
||||
function_part: ServiceIdWithFuncName(Literal("create"), Literal("")),
|
||||
args: vec![Variable("blueprint_id")],
|
||||
output: Scalar("service_id"),
|
||||
}),
|
||||
Instruction::Call(Call {
|
||||
peer_part: PeerPk(Literal("remote_peer_id")),
|
||||
function_part: ServiceIdWithFuncName(Literal(""), Literal("")),
|
||||
args: vec![Variable("service_id")],
|
||||
output: Scalar("client_result"),
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
assert_eq!(instruction, expected);
|
||||
}
|
||||
|
||||
// Test DSL
|
||||
|
||||
fn seq<'a>(l: Instruction<'a>, r: Instruction<'a>) -> Instruction<'a> {
|
||||
Instruction::Seq(Seq(Box::new(l), Box::new(r)))
|
||||
}
|
||||
fn par<'a>(l: Instruction<'a>, r: Instruction<'a>) -> Instruction<'a> {
|
||||
Instruction::Par(Par(Box::new(l), Box::new(r)))
|
||||
}
|
||||
fn xor<'a>(l: Instruction<'a>, r: Instruction<'a>) -> Instruction<'a> {
|
||||
Instruction::Xor(Xor(Box::new(l), Box::new(r)))
|
||||
}
|
||||
fn seqnn() -> Instruction<'static> {
|
||||
seq(null(), null())
|
||||
}
|
||||
fn null() -> Instruction<'static> {
|
||||
Instruction::Null(Null)
|
||||
}
|
||||
fn fold<'a>(iterable: &'a str, iterator: &'a str, instruction: Instruction<'a>) -> Instruction<'a> {
|
||||
Instruction::Fold(Fold {
|
||||
iterable,
|
||||
iterator,
|
||||
instruction: std::rc::Rc::new(instruction),
|
||||
})
|
||||
}
|
||||
fn binary_instruction<'a, 'b>(
|
||||
name: &'a str,
|
||||
) -> impl Fn(Instruction<'b>, Instruction<'b>) -> Instruction<'b> {
|
||||
match name {
|
||||
"xor" => |l, r| xor(l, r),
|
||||
"par" => |l, r| par(l, r),
|
||||
"seq" => |l, r| seq(l, r),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
20
crates/air-parser/src/lib.rs
Normal file
20
crates/air-parser/src/lib.rs
Normal file
@ -0,0 +1,20 @@
|
||||
#![deny(unused_imports, unused_variables, dead_code)]
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate fstrings;
|
||||
|
||||
pub mod ast;
|
||||
mod lalrpop {
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
// aqua is auto-generated, so exclude it from `cargo fmt -- --check`
|
||||
#[rustfmt::skip]
|
||||
mod aqua;
|
||||
mod parser;
|
||||
|
||||
pub use parser::parse;
|
||||
}
|
||||
|
||||
pub use lalrpop::parse;
|
@ -147,7 +147,9 @@ pub fn set_variables_call_service(ret_mapping: HashMap<String, String>) -> HostE
|
||||
#[macro_export]
|
||||
macro_rules! call_vm {
|
||||
($vm:expr, $init_user_id:expr, $script:expr, $prev_data:expr, $data:expr) => {
|
||||
$vm.call_with_prev_data($init_user_id, $script, $prev_data, $data)
|
||||
.expect("call should be successful");
|
||||
match $vm.call_with_prev_data($init_user_id, $script, $prev_data, $data) {
|
||||
Ok(v) => v,
|
||||
Err(err) => panic!("VM call failed: {}", err),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -9,11 +9,11 @@ name = "stepper_lib"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
air-parser = { path = "../crates/air-parser" }
|
||||
fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["logger"] }
|
||||
|
||||
serde = { version = "1.0.116", features = [ "derive", "rc" ] }
|
||||
serde_derive = "1.0.116"
|
||||
serde_sexpr = "0.1.0"
|
||||
|
||||
jsonpath_lib = "0.2.5"
|
||||
|
||||
|
@ -13,7 +13,7 @@ use std::cell::RefCell;
|
||||
thread_local!(static VM: RefCell<AquamarineVM> = RefCell::new(create_aqua_vm(unit_call_service(), "test_peer_id")));
|
||||
thread_local!(static SCRIPT: String = String::from(
|
||||
r#"
|
||||
(call (%current_peer_id% ("local_service_id" "local_fn_name") () result_name))
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_name)
|
||||
"#,
|
||||
)
|
||||
);
|
||||
|
@ -34,24 +34,24 @@ thread_local!(static CLIENT_2_VM: RefCell<AquamarineVM> = RefCell::new(create_aq
|
||||
fn chat_sent_message_benchmark() -> Result<StepperOutcome, AquamarineVMError> {
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(call ("Relay1" ("identity" "") () void1[]))
|
||||
(seq (
|
||||
(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[]))
|
||||
))
|
||||
(seq
|
||||
(call "Relay1" ("identity" "") [] void1[])
|
||||
(seq
|
||||
(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[])
|
||||
)
|
||||
(next m)
|
||||
))
|
||||
))
|
||||
))
|
||||
))
|
||||
))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
"#,
|
||||
);
|
||||
|
||||
|
@ -71,25 +71,25 @@ thread_local!(static SET_VARIABLES_VM: RefCell<AquamarineVM> = RefCell::new({
|
||||
fn create_service_benchmark() -> Result<StepperOutcome, AquamarineVMError> {
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(seq (
|
||||
(seq (
|
||||
(call ("set_variables" ("" "") ("module_bytes") module_bytes))
|
||||
(call ("set_variables" ("" "") ("module_config") module_config))
|
||||
))
|
||||
(call ("set_variables" ("" "") ("blueprint") blueprint))
|
||||
))
|
||||
(seq (
|
||||
(call ("A" ("add_module" "") (module_bytes module_config) module))
|
||||
(seq (
|
||||
(call ("A" ("add_blueprint" "") (blueprint) blueprint_id))
|
||||
(seq (
|
||||
(call ("A" ("create" "") (blueprint_id) service_id))
|
||||
(call ("remote_peer_id" ("" "") (service_id) client_result))
|
||||
))
|
||||
))
|
||||
))
|
||||
))"#,
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call "set_variables" ("" "") ["module_bytes"] module_bytes)
|
||||
(call "set_variables" ("" "") ["module_config"] module_config)
|
||||
)
|
||||
(call "set_variables" ("" "") ["blueprint"] blueprint)
|
||||
)
|
||||
(seq
|
||||
(call "A" ("add_module" "") [module_bytes module_config] module)
|
||||
(seq
|
||||
(call "A" ("add_blueprint" "") [blueprint] blueprint_id)
|
||||
(seq
|
||||
(call "A" ("create" "") [blueprint_id] service_id)
|
||||
(call "remote_peer_id" ("" "") [service_id] client_result)
|
||||
)
|
||||
)
|
||||
)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = SET_VARIABLES_VM
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
mod parsed_call;
|
||||
mod triplet;
|
||||
mod utils;
|
||||
|
||||
use parsed_call::ParsedCall;
|
||||
@ -26,10 +27,7 @@ use crate::AquamarineError::VariableNotFound;
|
||||
use crate::AquamarineError::VariableNotInJsonPath;
|
||||
use crate::Result;
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
use serde_derive::Serialize;
|
||||
|
||||
const CURRENT_PEER_ALIAS: &str = "%current_peer_id%";
|
||||
use air_parser::ast::Call;
|
||||
|
||||
/*
|
||||
(current)
|
||||
@ -42,25 +40,8 @@ const CURRENT_PEER_ALIAS: &str = "%current_peer_id%";
|
||||
FN_PART: resolves to (fn_name) \/ (fn_srv_id, fn_name)
|
||||
*/
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
#[serde(untagged)]
|
||||
pub(self) enum PeerPart {
|
||||
PeerPk(String),
|
||||
PeerPkWithServiceId(String, String),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
#[serde(untagged)]
|
||||
pub(self) enum FunctionPart {
|
||||
FuncName(String),
|
||||
ServiceIdWithFuncName(String, String),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct Call(PeerPart, FunctionPart, Vec<String>, String);
|
||||
|
||||
impl super::ExecutableInstruction for Call {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
impl<'i> super::ExecutableInstruction<'i> for Call<'i> {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
log_instruction!(call, exec_ctx, call_ctx);
|
||||
|
||||
let parsed_call = match ParsedCall::new(self, exec_ctx) {
|
||||
@ -113,7 +94,7 @@ mod tests {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(call (%current_peer_id% ("local_service_id" "local_fn_name") () result_name))
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_name)
|
||||
"#,
|
||||
);
|
||||
|
||||
@ -129,7 +110,7 @@ mod tests {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(call ("test_peer_id" ("local_service_id" "local_fn_name") () result_name))
|
||||
(call "test_peer_id" ("local_service_id" "local_fn_name") [] result_name)
|
||||
"#,
|
||||
);
|
||||
|
||||
@ -154,7 +135,7 @@ mod tests {
|
||||
|
||||
let remote_peer_id = String::from("some_remote_peer_id");
|
||||
let script = format!(
|
||||
r#"(call ("{}" ("local_service_id" "local_fn_name") (value) result_name))"#,
|
||||
r#"(call "{}" ("local_service_id" "local_fn_name") [value] result_name)"#,
|
||||
remote_peer_id
|
||||
);
|
||||
|
||||
@ -173,10 +154,10 @@ mod tests {
|
||||
|
||||
let script = format!(
|
||||
r#"
|
||||
(seq (
|
||||
(call ("set_variable" ("some_service_id" "local_fn_name") () remote_peer_id))
|
||||
(call (remote_peer_id ("some_service_id" "local_fn_name") () result_name))
|
||||
))
|
||||
(seq
|
||||
(call "set_variable" ("some_service_id" "local_fn_name") [] remote_peer_id)
|
||||
(call remote_peer_id ("some_service_id" "local_fn_name") [] result_name)
|
||||
)
|
||||
"#,
|
||||
);
|
||||
|
||||
@ -207,10 +188,10 @@ mod tests {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(call ("set_variable" ("some_service_id" "local_fn_name") () arg3))
|
||||
(call ("A" ("some_service_id" "local_fn_name") ("arg1" "arg2" arg3) result))
|
||||
))
|
||||
(seq
|
||||
(call "set_variable" ("some_service_id" "local_fn_name") [] arg3)
|
||||
(call "A" ("some_service_id" "local_fn_name") ["arg1" "arg2" arg3] result)
|
||||
)
|
||||
"#,
|
||||
);
|
||||
|
||||
|
@ -16,63 +16,62 @@
|
||||
|
||||
#![allow(unused_unsafe)] // for wasm_bindgen target where calling FFI is safe
|
||||
|
||||
use super::utils::find_by_json_path;
|
||||
use super::utils::is_string_literal;
|
||||
use super::utils::set_local_call_result;
|
||||
use super::triplet::{ResolvedTriplet, Triplet};
|
||||
use super::utils::{resolve_jvalue, set_local_call_result, set_remote_call_result};
|
||||
use super::Call;
|
||||
use super::CURRENT_PEER_ALIAS;
|
||||
|
||||
use crate::air::ExecutionCtx;
|
||||
use crate::build_targets::CALL_SERVICE_SUCCESS;
|
||||
use crate::call_evidence::CallEvidenceCtx;
|
||||
use crate::call_evidence::CallResult;
|
||||
use crate::call_evidence::EvidenceState;
|
||||
use crate::call_evidence::{CallEvidenceCtx, CallResult, EvidenceState};
|
||||
use crate::log_targets::EVIDENCE_CHANGING;
|
||||
use crate::AValue;
|
||||
use crate::AquamarineError;
|
||||
use crate::JValue;
|
||||
use crate::Result;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use air_parser::ast::{CallOutput, Value};
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(super) struct ParsedCall {
|
||||
pub(super) struct ParsedCall<'i> {
|
||||
peer_pk: String,
|
||||
service_id: String,
|
||||
function_name: String,
|
||||
function_arg_paths: Vec<String>,
|
||||
result_variable_name: String,
|
||||
function_arg_paths: Vec<Value<'i>>,
|
||||
output: CallOutput<'i>,
|
||||
}
|
||||
|
||||
impl ParsedCall {
|
||||
pub(super) fn new(raw_call: &Call, exec_ctx: &ExecutionCtx) -> Result<Self> {
|
||||
let (peer_pk, service_id, function_name) = prepare_peer_fn_parts(raw_call, exec_ctx)?;
|
||||
let result_variable_name = parse_result_variable_name(raw_call)?;
|
||||
impl<'i> ParsedCall<'i> {
|
||||
/// Builds `ParsedCall` from `Call` by transforming `PeerPart` & `FunctionPart` into `ResolvedTriplet`
|
||||
pub(super) fn new(raw_call: &Call<'i>, exec_ctx: &ExecutionCtx<'i>) -> Result<Self> {
|
||||
let triplet = Triplet::try_from(&raw_call.peer_part, &raw_call.function_part)?;
|
||||
#[rustfmt::skip]
|
||||
let ResolvedTriplet { peer_pk, service_id, function_name } = triplet.resolve(exec_ctx)?;
|
||||
|
||||
Ok(Self {
|
||||
peer_pk,
|
||||
service_id,
|
||||
function_name,
|
||||
function_arg_paths: raw_call.2.clone(),
|
||||
result_variable_name: result_variable_name.to_string(),
|
||||
function_arg_paths: raw_call.args.clone(),
|
||||
output: raw_call.output.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn execute(self, exec_ctx: &mut ExecutionCtx, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
let should_executed = self.prepare_evidence_state(exec_ctx, call_ctx)?;
|
||||
if !should_executed {
|
||||
pub(super) fn execute(self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
let should_execute = self.prepare_evidence_state(exec_ctx, call_ctx)?;
|
||||
if !should_execute {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if self.peer_pk != exec_ctx.current_peer_id && self.peer_pk != CURRENT_PEER_ALIAS {
|
||||
super::utils::set_remote_call_result(self.peer_pk, exec_ctx, call_ctx);
|
||||
if self.peer_pk != exec_ctx.current_peer_id {
|
||||
set_remote_call_result(self.peer_pk, exec_ctx, call_ctx);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let function_args = extract_args_by_paths(&self.function_arg_paths, exec_ctx)?;
|
||||
let function_args = serde_json::to_string(&function_args)
|
||||
.map_err(|e| AquamarineError::FuncArgsSerializationError(function_args, e))?;
|
||||
let function_args = self.function_arg_paths.iter();
|
||||
let function_args: Result<Vec<_>> = function_args.map(|v| resolve_jvalue(v, exec_ctx)).collect();
|
||||
let function_args = JValue::Array(function_args?).to_string();
|
||||
|
||||
let result = unsafe { crate::call_service(self.service_id, self.function_name, function_args) };
|
||||
|
||||
@ -88,7 +87,7 @@ impl ParsedCall {
|
||||
let result: JValue = serde_json::from_str(&result.result)
|
||||
.map_err(|e| AquamarineError::CallServiceResultDeserializationError(result, e))?;
|
||||
let result = Rc::new(result);
|
||||
super::utils::set_local_call_result(self.result_variable_name, exec_ctx, result.clone())?;
|
||||
set_local_call_result(self.output, exec_ctx, result.clone())?;
|
||||
|
||||
let new_evidence_state = EvidenceState::Call(CallResult::Executed(result));
|
||||
log::info!(
|
||||
@ -103,7 +102,7 @@ impl ParsedCall {
|
||||
|
||||
pub(super) fn prepare_evidence_state(
|
||||
&self,
|
||||
exec_ctx: &mut ExecutionCtx,
|
||||
exec_ctx: &mut ExecutionCtx<'i>,
|
||||
call_ctx: &mut CallEvidenceCtx,
|
||||
) -> Result<bool> {
|
||||
use crate::call_evidence::CallResult::*;
|
||||
@ -147,7 +146,7 @@ impl ParsedCall {
|
||||
}
|
||||
// this instruction's been already executed
|
||||
Call(Executed(result)) => {
|
||||
set_local_call_result(self.result_variable_name.clone(), exec_ctx, result.clone())?;
|
||||
set_local_call_result(self.output.clone(), exec_ctx, result.clone())?;
|
||||
call_ctx.new_path.push_back(prev_state);
|
||||
Ok(false)
|
||||
}
|
||||
@ -159,132 +158,3 @@ impl ParsedCall {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_peer_fn_parts<'a>(raw_call: &'a Call, exec_ctx: &'a ExecutionCtx) -> Result<(String, String, String)> {
|
||||
use super::FunctionPart::*;
|
||||
use super::PeerPart::*;
|
||||
|
||||
let (peer_pk, service_id, func_name) = match (&raw_call.0, &raw_call.1) {
|
||||
(PeerPkWithServiceId(peer_pk, peer_service_id), ServiceIdWithFuncName(_service_id, func_name)) => {
|
||||
Ok((peer_pk, peer_service_id, func_name))
|
||||
}
|
||||
(PeerPkWithServiceId(peer_pk, peer_service_id), FuncName(func_name)) => {
|
||||
Ok((peer_pk, peer_service_id, func_name))
|
||||
}
|
||||
(PeerPk(peer_pk), ServiceIdWithFuncName(service_id, func_name)) => Ok((peer_pk, service_id, func_name)),
|
||||
(PeerPk(_), FuncName(_)) => Err(AquamarineError::InstructionError(String::from(
|
||||
"call should have service id specified by peer part or function part",
|
||||
))),
|
||||
}?;
|
||||
|
||||
let peer_pk = if peer_pk != CURRENT_PEER_ALIAS {
|
||||
prepare_call_arg(peer_pk, exec_ctx)?
|
||||
} else {
|
||||
peer_pk.to_string()
|
||||
};
|
||||
|
||||
let service_id = prepare_call_arg(service_id, exec_ctx)?;
|
||||
let func_name = prepare_call_arg(func_name, exec_ctx)?;
|
||||
|
||||
Ok((peer_pk, service_id, func_name))
|
||||
}
|
||||
|
||||
fn extract_args_by_paths(function_arg_paths: &[String], ctx: &ExecutionCtx) -> Result<JValue> {
|
||||
let mut result = Vec::with_capacity(function_arg_paths.len());
|
||||
let owned_maybe_json_path = |jvalue: Cow<'_, JValue>, json_path: Option<&str>| -> Result<Vec<JValue>> {
|
||||
if json_path.is_none() {
|
||||
return Ok(vec![jvalue.into_owned()]);
|
||||
}
|
||||
|
||||
let json_path = json_path.unwrap();
|
||||
let values = find_by_json_path(jvalue.as_ref(), json_path)?;
|
||||
Ok(values.into_iter().cloned().collect())
|
||||
};
|
||||
|
||||
for arg_path in function_arg_paths.iter() {
|
||||
if is_string_literal(arg_path) {
|
||||
result.push(JValue::String(arg_path[1..arg_path.len() - 1].to_string()));
|
||||
} else {
|
||||
let arg = get_args_by_path(arg_path, ctx, owned_maybe_json_path)?;
|
||||
result.extend(arg);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(JValue::Array(result))
|
||||
}
|
||||
|
||||
fn parse_result_variable_name(call: &Call) -> Result<&str> {
|
||||
let result_variable_name = &call.3;
|
||||
|
||||
if result_variable_name.is_empty() {
|
||||
return Err(AquamarineError::InstructionError(String::from(
|
||||
"result name of a call instruction must be non empty",
|
||||
)));
|
||||
}
|
||||
|
||||
if is_string_literal(result_variable_name) {
|
||||
return Err(AquamarineError::InstructionError(String::from(
|
||||
"result name of a call instruction must be non string literal",
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(result_variable_name)
|
||||
}
|
||||
|
||||
fn get_args_by_path<'args_path, 'exec_ctx, T: 'exec_ctx>(
|
||||
args_path: &'args_path str,
|
||||
ctx: &'exec_ctx ExecutionCtx,
|
||||
maybe_json_path: impl FnOnce(Cow<'exec_ctx, JValue>, Option<&str>) -> Result<T>,
|
||||
) -> Result<T> {
|
||||
let mut split_arg: Vec<&str> = args_path.splitn(2, '.').collect();
|
||||
let arg_path_head = split_arg.remove(0);
|
||||
|
||||
match ctx.data_cache.get(arg_path_head) {
|
||||
Some(AValue::JValueFoldCursor(fold_state)) => match fold_state.iterable.as_ref() {
|
||||
JValue::Array(array) => {
|
||||
let jvalue = &array[fold_state.cursor];
|
||||
maybe_json_path(Cow::Borrowed(jvalue), split_arg.pop())
|
||||
}
|
||||
_ => unreachable!("fold state must be well-formed because it is changed only by stepper"),
|
||||
},
|
||||
Some(AValue::JValueRef(value)) => maybe_json_path(Cow::Borrowed(value.as_ref()), split_arg.pop()),
|
||||
Some(AValue::JValueAccumulatorRef(acc)) => {
|
||||
let owned_acc = acc.borrow().iter().map(|v| v.as_ref()).cloned().collect::<Vec<_>>();
|
||||
let jvalue = JValue::Array(owned_acc);
|
||||
maybe_json_path(Cow::Owned(jvalue), split_arg.pop())
|
||||
}
|
||||
None => Err(AquamarineError::VariableNotFound(arg_path_head.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare arguments of call
|
||||
fn prepare_call_arg<'a>(arg_path: &'a str, ctx: &'a ExecutionCtx) -> Result<String> {
|
||||
fn borrowed_maybe_json_path(jvalue: Cow<'_, JValue>, json_path: Option<&str>) -> Result<JValue> {
|
||||
if json_path.is_none() {
|
||||
return Ok(jvalue.into_owned());
|
||||
}
|
||||
|
||||
let json_path = json_path.unwrap();
|
||||
let values = find_by_json_path(jvalue.as_ref(), json_path)?;
|
||||
if values.is_empty() {
|
||||
return Err(AquamarineError::VariableNotFound(json_path.to_string()));
|
||||
}
|
||||
|
||||
if values.len() != 1 {
|
||||
return Err(AquamarineError::MultipleValuesInJsonPath(json_path.to_string()));
|
||||
}
|
||||
|
||||
Ok(values[0].clone())
|
||||
}
|
||||
|
||||
if is_string_literal(arg_path) {
|
||||
return Ok(arg_path[1..arg_path.len() - 1].to_string());
|
||||
}
|
||||
|
||||
let arg = get_args_by_path(arg_path, ctx, borrowed_maybe_json_path)?;
|
||||
|
||||
match arg {
|
||||
JValue::String(str) => Ok(str),
|
||||
v => Err(AquamarineError::IncompatibleJValueType(v, String::from("string"))),
|
||||
}
|
||||
}
|
||||
|
83
stepper-lib/src/air/call/triplet.rs
Normal file
83
stepper-lib/src/air/call/triplet.rs
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::utils::resolve_value;
|
||||
|
||||
use crate::air::ExecutionCtx;
|
||||
use crate::{AquamarineError, Result};
|
||||
|
||||
use air_parser::ast::{FunctionPart, PeerPart, Value};
|
||||
|
||||
/// Triplet represents a location of the executable code in the network
|
||||
/// It is build from `PeerPart` and `FunctionPart` of a `Call` instruction
|
||||
pub(super) struct Triplet<'a, 'i> {
|
||||
pub(super) peer_pk: &'a Value<'i>,
|
||||
pub(super) service_id: &'a Value<'i>,
|
||||
pub(super) function_name: &'a Value<'i>,
|
||||
}
|
||||
|
||||
/// ResolvedTriplet represents same location as `Triplet`, but with all
|
||||
/// variables, literals and etc resolved into final `String`
|
||||
pub(super) struct ResolvedTriplet {
|
||||
pub(super) peer_pk: String,
|
||||
pub(super) service_id: String,
|
||||
pub(super) function_name: String,
|
||||
}
|
||||
|
||||
impl<'a, 'i> Triplet<'a, 'i> {
|
||||
/// Build a `Triplet` from `Call`'s `PeerPart` and `FunctionPart`
|
||||
pub fn try_from(peer: &'a PeerPart<'i>, f: &'a FunctionPart<'i>) -> Result<Self> {
|
||||
use air_parser::ast::FunctionPart::*;
|
||||
use air_parser::ast::PeerPart::*;
|
||||
|
||||
let (peer_pk, service_id, function_name) = match (peer, f) {
|
||||
(PeerPkWithServiceId(peer_pk, peer_service_id), ServiceIdWithFuncName(_service_id, func_name)) => {
|
||||
Ok((peer_pk, peer_service_id, func_name))
|
||||
}
|
||||
(PeerPkWithServiceId(peer_pk, peer_service_id), FuncName(func_name)) => {
|
||||
Ok((peer_pk, peer_service_id, func_name))
|
||||
}
|
||||
(PeerPk(peer_pk), ServiceIdWithFuncName(service_id, func_name)) => Ok((peer_pk, service_id, func_name)),
|
||||
(PeerPk(_), FuncName(_)) => Err(AquamarineError::InstructionError(String::from(
|
||||
"call should have service id specified by peer part or function part",
|
||||
))),
|
||||
}?;
|
||||
|
||||
Ok(Self {
|
||||
peer_pk,
|
||||
service_id,
|
||||
function_name,
|
||||
})
|
||||
}
|
||||
|
||||
/// Resolve variables, literals, etc in the `Triplet`, and build a `ResolvedTriplet`
|
||||
pub fn resolve(self, ctx: &'a ExecutionCtx<'i>) -> Result<ResolvedTriplet> {
|
||||
let Triplet {
|
||||
peer_pk,
|
||||
service_id,
|
||||
function_name,
|
||||
} = self;
|
||||
let peer_pk = resolve_value(peer_pk, ctx)?.as_ref().to_string();
|
||||
let service_id = resolve_value(service_id, ctx)?.as_ref().to_string();
|
||||
let function_name = resolve_value(function_name, ctx)?.as_ref().to_string();
|
||||
|
||||
Ok(ResolvedTriplet {
|
||||
peer_pk,
|
||||
service_id,
|
||||
function_name,
|
||||
})
|
||||
}
|
||||
}
|
@ -24,29 +24,28 @@ use crate::AquamarineError;
|
||||
use crate::JValue;
|
||||
use crate::Result;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use air_parser::ast::{CallOutput, Value};
|
||||
|
||||
pub(super) fn set_local_call_result(
|
||||
result_variable_name: String,
|
||||
exec_ctx: &mut ExecutionCtx,
|
||||
use std::{borrow::Cow, cell::RefCell, rc::Rc};
|
||||
|
||||
/// Writes result of a local `Call` instruction to `ExecutionCtx` at `output`
|
||||
pub(super) fn set_local_call_result<'i>(
|
||||
output: CallOutput<'i>,
|
||||
exec_ctx: &mut ExecutionCtx<'i>,
|
||||
result: Rc<JValue>,
|
||||
) -> Result<()> {
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use AquamarineError::*;
|
||||
|
||||
let stripped_result_name = result_variable_name.strip_suffix("[]");
|
||||
if stripped_result_name.is_none() {
|
||||
// if result is not an array, simply insert it into data
|
||||
match exec_ctx.data_cache.entry(result_variable_name) {
|
||||
match output {
|
||||
CallOutput::Scalar(name) => {
|
||||
match exec_ctx.data_cache.entry(name.to_string()) {
|
||||
Vacant(entry) => entry.insert(AValue::JValueRef(result)),
|
||||
Occupied(entry) => return Err(MultipleVariablesFound(entry.key().clone())),
|
||||
};
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// unwrap is safe because it's been checked for []
|
||||
match exec_ctx.data_cache.entry(stripped_result_name.unwrap().to_string()) {
|
||||
CallOutput::Accumulator(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(result),
|
||||
@ -55,12 +54,19 @@ pub(super) fn set_local_call_result(
|
||||
Vacant(entry) => {
|
||||
entry.insert(AValue::JValueAccumulatorRef(RefCell::new(vec![result])));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn set_remote_call_result(peer_pk: String, exec_ctx: &mut ExecutionCtx, call_ctx: &mut CallEvidenceCtx) {
|
||||
/// Writes evidence of a particle being sent to remote node
|
||||
pub(super) fn set_remote_call_result<'i>(
|
||||
peer_pk: String,
|
||||
exec_ctx: &mut ExecutionCtx<'i>,
|
||||
call_ctx: &mut CallEvidenceCtx,
|
||||
) {
|
||||
exec_ctx.next_peer_pks.push(peer_pk);
|
||||
exec_ctx.subtree_complete = false;
|
||||
|
||||
@ -73,6 +79,7 @@ pub(super) fn set_remote_call_result(peer_pk: String, exec_ctx: &mut ExecutionCt
|
||||
call_ctx.new_path.push_back(new_evidence_state);
|
||||
}
|
||||
|
||||
/// Applies `json_path` to `jvalue`
|
||||
pub(super) fn find_by_json_path<'jvalue, 'json_path>(
|
||||
jvalue: &'jvalue JValue,
|
||||
json_path: &'json_path str,
|
||||
@ -82,6 +89,86 @@ pub(super) fn find_by_json_path<'jvalue, 'json_path>(
|
||||
jsonpath_lib::select(jvalue, json_path).map_err(|e| JsonPathError(jvalue.clone(), String::from(json_path), e))
|
||||
}
|
||||
|
||||
pub(super) fn is_string_literal(value: &str) -> bool {
|
||||
value.starts_with('"') && value.ends_with('"')
|
||||
/// Takes variable's value from `ExecutionCtx::data_cache`
|
||||
/// TODO: maybe return &'i JValue?
|
||||
pub(super) fn resolve_variable<'exec_ctx, 'i>(variable: &'i str, ctx: &'exec_ctx ExecutionCtx<'i>) -> Result<JValue> {
|
||||
use AquamarineError::VariableNotFound;
|
||||
|
||||
let value = ctx
|
||||
.data_cache
|
||||
.get(variable)
|
||||
.ok_or_else(|| VariableNotFound(variable.to_string()))?;
|
||||
|
||||
match value {
|
||||
AValue::JValueFoldCursor(fold_state) => {
|
||||
if let JValue::Array(array) = fold_state.iterable.as_ref() {
|
||||
Ok(array[fold_state.cursor].clone())
|
||||
} else {
|
||||
unreachable!("fold state must be well-formed because it is changed only by stepper")
|
||||
}
|
||||
}
|
||||
AValue::JValueRef(value) => Ok(value.as_ref().clone()),
|
||||
AValue::JValueAccumulatorRef(acc) => {
|
||||
let owned_acc = acc.borrow().iter().map(|v| v.as_ref()).cloned().collect::<Vec<_>>();
|
||||
Ok(JValue::Array(owned_acc))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn apply_json_path<'i>(jvalue: JValue, json_path: &'i str) -> Result<JValue> {
|
||||
let values = find_by_json_path(&jvalue, json_path)?;
|
||||
if values.is_empty() {
|
||||
return Err(AquamarineError::VariableNotFound(json_path.to_string()));
|
||||
}
|
||||
|
||||
if values.len() != 1 {
|
||||
return Err(AquamarineError::MultipleValuesInJsonPath(json_path.to_string()));
|
||||
}
|
||||
|
||||
// TODO: sure need this clone?
|
||||
Ok(values[0].clone())
|
||||
}
|
||||
|
||||
pub(super) fn require_string(value: JValue) -> Result<String> {
|
||||
if let JValue::String(s) = value {
|
||||
Ok(s)
|
||||
} else {
|
||||
Err(AquamarineError::IncompatibleJValueType(value, "string".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve value to string by either resolving variable from `ExecutionCtx`, taking literal value, or etc
|
||||
pub(super) fn resolve_value<'i, 'a: 'i>(value: &'a Value<'i>, ctx: &'a ExecutionCtx<'i>) -> Result<Cow<'i, str>> {
|
||||
let resolved = match value {
|
||||
Value::CurrentPeerId => Cow::Borrowed(ctx.current_peer_id.as_str()),
|
||||
Value::Literal(value) => Cow::Borrowed(*value),
|
||||
Value::Variable(name) => {
|
||||
let resolved = resolve_variable(name, ctx)?;
|
||||
let resolved = require_string(resolved)?;
|
||||
Cow::Owned(resolved)
|
||||
}
|
||||
Value::JsonPath { variable, path } => {
|
||||
let resolved = resolve_variable(variable, ctx)?;
|
||||
let resolved = apply_json_path(resolved, path)?;
|
||||
let resolved = require_string(resolved)?;
|
||||
Cow::Owned(resolved)
|
||||
}
|
||||
};
|
||||
|
||||
Ok(resolved)
|
||||
}
|
||||
|
||||
/// Resolve value to JValue, similar to `resolve_value`
|
||||
pub(super) fn resolve_jvalue<'i>(value: &Value<'i>, ctx: &ExecutionCtx<'i>) -> Result<JValue> {
|
||||
let value = match value {
|
||||
Value::CurrentPeerId => JValue::String(ctx.current_peer_id.clone()),
|
||||
Value::Literal(value) => JValue::String(value.to_string()),
|
||||
Value::Variable(name) => resolve_variable(name, ctx)?,
|
||||
Value::JsonPath { variable, path } => {
|
||||
let value = resolve_variable(variable, ctx)?;
|
||||
apply_json_path(value, path)?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ use std::fmt::Formatter;
|
||||
|
||||
/// Execution context contains all necessary information needed to execute aqua script.
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub(crate) struct ExecutionCtx {
|
||||
pub(crate) struct ExecutionCtx<'i> {
|
||||
/// Contains all set variables.
|
||||
pub data_cache: HashMap<String, AValue>,
|
||||
pub data_cache: HashMap<String, AValue<'i>>,
|
||||
|
||||
/// Set of peer public keys that should receive resulted data.
|
||||
pub next_peer_pks: Vec<String>,
|
||||
@ -41,7 +41,7 @@ pub(crate) struct ExecutionCtx {
|
||||
pub subtree_complete: bool,
|
||||
}
|
||||
|
||||
impl ExecutionCtx {
|
||||
impl<'i> ExecutionCtx<'i> {
|
||||
pub(crate) fn new(current_peer_id: String) -> Self {
|
||||
Self {
|
||||
data_cache: HashMap::new(),
|
||||
@ -52,7 +52,7 @@ impl ExecutionCtx {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ExecutionCtx {
|
||||
impl<'i> Display for ExecutionCtx<'i> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "data cache:")?;
|
||||
for (key, value) in self.data_cache.iter() {
|
||||
|
@ -23,8 +23,8 @@ use crate::AquamarineError;
|
||||
use crate::JValue;
|
||||
use crate::Result;
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
use serde_derive::Serialize;
|
||||
use air_parser::ast::{Fold, Next};
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
/*
|
||||
@ -36,32 +36,22 @@ use std::rc::Rc;
|
||||
)
|
||||
*/
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct Fold(String, String, Rc<Instruction>);
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct Next(String);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct FoldState {
|
||||
pub(crate) struct FoldState<'i> {
|
||||
// TODO: maybe change to bidirectional iterator
|
||||
pub(crate) cursor: usize,
|
||||
pub(crate) iterable: Rc<JValue>,
|
||||
pub(crate) instr_head: Rc<Instruction>,
|
||||
pub(crate) instr_head: Rc<Instruction<'i>>,
|
||||
}
|
||||
|
||||
impl super::ExecutableInstruction for Fold {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
impl<'i> super::ExecutableInstruction<'i> for Fold<'i> {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
use AquamarineError::*;
|
||||
|
||||
log_instruction!(fold, exec_ctx, call_ctx);
|
||||
|
||||
let iterable_name = &self.0;
|
||||
let iterator_name = &self.1;
|
||||
let instr_head = self.2.clone();
|
||||
|
||||
// check that value exists and has array type
|
||||
let iterable = match exec_ctx.data_cache.get(iterable_name) {
|
||||
let iterable = match exec_ctx.data_cache.get(self.iterable) {
|
||||
Some(AValue::JValueRef(jvalue_rc)) => {
|
||||
match jvalue_rc.as_ref() {
|
||||
JValue::Array(array) => {
|
||||
@ -76,41 +66,41 @@ impl super::ExecutableInstruction for Fold {
|
||||
}
|
||||
}
|
||||
Some(v) => return Err(IncompatibleAValueType(format!("{:?}", v), String::from("JValueRef"))),
|
||||
None => return Err(VariableNotFound(String::from(iterable_name))),
|
||||
None => return Err(VariableNotFound(self.iterable.to_string())),
|
||||
};
|
||||
|
||||
let fold_state = FoldState {
|
||||
cursor: 0,
|
||||
iterable: iterable.clone(),
|
||||
instr_head: instr_head.clone(),
|
||||
instr_head: self.instruction.clone(),
|
||||
};
|
||||
|
||||
let previous_value = exec_ctx
|
||||
.data_cache
|
||||
.insert(iterator_name.clone(), AValue::JValueFoldCursor(fold_state));
|
||||
.insert(self.iterator.to_string(), AValue::JValueFoldCursor(fold_state));
|
||||
|
||||
if previous_value.is_some() {
|
||||
return Err(MultipleFoldStates(iterable_name.clone()));
|
||||
return Err(MultipleFoldStates(self.iterable.to_string()));
|
||||
}
|
||||
|
||||
instr_head.execute(exec_ctx, call_ctx)?;
|
||||
exec_ctx.data_cache.remove(iterator_name);
|
||||
self.instruction.execute(exec_ctx, call_ctx)?;
|
||||
exec_ctx.data_cache.remove(self.iterator);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl super::ExecutableInstruction for Next {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
impl<'i> super::ExecutableInstruction<'i> for Next<'i> {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
use AquamarineError::IncompatibleAValueType;
|
||||
|
||||
log_instruction!(next, exec_ctx, call_ctx);
|
||||
|
||||
let iterator_name = &self.0;
|
||||
let iterator_name = self.0;
|
||||
let avalue = exec_ctx
|
||||
.data_cache
|
||||
.get_mut(iterator_name)
|
||||
.ok_or_else(|| AquamarineError::FoldStateNotFound(iterator_name.clone()))?;
|
||||
.ok_or_else(|| AquamarineError::FoldStateNotFound(iterator_name.to_string()))?;
|
||||
let fold_state = match avalue {
|
||||
AValue::JValueFoldCursor(state) => state,
|
||||
v => {
|
||||
@ -172,15 +162,15 @@ mod tests {
|
||||
|
||||
let lfold = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(call ("set_variable" ("" "") () Iterable))
|
||||
(fold (Iterable i
|
||||
(seq (
|
||||
(call ("A" ("" "") (i) acc[]))
|
||||
(seq
|
||||
(call "set_variable" ("" "") [] Iterable)
|
||||
(fold Iterable i
|
||||
(seq
|
||||
(call "A" ("" "") [i] acc[])
|
||||
(next i)
|
||||
))
|
||||
))
|
||||
))"#,
|
||||
)
|
||||
)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(set_variable_vm, "", lfold.clone(), "[]", "[]");
|
||||
@ -205,15 +195,15 @@ mod tests {
|
||||
|
||||
let rfold = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(call ("set_variable" ("" "") () Iterable))
|
||||
(fold (Iterable i
|
||||
(seq (
|
||||
(seq
|
||||
(call "set_variable" ("" "") [] Iterable)
|
||||
(fold Iterable i
|
||||
(seq
|
||||
(next i)
|
||||
(call ("A" ("" "") (i) acc[]))
|
||||
))
|
||||
))
|
||||
))"#,
|
||||
(call "A" ("" "") [i] acc[])
|
||||
)
|
||||
)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(set_variable_vm, "", rfold.clone(), "[]", "[]");
|
||||
@ -238,23 +228,23 @@ mod tests {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(seq (
|
||||
(call ("set_variable" ("" "") () Iterable1))
|
||||
(call ("set_variable" ("" "") () Iterable2))
|
||||
))
|
||||
(fold (Iterable1 i
|
||||
(seq (
|
||||
(fold (Iterable2 j
|
||||
(seq (
|
||||
(call ("A" ("" "") (i) acc[]))
|
||||
(seq
|
||||
(seq
|
||||
(call "set_variable" ("" "") [] Iterable1)
|
||||
(call "set_variable" ("" "") [] Iterable2)
|
||||
)
|
||||
(fold Iterable1 i
|
||||
(seq
|
||||
(fold Iterable2 j
|
||||
(seq
|
||||
(call "A" ("" "") [i] acc[])
|
||||
(next j)
|
||||
))
|
||||
))
|
||||
)
|
||||
)
|
||||
(next i)
|
||||
))
|
||||
))
|
||||
))"#,
|
||||
)
|
||||
)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(set_variable_vm, "", script.clone(), "[]", "[]");
|
||||
@ -281,23 +271,23 @@ mod tests {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(seq (
|
||||
(call ("set_variable" ("" "") () Iterable1))
|
||||
(call ("set_variable" ("" "") () Iterable2))
|
||||
))
|
||||
(fold (Iterable1 i
|
||||
(seq (
|
||||
(fold (Iterable2 i
|
||||
(seq (
|
||||
(call ("A" ("" "") (i) acc[]))
|
||||
(seq
|
||||
(seq
|
||||
(call "set_variable" ("" "") [] Iterable1)
|
||||
(call "set_variable" ("" "") [] Iterable2)
|
||||
)
|
||||
(fold Iterable1 i
|
||||
(seq
|
||||
(fold Iterable2 i
|
||||
(seq
|
||||
(call "A" ("" "") [i] acc[])
|
||||
(next i)
|
||||
))
|
||||
))
|
||||
)
|
||||
)
|
||||
(next i)
|
||||
))
|
||||
))
|
||||
))"#,
|
||||
)
|
||||
)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = vm.call_with_prev_data("", script, "[]", "[]");
|
||||
@ -325,15 +315,15 @@ mod tests {
|
||||
|
||||
let empty_fold = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(call ("set_variable" ("" "") () Iterable))
|
||||
(fold (Iterable i
|
||||
(seq (
|
||||
(call ("A" ("" "") (i) acc[]))
|
||||
(seq
|
||||
(call "set_variable" ("" "") [] Iterable)
|
||||
(fold Iterable i
|
||||
(seq
|
||||
(call "A" ("" "") [i] acc[])
|
||||
(next i)
|
||||
))
|
||||
))
|
||||
))"#,
|
||||
)
|
||||
)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(set_variable_vm, "", empty_fold.clone(), "[]", "[]");
|
||||
|
@ -29,43 +29,24 @@ pub(self) use crate::call_evidence::CallEvidenceCtx;
|
||||
pub(self) use crate::call_evidence::EvidenceState;
|
||||
|
||||
use crate::Result;
|
||||
use call::Call;
|
||||
use fold::Fold;
|
||||
use fold::Next;
|
||||
use null::Null;
|
||||
use par::Par;
|
||||
use seq::Seq;
|
||||
use xor::Xor;
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
use serde_derive::Serialize;
|
||||
use air_parser::ast::Instruction;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub(crate) enum Instruction {
|
||||
Null(Null),
|
||||
Call(Call),
|
||||
Fold(Fold),
|
||||
Next(Next),
|
||||
Par(Par),
|
||||
Seq(Seq),
|
||||
Xor(Xor),
|
||||
pub(crate) trait ExecutableInstruction<'i> {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()>;
|
||||
}
|
||||
|
||||
pub(crate) trait ExecutableInstruction {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx, call_ctx: &mut CallEvidenceCtx) -> Result<()>;
|
||||
}
|
||||
|
||||
impl ExecutableInstruction for Instruction {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
impl<'i> ExecutableInstruction<'i> for Instruction<'i> {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
match self {
|
||||
Instruction::Null(null) => null.execute(exec_ctx, call_ctx),
|
||||
Instruction::Seq(seq) => seq.execute(exec_ctx, call_ctx),
|
||||
Instruction::Call(call) => call.execute(exec_ctx, call_ctx),
|
||||
Instruction::Null(null) => null.execute(exec_ctx, call_ctx),
|
||||
Instruction::Fold(fold) => fold.execute(exec_ctx, call_ctx),
|
||||
Instruction::Next(next) => next.execute(exec_ctx, call_ctx),
|
||||
Instruction::Par(par) => par.execute(exec_ctx, call_ctx),
|
||||
Instruction::Seq(seq) => seq.execute(exec_ctx, call_ctx),
|
||||
Instruction::Xor(xor) => xor.execute(exec_ctx, call_ctx),
|
||||
Instruction::Error => unreachable!("should not execute if parsing failed. QED."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,10 @@ use super::ExecutionCtx;
|
||||
use crate::log_instruction;
|
||||
use crate::Result;
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
use serde_derive::Serialize;
|
||||
use air_parser::ast::Null;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct Null {}
|
||||
|
||||
impl super::ExecutableInstruction for Null {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
impl<'i> super::ExecutableInstruction<'i> for Null {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
log_instruction!(null, exec_ctx, call_ctx);
|
||||
|
||||
Ok(())
|
||||
|
@ -23,14 +23,10 @@ use crate::log_instruction;
|
||||
use crate::log_targets::EVIDENCE_CHANGING;
|
||||
use crate::Result;
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
use serde_derive::Serialize;
|
||||
use air_parser::ast::Par;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct Par(Box<Instruction>, Box<Instruction>);
|
||||
|
||||
impl ExecutableInstruction for Par {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
impl<'i> ExecutableInstruction<'i> for Par<'i> {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
log_instruction!(par, exec_ctx, call_ctx);
|
||||
|
||||
let (left_subtree_size, right_subtree_size) = extract_subtree_sizes(call_ctx)?;
|
||||
@ -87,10 +83,10 @@ fn extract_subtree_sizes(call_ctx: &mut CallEvidenceCtx) -> Result<(usize, usize
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_subtree(
|
||||
subtree: &Instruction,
|
||||
fn execute_subtree<'i>(
|
||||
subtree: &Instruction<'i>,
|
||||
subtree_size: usize,
|
||||
exec_ctx: &mut ExecutionCtx,
|
||||
exec_ctx: &mut ExecutionCtx<'i>,
|
||||
call_ctx: &mut CallEvidenceCtx,
|
||||
) -> Result<usize> {
|
||||
call_ctx.current_subtree_elements_count = subtree_size;
|
||||
@ -104,14 +100,14 @@ fn execute_subtree(
|
||||
Ok(call_ctx.new_path.len() - before_states_count)
|
||||
}
|
||||
|
||||
fn determine_subtree_complete(next_instruction: &Instruction) -> bool {
|
||||
fn determine_subtree_complete(next_instruction: &Instruction<'_>) -> bool {
|
||||
// this is needed to prevent situation when on such pattern
|
||||
// (fold (Iterable i
|
||||
// (par (
|
||||
// (call (..))
|
||||
// (par
|
||||
// (call ..)
|
||||
// (next i)
|
||||
// ))
|
||||
// ))
|
||||
// )
|
||||
// )
|
||||
// par will be executed after the last next that wouldn't change subtree_complete
|
||||
!matches!(next_instruction, Instruction::Next(_))
|
||||
}
|
||||
@ -130,10 +126,10 @@ mod tests {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(par (
|
||||
(call ("remote_peer_id_1" ("local_service_id" "local_fn_name") () result_name))
|
||||
(call ("remote_peer_id_2" ("service_id" "fn_name") () g))
|
||||
))"#,
|
||||
(par
|
||||
(call "remote_peer_id_1" ("local_service_id" "local_fn_name") [] result_name)
|
||||
(call "remote_peer_id_2" ("service_id" "fn_name") [] g)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let mut res = call_vm!(vm, "", script, "[]", "[]");
|
||||
@ -151,10 +147,10 @@ mod tests {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(par (
|
||||
(call (%current_peer_id% ("local_service_id" "local_fn_name") () result_name))
|
||||
(call ("remote_peer_id_2" ("service_id" "fn_name") () g))
|
||||
))"#,
|
||||
(par
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_name)
|
||||
(call "remote_peer_id_2" ("service_id" "fn_name") [] g)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(vm, "", script, "[]", "[]");
|
||||
|
@ -16,18 +16,13 @@
|
||||
|
||||
use super::CallEvidenceCtx;
|
||||
use super::ExecutionCtx;
|
||||
use super::Instruction;
|
||||
use crate::log_instruction;
|
||||
use crate::Result;
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
use serde_derive::Serialize;
|
||||
use air_parser::ast::Seq;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct Seq(Box<Instruction>, Box<Instruction>);
|
||||
|
||||
impl super::ExecutableInstruction for Seq {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
impl<'i> super::ExecutableInstruction<'i> for Seq<'i> {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
log_instruction!(seq, exec_ctx, call_ctx);
|
||||
|
||||
exec_ctx.subtree_complete = true;
|
||||
@ -55,10 +50,10 @@ mod tests {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(call ("remote_peer_id_1" ("local_service_id" "local_fn_name") () result_name))
|
||||
(call ("remote_peer_id_2" ("service_id" "fn_name") () g))
|
||||
))"#,
|
||||
(seq
|
||||
(call "remote_peer_id_1" ("local_service_id" "local_fn_name") [] result_name)
|
||||
(call "remote_peer_id_2" ("service_id" "fn_name") [] g)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(vm, "asd", script.clone(), "[]", "[]");
|
||||
@ -74,10 +69,10 @@ mod tests {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(call (%current_peer_id% ("local_service_id" "local_fn_name") () result_name))
|
||||
(call ("remote_peer_id_2" ("service_id" "fn_name") () g))
|
||||
))"#,
|
||||
(seq
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_name)
|
||||
(call "remote_peer_id_2" ("service_id" "fn_name") [] g)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(vm, "asd", script, "[]", "[]");
|
||||
|
@ -16,19 +16,14 @@
|
||||
|
||||
use super::CallEvidenceCtx;
|
||||
use super::ExecutionCtx;
|
||||
use super::Instruction;
|
||||
use crate::log_instruction;
|
||||
use crate::AquamarineError::LocalServiceError;
|
||||
use crate::Result;
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
use serde_derive::Serialize;
|
||||
use air_parser::ast::Xor;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct Xor(Box<Instruction>, Box<Instruction>);
|
||||
|
||||
impl super::ExecutableInstruction for Xor {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
impl<'i> super::ExecutableInstruction<'i> for Xor<'i> {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, call_ctx: &mut CallEvidenceCtx) -> Result<()> {
|
||||
log_instruction!(xor, exec_ctx, call_ctx);
|
||||
|
||||
exec_ctx.subtree_complete = true;
|
||||
@ -83,10 +78,10 @@ mod tests {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(xor (
|
||||
(call (%current_peer_id% ("service_id_1" "local_fn_name") () result_1))
|
||||
(call (%current_peer_id% ("service_id_2" "local_fn_name") () result_2))
|
||||
))"#,
|
||||
(xor
|
||||
(call %current_peer_id% ("service_id_1" "local_fn_name") [] result_1)
|
||||
(call %current_peer_id% ("service_id_2" "local_fn_name") [] result_2)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(vm, "asd", script, "[]", "[]");
|
||||
@ -101,10 +96,10 @@ mod tests {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(xor (
|
||||
(call (%current_peer_id% ("service_id_2" "local_fn_name") () result_1))
|
||||
(call (%current_peer_id% ("service_id_1" "local_fn_name") () result_2))
|
||||
))"#,
|
||||
(xor
|
||||
(call %current_peer_id% ("service_id_2" "local_fn_name") [] result_1)
|
||||
(call %current_peer_id% ("service_id_1" "local_fn_name") [] result_2)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(vm, "asd", script, "[]", "[]");
|
||||
|
@ -22,7 +22,6 @@ use crate::StepperOutcome;
|
||||
|
||||
use jsonpath_lib::JsonPathError;
|
||||
use serde_json::Error as SerdeJsonError;
|
||||
use serde_sexpr::Error as SExprError;
|
||||
|
||||
use std::convert::Into;
|
||||
use std::env::VarError;
|
||||
@ -30,8 +29,8 @@ use std::error::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AquamarineError {
|
||||
/// Errors occurred while parsing aqua script in the form of S expressions.
|
||||
SExprParseError(SExprError),
|
||||
/// Error occurred while parsing AIR script
|
||||
AIRParseError(String),
|
||||
|
||||
/// Errors occurred while parsing function arguments of an expression.
|
||||
FuncArgsSerializationError(JValue, SerdeJsonError),
|
||||
@ -76,7 +75,7 @@ pub enum AquamarineError {
|
||||
InvalidEvidenceState(EvidenceState, String),
|
||||
|
||||
/// Errors occurred on call evidence deserialization.
|
||||
CallEvidenceDeserializationError(SerdeJsonError),
|
||||
CallEvidenceDeserializationError(SerdeJsonError, String),
|
||||
|
||||
/// Errors occurred on call evidence serialization.
|
||||
CallEvidenceSerializationError(SerdeJsonError),
|
||||
@ -96,7 +95,7 @@ impl Error for AquamarineError {}
|
||||
impl std::fmt::Display for AquamarineError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
AquamarineError::SExprParseError(err) => write!(f, "aqua script can't be parsed: {:?}", err),
|
||||
AquamarineError::AIRParseError(err) => write!(f, "aqua script can't be parsed:\n{}", err),
|
||||
AquamarineError::FuncArgsSerializationError(args, err) => write!(
|
||||
f,
|
||||
"function arguments {} can't be serialized or deserialized with an error: {:?}",
|
||||
@ -145,9 +144,11 @@ impl std::fmt::Display for AquamarineError {
|
||||
"invalid evidence state: expected {}, but found {:?}",
|
||||
expected, found
|
||||
),
|
||||
AquamarineError::CallEvidenceDeserializationError(err) => {
|
||||
write!(f, "an error occurred while data deserialization: {:?}", err)
|
||||
}
|
||||
AquamarineError::CallEvidenceDeserializationError(err, path) => write!(
|
||||
f,
|
||||
"an error occurred while call evidence path deserialization on {:?}: {:?}",
|
||||
path, err
|
||||
),
|
||||
AquamarineError::CallEvidenceSerializationError(err) => {
|
||||
write!(f, "an error occurred while data serialization: {:?}", err)
|
||||
}
|
||||
@ -170,12 +171,6 @@ impl std::fmt::Display for AquamarineError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SExprError> for AquamarineError {
|
||||
fn from(err: SExprError) -> Self {
|
||||
AquamarineError::SExprParseError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::convert::Infallible> for AquamarineError {
|
||||
fn from(_: std::convert::Infallible) -> Self {
|
||||
unreachable!()
|
||||
@ -185,7 +180,7 @@ impl From<std::convert::Infallible> for AquamarineError {
|
||||
impl Into<StepperOutcome> for AquamarineError {
|
||||
fn into(self) -> StepperOutcome {
|
||||
let ret_code = match self {
|
||||
AquamarineError::SExprParseError(_) => 1,
|
||||
AquamarineError::AIRParseError(_) => 1,
|
||||
AquamarineError::FuncArgsSerializationError(..) => 2,
|
||||
AquamarineError::CallServiceResultDeserializationError(..) => 3,
|
||||
AquamarineError::CurrentPeerIdEnvError(..) => 4,
|
||||
|
@ -38,7 +38,7 @@ pub fn execute_aqua(init_user_id: String, aqua: String, prev_data: String, data:
|
||||
}
|
||||
|
||||
fn execute_aqua_impl(_init_user_id: String, aqua: String, prev_path: String, path: String) -> Result<StepperOutcome> {
|
||||
let (prev_path, path, aqua) = prepare(prev_path, path, aqua)?;
|
||||
let (prev_path, path, aqua) = prepare(prev_path, path, aqua.as_str())?;
|
||||
let (mut exec_ctx, mut call_ctx) = make_contexts(prev_path, path)?;
|
||||
|
||||
aqua.execute(&mut exec_ctx, &mut call_ctx)?;
|
||||
|
@ -14,9 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::utils::format_aqua;
|
||||
use crate::air::ExecutionCtx;
|
||||
use crate::air::Instruction;
|
||||
use crate::call_evidence::merge_call_paths;
|
||||
use crate::call_evidence::CallEvidenceCtx;
|
||||
use crate::get_current_peer_id;
|
||||
@ -25,19 +23,21 @@ use crate::AquamarineError;
|
||||
use crate::CallEvidencePath;
|
||||
use crate::Result;
|
||||
|
||||
use air_parser::ast::Instruction;
|
||||
|
||||
/// Parse and prepare supplied data and aqua script.
|
||||
pub(super) fn prepare(
|
||||
pub(super) fn prepare<'i>(
|
||||
raw_prev_path: String,
|
||||
raw_path: String,
|
||||
raw_aqua: String,
|
||||
) -> Result<(CallEvidencePath, CallEvidencePath, Instruction)> {
|
||||
raw_aqua: &'i str,
|
||||
) -> Result<(CallEvidencePath, CallEvidencePath, Instruction<'i>)> {
|
||||
use AquamarineError::CallEvidenceDeserializationError as CallDeError;
|
||||
|
||||
let prev_path: CallEvidencePath = serde_json::from_str(&raw_prev_path).map_err(CallDeError)?;
|
||||
let path: CallEvidencePath = serde_json::from_str(&raw_path).map_err(CallDeError)?;
|
||||
let prev_path: CallEvidencePath =
|
||||
serde_json::from_str(&raw_prev_path).map_err(|err| CallDeError(err, raw_prev_path))?;
|
||||
let path: CallEvidencePath = serde_json::from_str(&raw_path).map_err(|err| CallDeError(err, raw_path))?;
|
||||
|
||||
let formatted_aqua = format_aqua(raw_aqua);
|
||||
let aqua: Instruction = serde_sexpr::from_str(&formatted_aqua)?;
|
||||
let aqua: Instruction<'i> = *air_parser::parse(raw_aqua).map_err(|msg| AquamarineError::AIRParseError(msg))?;
|
||||
|
||||
log::info!(
|
||||
target: RUN_PARAMS,
|
||||
@ -55,7 +55,7 @@ pub(super) fn prepare(
|
||||
pub(super) fn make_contexts(
|
||||
prev_path: CallEvidencePath,
|
||||
path: CallEvidencePath,
|
||||
) -> Result<(ExecutionCtx, CallEvidenceCtx)> {
|
||||
) -> Result<(ExecutionCtx<'static>, CallEvidenceCtx)> {
|
||||
use AquamarineError::CurrentPeerIdEnvError as EnvError;
|
||||
|
||||
let current_peer_id = get_current_peer_id().map_err(|e| EnvError(e, String::from("CURRENT_PEER_ID")))?;
|
||||
|
@ -16,36 +16,6 @@
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
/// Formats aqua script in a form of S-expressions to a form compatible with the serde_sexpr crate.
|
||||
pub(super) fn format_aqua(aqua: String) -> String {
|
||||
use std::iter::FromIterator;
|
||||
|
||||
let mut formatted_aqua = Vec::with_capacity(aqua.len());
|
||||
// whether to skip the next whitespace
|
||||
let mut skip_next_whitespace = false;
|
||||
// whether c was a closing brace
|
||||
let mut was_cbr = false;
|
||||
|
||||
for c in aqua.chars() {
|
||||
let is_whitespace = c == ' ';
|
||||
if (skip_next_whitespace && is_whitespace) || c == '\n' {
|
||||
continue;
|
||||
}
|
||||
|
||||
let is_cbr = c == ')';
|
||||
|
||||
skip_next_whitespace = is_whitespace || c == '(' || is_cbr;
|
||||
if was_cbr && !is_cbr {
|
||||
formatted_aqua.push(' ');
|
||||
}
|
||||
|
||||
was_cbr = is_cbr;
|
||||
formatted_aqua.push(c)
|
||||
}
|
||||
|
||||
String::from_iter(formatted_aqua.into_iter())
|
||||
}
|
||||
|
||||
/// Deduplicate values in a supplied vector.
|
||||
pub(super) fn dedup<T: Eq + Hash>(mut vec: Vec<T>) -> Vec<T> {
|
||||
use std::collections::HashSet;
|
||||
@ -53,28 +23,3 @@ pub(super) fn dedup<T: Eq + Hash>(mut vec: Vec<T>) -> Vec<T> {
|
||||
let set: HashSet<_> = vec.drain(..).collect();
|
||||
set.into_iter().collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn format_aqua_test() {
|
||||
let aqua = format!(
|
||||
r#"(( (( (seq (
|
||||
(call (%current_peer_id% (add_module ||) (module) module))
|
||||
(seq (
|
||||
(call (%current_peer_id% (add_blueprint ||) (blueprint) blueprint_id))
|
||||
(seq (
|
||||
(call (%current_peer_id% (create ||) (blueprint_id) service_id))
|
||||
(call ({} (|| ||) (service_id) client_result))
|
||||
) )
|
||||
) )
|
||||
))"#,
|
||||
"abc"
|
||||
);
|
||||
|
||||
let aqua = super::format_aqua(aqua);
|
||||
let formatted_aqua = String::from("(((((seq ((call (%current_peer_id% (add_module ||) (module) module)) (seq ((call (%current_peer_id% (add_blueprint ||) (blueprint) blueprint_id)) (seq ((call (%current_peer_id% (create ||) (blueprint_id) service_id)) (call (abc (|| ||) (service_id) client_result))))))))");
|
||||
|
||||
assert_eq!(aqua, formatted_aqua);
|
||||
}
|
||||
}
|
||||
|
@ -54,13 +54,13 @@ use std::fmt::Formatter;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub(crate) enum AValue {
|
||||
pub(crate) enum AValue<'i> {
|
||||
JValueRef(Rc<JValue>),
|
||||
JValueAccumulatorRef(RefCell<Vec<Rc<JValue>>>),
|
||||
JValueFoldCursor(crate::air::FoldState),
|
||||
JValueFoldCursor(crate::air::FoldState<'i>),
|
||||
}
|
||||
|
||||
impl Display for AValue {
|
||||
impl<'i> Display for AValue<'i> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
AValue::JValueRef(value) => write!(f, "{:?}", value)?,
|
||||
|
@ -38,13 +38,13 @@ fn seq_par_call() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(par (
|
||||
(call (%current_peer_id% ("local_service_id" "local_fn_name") () result_1))
|
||||
(call ("remote_peer_id" ("service_id" "fn_name") () g))
|
||||
))
|
||||
(call (%current_peer_id% ("local_service_id" "local_fn_name") () result_2))
|
||||
))"#,
|
||||
(seq
|
||||
(par
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_1)
|
||||
(call "remote_peer_id" ("service_id" "fn_name") [] g)
|
||||
)
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_2)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(vm, "asd", script, "[]", "[]");
|
||||
@ -72,13 +72,13 @@ fn par_par_call() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(par (
|
||||
(par (
|
||||
(call (%current_peer_id% ("local_service_id" "local_fn_name") () result_1))
|
||||
(call ("remote_peer_id" ("service_id" "fn_name") () g))
|
||||
))
|
||||
(call (%current_peer_id% ("local_service_id" "local_fn_name") () result_2))
|
||||
))"#,
|
||||
(par
|
||||
(par
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_1)
|
||||
(call "remote_peer_id" ("service_id" "fn_name") [] g)
|
||||
)
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_2)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(vm, "asd", script, "[]", "[]");
|
||||
@ -153,25 +153,25 @@ fn create_service() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(seq (
|
||||
(seq (
|
||||
(call ("set_variables" ("" "") ("module_bytes") module_bytes))
|
||||
(call ("set_variables" ("" "") ("module_config") module_config))
|
||||
))
|
||||
(call ("set_variables" ("" "") ("blueprint") blueprint))
|
||||
))
|
||||
(seq (
|
||||
(call ("A" ("add_module" "") (module_bytes module_config) module))
|
||||
(seq (
|
||||
(call ("A" ("add_blueprint" "") (blueprint) blueprint_id))
|
||||
(seq (
|
||||
(call ("A" ("create" "") (blueprint_id) service_id))
|
||||
(call ("remote_peer_id" ("" "") (service_id) client_result))
|
||||
))
|
||||
))
|
||||
))
|
||||
))"#,
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call "set_variables" ("" "") ["module_bytes"] module_bytes)
|
||||
(call "set_variables" ("" "") ["module_config"] module_config)
|
||||
)
|
||||
(call "set_variables" ("" "") ["blueprint"] blueprint)
|
||||
)
|
||||
(seq
|
||||
(call "A" ("add_module" "") [module_bytes module_config] module)
|
||||
(seq
|
||||
(call "A" ("add_blueprint" "") [blueprint] blueprint_id)
|
||||
(seq
|
||||
(call "A" ("create" "") [blueprint_id] service_id)
|
||||
(call "remote_peer_id" ("" "") [service_id] client_result)
|
||||
)
|
||||
)
|
||||
)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(set_variables_vm, "init_user_id", script.clone(), "[]", "[]");
|
||||
|
@ -37,13 +37,13 @@ fn evidence_seq_par_call() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(par (
|
||||
(call (%current_peer_id% ("local_service_id" "local_fn_name") () result_1))
|
||||
(call ("remote_peer_id" ("service_id" "fn_name") () g))
|
||||
))
|
||||
(call (%current_peer_id% ("local_service_id" "local_fn_name") () result_2))
|
||||
))"#,
|
||||
(seq
|
||||
(par
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_1)
|
||||
(call "remote_peer_id" ("service_id" "fn_name") [] g)
|
||||
)
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_2)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let initial_state = json!([
|
||||
@ -77,13 +77,13 @@ fn evidence_par_par_call() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(par (
|
||||
(par (
|
||||
(call ("some_peer_id" ("local_service_id" "local_fn_name") () result_1))
|
||||
(call ("remote_peer_id" ("service_id" "fn_name") () g))
|
||||
))
|
||||
(call (%current_peer_id% ("local_service_id" "local_fn_name") () result_2))
|
||||
))"#,
|
||||
(par
|
||||
(par
|
||||
(call "some_peer_id" ("local_service_id" "local_fn_name") [] result_1)
|
||||
(call "remote_peer_id" ("service_id" "fn_name") [] g)
|
||||
)
|
||||
(call %current_peer_id% ("local_service_id" "local_fn_name") [] result_2)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let initial_state = json!([
|
||||
@ -122,13 +122,13 @@ fn evidence_seq_seq() {
|
||||
|
||||
let script = format!(
|
||||
r#"
|
||||
(seq (
|
||||
(call ("{}" ("identity" "") () void0))
|
||||
(seq (
|
||||
(call ("{}" ("add_blueprint" "") () blueprint_id))
|
||||
(call ("{}" ("addBlueprint-14d8488e-d10d-474d-96b2-878f6a7d74c8" "") () void1))
|
||||
))
|
||||
))
|
||||
(seq
|
||||
(call "{}" ("identity" "") [] void0)
|
||||
(seq
|
||||
(call "{}" ("add_blueprint" "") [] blueprint_id)
|
||||
(call "{}" ("addBlueprint-14d8488e-d10d-474d-96b2-878f6a7d74c8" "") [] void1)
|
||||
)
|
||||
)
|
||||
"#,
|
||||
peer_id_1, peer_id_1, peer_id_2
|
||||
);
|
||||
@ -201,25 +201,25 @@ fn evidence_create_service() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(seq (
|
||||
(seq (
|
||||
(call ("set_variables" ("add_module" "") ("module_bytes") module_bytes))
|
||||
(call ("set_variables" ("add_module" "") ("module_config") module_config))
|
||||
))
|
||||
(call ("set_variables" ("add_module" "") ("blueprint") blueprint))
|
||||
))
|
||||
(seq (
|
||||
(call ("A" ("add_module" "") (module_bytes module_config) module))
|
||||
(seq (
|
||||
(call ("A" ("add_blueprint" "") (blueprint) blueprint_id))
|
||||
(seq (
|
||||
(call ("A" ("create" "") (blueprint_id) service_id))
|
||||
(call ("remote_peer_id" ("" "") (service_id) client_result))
|
||||
))
|
||||
))
|
||||
))
|
||||
))"#,
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call "set_variables" ("add_module" "") ["module_bytes"] module_bytes)
|
||||
(call "set_variables" ("add_module" "") ["module_config"] module_config)
|
||||
)
|
||||
(call "set_variables" ("add_module" "") ["blueprint"] blueprint)
|
||||
)
|
||||
(seq
|
||||
(call "A" ("add_module" "") [module_bytes module_config] module)
|
||||
(seq
|
||||
(call "A" ("add_blueprint" "") [blueprint] blueprint_id)
|
||||
(seq
|
||||
(call "A" ("create" "") [blueprint_id] service_id)
|
||||
(call "remote_peer_id" ("" "") [service_id] client_result)
|
||||
)
|
||||
)
|
||||
)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let add_module_response = String::from("add_module response");
|
||||
@ -263,18 +263,18 @@ fn evidence_par_seq_fold_call() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(par (
|
||||
(seq (
|
||||
(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[]))
|
||||
(par
|
||||
(seq
|
||||
(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[])
|
||||
(next i)
|
||||
))
|
||||
))
|
||||
))
|
||||
(call ("some_peer_id_3" ("local_service_id" "local_fn_name") () result_2))
|
||||
))"#,
|
||||
)
|
||||
)
|
||||
)
|
||||
(call "some_peer_id_3" ("local_service_id" "local_fn_name") [] result_2)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let res = call_vm!(vm2, "asd", script.clone(), "[]", "[]");
|
||||
@ -339,18 +339,18 @@ fn evidence_par_seq_fold_in_cycle_call() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(par (
|
||||
(seq (
|
||||
(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[]))
|
||||
(par
|
||||
(seq
|
||||
(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[])
|
||||
(next i)
|
||||
))
|
||||
))
|
||||
))
|
||||
(call ("some_peer_id_3" ("local_service_id" "local_fn_name") () result_2))
|
||||
))"#,
|
||||
)
|
||||
)
|
||||
)
|
||||
(call "some_peer_id_3" ("local_service_id" "local_fn_name") [] result_2)
|
||||
)"#,
|
||||
);
|
||||
|
||||
let mut data = String::from("[]");
|
||||
@ -401,19 +401,19 @@ fn evidence_seq_par_seq_seq() {
|
||||
let mut vm2 = create_aqua_vm(unit_call_service(), peer_id_2.clone());
|
||||
let script = format!(
|
||||
r#"
|
||||
(seq (
|
||||
(par (
|
||||
(seq (
|
||||
(call ("{}" ("" "") () result_1))
|
||||
(call ("{}" ("" "") () result_2))
|
||||
))
|
||||
(seq (
|
||||
(call ("{}" ("" "") () result_3))
|
||||
(call ("{}" ("" "") () result_4))
|
||||
))
|
||||
))
|
||||
(call ("{}" ("" "") () result_5))
|
||||
))
|
||||
(seq
|
||||
(par
|
||||
(seq
|
||||
(call "{}" ("" "") [] result_1)
|
||||
(call "{}" ("" "") [] result_2)
|
||||
)
|
||||
(seq
|
||||
(call "{}" ("" "") [] result_3)
|
||||
(call "{}" ("" "") [] result_4)
|
||||
)
|
||||
)
|
||||
(call "{}" ("" "") [] result_5)
|
||||
)
|
||||
"#,
|
||||
peer_id_1, peer_id_2, peer_id_2, peer_id_1, peer_id_2
|
||||
);
|
||||
|
@ -45,29 +45,29 @@ fn data_merge() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(call (%current_peer_id% ("neighborhood" "") () neighborhood))
|
||||
(seq (
|
||||
(seq (
|
||||
(fold (neighborhood i
|
||||
(par (
|
||||
(call (i ("add_provider" "") () void[]))
|
||||
(seq
|
||||
(call %current_peer_id% ("neighborhood" "") [] neighborhood)
|
||||
(seq
|
||||
(seq
|
||||
(fold neighborhood i
|
||||
(par
|
||||
(call i ("add_provider" "") [] void[])
|
||||
(next i)
|
||||
))
|
||||
))
|
||||
(fold (neighborhood i
|
||||
(par (
|
||||
(call (i ("get_providers" "") () providers[]))
|
||||
)
|
||||
)
|
||||
(fold neighborhood i
|
||||
(par
|
||||
(call i ("get_providers" "") [] providers[])
|
||||
(next i)
|
||||
))
|
||||
))
|
||||
))
|
||||
(seq (
|
||||
(call ("A" ("identity" "") () void[]))
|
||||
(call ("B" ("" "") () none))
|
||||
))
|
||||
))
|
||||
))
|
||||
)
|
||||
)
|
||||
)
|
||||
(seq
|
||||
(call "A" ("identity" "") [] void[])
|
||||
(call "B" ("" "") [] none)
|
||||
)
|
||||
)
|
||||
)
|
||||
"#,
|
||||
);
|
||||
|
||||
@ -187,22 +187,22 @@ fn acc_merge() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(call ("A" ("add_provider" "") () void[]))
|
||||
(seq (
|
||||
(call ("A" ("add_provider" "") () void[]))
|
||||
(seq (
|
||||
(call ("A" ("get_providers" "") () providers[]))
|
||||
(seq (
|
||||
(call ("A" ("get_providers" "") () providers[]))
|
||||
(seq (
|
||||
(call ("B" ("" "2") (providers) void[]))
|
||||
(call ("B" ("" "3") (void) void[]))
|
||||
))
|
||||
))
|
||||
))
|
||||
))
|
||||
))
|
||||
(seq
|
||||
(call "A" ("add_provider" "") [] void[])
|
||||
(seq
|
||||
(call "A" ("add_provider" "") [] void[])
|
||||
(seq
|
||||
(call "A" ("get_providers" "") [] providers[])
|
||||
(seq
|
||||
(call "A" ("get_providers" "") [] providers[])
|
||||
(seq
|
||||
(call "B" ("" "2") [providers] void[])
|
||||
(call "B" ("" "3") [void] void[])
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
"#,
|
||||
);
|
||||
|
||||
|
@ -48,24 +48,24 @@ fn join_chat() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(call ("Relay1" ("identity" "") () void1[]))
|
||||
(seq (
|
||||
(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[]))
|
||||
))
|
||||
(seq
|
||||
(call "Relay1" ("identity" "") [] void1[])
|
||||
(seq
|
||||
(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[])
|
||||
)
|
||||
(next m)
|
||||
))
|
||||
))
|
||||
))
|
||||
))
|
||||
))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
"#,
|
||||
);
|
||||
|
||||
@ -202,21 +202,21 @@ fn join() {
|
||||
|
||||
let script = String::from(
|
||||
r#"
|
||||
(seq (
|
||||
(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[]))
|
||||
))
|
||||
(seq
|
||||
(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[])
|
||||
)
|
||||
(next m)
|
||||
))
|
||||
))
|
||||
))
|
||||
))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
"#,
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user