Introduce never instruction (#335)

This commit is contained in:
Mike Voronov 2022-09-19 14:36:46 +03:00 committed by GitHub
parent 250b316682
commit 20bb230a3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 955 additions and 756 deletions

View File

@ -1,3 +1,11 @@
## Version 0.29.0 (2022-09-19)
[PR 335](https://github.com/fluencelabs/aquavm/pull/335):
Introduce `never` instruction
[PR 332](https://github.com/fluencelabs/aquavm/pull/332):
Fix bug with incorrect positions in `canon` instruction
## Version 0.28.0 (2022-09-07)
[PR 314](https://github.com/fluencelabs/aquavm/pull/314):

View File

@ -28,7 +28,7 @@ AIR scripts control the Fluence peer-to-peer network, its peers and, through Mar
### What is AIR?
- S-expression-based low-level language with binary form to come
- Consists of twelve (12) instructions with more instructions to come
- Consists of fourteen (14) instructions with more instructions to come
- Semantics are inspired by [π-calculus](https://en.wikipedia.org/wiki/%CE%A0-calculus), [λ-calculus](https://en.wikipedia.org/wiki/Lambda_calculus) and [category theory](https://en.wikipedia.org/wiki/Category_theory)
- Syntax is inspired by [Wasm Text Format](https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format) (WAT) and [Lisp](https://en.wikipedia.org/wiki/Lisp_(programming_language))
@ -175,6 +175,14 @@ Example
(fail 1337 "error message")
```
#### never
```wasm
(never)
```
- marks a subgraph as incomplete, useful for code generation
#### null
```wasm

View File

@ -1,6 +1,6 @@
[package]
name = "air-interpreter"
version = "0.28.0"
version = "0.29.0"
description = "Crate-wrapper for air"
authors = ["Fluence Labs"]
edition = "2018"

View File

@ -1,6 +1,6 @@
[package]
name = "air"
version = "0.28.0"
version = "0.29.0"
description = "Interpreter of AIR scripts intended to coordinate request flow in the Fluence network"
authors = ["Fluence Labs"]
edition = "2018"

View File

@ -24,6 +24,7 @@ mod fold_scalar;
mod fold_stream;
mod match_;
mod mismatch;
mod never;
mod new;
mod next;
mod null;
@ -80,6 +81,7 @@ impl<'i> ExecutableInstruction<'i> for Instruction<'i> {
Instruction::Fail(fail) => execute!(self, fail, exec_ctx, trace_ctx),
Instruction::FoldScalar(fold) => execute!(self, fold, exec_ctx, trace_ctx),
Instruction::FoldStream(fold) => execute!(self, fold, exec_ctx, trace_ctx),
Instruction::Never(never) => execute!(self, never, exec_ctx, trace_ctx),
Instruction::New(new) => execute!(self, new, exec_ctx, trace_ctx),
Instruction::Next(next) => execute!(self, next, exec_ctx, trace_ctx),
Instruction::Null(null) => execute!(self, null, exec_ctx, trace_ctx),

View File

@ -0,0 +1,31 @@
/*
* Copyright 2022 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::ExecutionCtx;
use super::ExecutionResult;
use super::TraceHandler;
use crate::log_instruction;
use air_parser::ast::Never;
impl<'i> super::ExecutableInstruction<'i> for Never {
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
log_instruction!(null, exec_ctx, trace_ctx);
exec_ctx.subgraph_complete = false;
Ok(())
}
}

View File

@ -21,6 +21,7 @@ mod fail;
mod fold;
mod match_;
mod mismatch;
mod never;
mod new;
mod par;
mod seq;

View File

@ -0,0 +1,34 @@
/*
* 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 air_test_utils::prelude::*;
#[test]
fn never_not_complete_subgraph() {
let vm_peer_id = "test_peer_id";
let mut vm = create_avm(unit_call_service(), vm_peer_id);
let script = f!(r#"
(seq
(never)
(call "{vm_peer_id}" ("" "") [])
)
"#);
let result = checked_call_vm!(vm, <_>::default(), script, "", "");
let actual_trace = trace_from_result(&result);
assert!(actual_trace.is_empty());
}

View File

@ -37,6 +37,7 @@ pub enum Instruction<'i> {
Fail(Fail<'i>),
FoldScalar(FoldScalar<'i>),
FoldStream(FoldStream<'i>),
Never(Never),
New(New<'i>),
Next(Next<'i>),
Null(Null),
@ -137,6 +138,10 @@ pub struct Next<'i> {
pub iterator: Scalar<'i>,
}
/// (never)
#[derive(Serialize, Debug, PartialEq, Eq)]
pub struct Never;
/// (new variable instruction)
#[derive(Serialize, Debug, PartialEq)]
pub struct New<'i> {

View File

@ -34,6 +34,7 @@ impl fmt::Display for Instruction<'_> {
Fail(fail) => write!(f, "{}", fail),
FoldScalar(fold) => write!(f, "{}", fold),
FoldStream(fold) => write!(f, "{}", fold),
Never(never) => write!(f, "{}", never),
Next(next) => write!(f, "{}", next),
New(new) => write!(f, "{}", new),
Null(null) => write!(f, "{}", null),
@ -131,6 +132,12 @@ impl fmt::Display for MisMatch<'_> {
}
}
impl fmt::Display for Never {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "never")
}
}
impl fmt::Display for Next<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "next {}", self.iterator)

View File

@ -46,6 +46,7 @@ Instr: Box<Instruction<'input>> = {
"(" seq <l:Instr> <r:Instr> ")" => Box::new(Instruction::Seq(Seq::new(l, r))),
"(" par <l:Instr> <r:Instr> ")" => Box::new(Instruction::Par(Par::new(l, r))),
"(" never ")" => Box::new(Instruction::Never(Never)),
"(" null ")" => Box::new(Instruction::Null(Null)),
<left: @L> "(" new <argument: NewArgument> <instruction:Instr> ")" <right: @R> => {
@ -264,6 +265,7 @@ extern {
fail => Token::Fail,
fold => Token::Fold,
xor => Token::Xor,
never => Token::Never,
new => Token::New,
next => Token::Next,
null => Token::Null,

File diff suppressed because it is too large Load Diff

View File

@ -183,6 +183,7 @@ fn string_to_token(input: &str, start_pos: usize) -> LexerResult<Token> {
FAIL_INSTR => Ok(Token::Fail),
FOLD_INSTR => Ok(Token::Fold),
XOR_INSTR => Ok(Token::Xor),
NEVER_INSTR => Ok(Token::Never),
NEW_INSTR => Ok(Token::New),
NEXT_INSTR => Ok(Token::Next),
NULL_INSTR => Ok(Token::Null),
@ -233,6 +234,7 @@ const PAR_INSTR: &str = "par";
const FAIL_INSTR: &str = "fail";
const FOLD_INSTR: &str = "fold";
const XOR_INSTR: &str = "xor";
const NEVER_INSTR: &str = "never";
const NEW_INSTR: &str = "new";
const NEXT_INSTR: &str = "next";
const NULL_INSTR: &str = "null";

View File

@ -74,6 +74,7 @@ pub enum Token<'input> {
Fail,
Fold,
Xor,
Never,
New,
Next,
Null,

View File

@ -65,6 +65,10 @@ pub(super) fn new<'i>(
})
}
pub(super) fn never() -> Instruction<'static> {
Instruction::Never(Never)
}
pub(super) fn null() -> Instruction<'static> {
Instruction::Null(Null)
}

View File

@ -21,6 +21,7 @@ mod dsl;
mod fail;
mod fold;
mod match_;
mod never;
mod new;
mod null;
mod par;

View File

@ -0,0 +1,32 @@
/*
* Copyright 2022 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::dsl::*;
use super::parse;
#[test]
fn parse_null() {
let source_code = r#"
(seq
(never)
( never )
)
"#;
let instruction = parse(source_code);
let expected = seq(never(), never());
assert_eq!(instruction, expected)
}

View File

@ -138,6 +138,7 @@ impl<W: io::Write> Beautifier<W> {
ast::Instruction::FoldStream(fold_stream) => {
self.beautify_fold_stream(fold_stream, indent)
}
ast::Instruction::Never(never) => self.beautify_simple(never, indent),
ast::Instruction::New(new) => self.beautify_new(new, indent),
ast::Instruction::Next(next) => self.beautify_simple(next, indent),
ast::Instruction::Null(null) => self.beautify_simple(null, indent),