mirror of
https://github.com/fluencelabs/aquavm
synced 2025-03-15 12:30:50 +00:00
Add variables names in resolve errors (#194)
This commit is contained in:
parent
1d8182d497
commit
5ef8bfc940
@ -20,13 +20,12 @@ use super::ExecutionResult;
|
||||
use crate::exec_err;
|
||||
use crate::JValue;
|
||||
|
||||
use air_parser::ast::CallInstrValue;
|
||||
use air_parser::ast::Triplet;
|
||||
use air_parser::ast;
|
||||
use polyplets::ResolvedTriplet;
|
||||
|
||||
/// Resolve variables, literals, etc in the `Triplet`, and build a `ResolvedTriplet`.
|
||||
pub(crate) fn resolve<'i>(triplet: &Triplet<'i>, ctx: &ExecutionCtx<'i>) -> ExecutionResult<ResolvedTriplet> {
|
||||
let Triplet {
|
||||
pub(crate) fn resolve<'i>(triplet: &ast::Triplet<'i>, ctx: &ExecutionCtx<'i>) -> ExecutionResult<ResolvedTriplet> {
|
||||
let ast::Triplet {
|
||||
peer_pk,
|
||||
service_id,
|
||||
function_name,
|
||||
@ -45,26 +44,29 @@ pub(crate) fn resolve<'i>(triplet: &Triplet<'i>, ctx: &ExecutionCtx<'i>) -> Exec
|
||||
|
||||
/// Resolve value to string by either resolving variable from `ExecutionCtx`, taking literal value, or etc.
|
||||
// TODO: return Rc<String> to avoid excess cloning
|
||||
fn resolve_to_string<'i>(value: &CallInstrValue<'i>, ctx: &ExecutionCtx<'i>) -> ExecutionResult<String> {
|
||||
fn resolve_to_string<'i>(value: &ast::CallInstrValue<'i>, ctx: &ExecutionCtx<'i>) -> ExecutionResult<String> {
|
||||
use crate::execution_step::utils::resolve_ast_variable_wl;
|
||||
use ast::CallInstrValue::*;
|
||||
|
||||
let resolved = match value {
|
||||
CallInstrValue::InitPeerId => ctx.init_peer_id.clone(),
|
||||
CallInstrValue::Literal(value) => value.to_string(),
|
||||
CallInstrValue::Variable(variable) => {
|
||||
InitPeerId => ctx.init_peer_id.clone(),
|
||||
Literal(value) => value.to_string(),
|
||||
Variable(variable) => {
|
||||
let (resolved, _) = resolve_ast_variable_wl(variable, ctx)?;
|
||||
jvalue_to_string(resolved)?
|
||||
try_jvalue_to_string(resolved, variable)?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(resolved)
|
||||
}
|
||||
|
||||
fn jvalue_to_string(jvalue: JValue) -> ExecutionResult<String> {
|
||||
use ExecutionError::IncompatibleJValueType;
|
||||
|
||||
fn try_jvalue_to_string(jvalue: JValue, variable: &ast::VariableWithLambda<'_>) -> ExecutionResult<String> {
|
||||
match jvalue {
|
||||
JValue::String(s) => Ok(s),
|
||||
_ => exec_err!(IncompatibleJValueType(jvalue, "string")),
|
||||
_ => exec_err!(ExecutionError::IncompatibleJValueType {
|
||||
variable_name: variable.name().to_string(),
|
||||
actual_value: jvalue,
|
||||
expected_value_type: "string",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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::ExecutionCtx;
|
||||
use super::ExecutionResult;
|
||||
use super::ExecutionError;
|
||||
use super::TraceHandler;
|
||||
use crate::log_instruction;
|
||||
|
||||
use air_parser::ast::Null;
|
||||
|
||||
impl<'i> super::ExecutableInstruction<'i> for Fail {
|
||||
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
|
||||
log_instruction!(null, exec_ctx, trace_ctx);
|
||||
|
||||
Err(ExecutionError::FailMet {
|
||||
message: self.message.to_string()
|
||||
})
|
||||
}
|
||||
}
|
@ -87,19 +87,17 @@ fn create_scalar_iterable<'ctx>(
|
||||
variable_name: &str,
|
||||
) -> ExecutionResult<FoldIterableScalar> {
|
||||
match exec_ctx.scalars.get(variable_name)? {
|
||||
ScalarRef::Value(call_result) => from_call_result(call_result.clone()),
|
||||
ScalarRef::Value(call_result) => from_call_result(call_result.clone(), variable_name),
|
||||
ScalarRef::IterableValue(fold_state) => {
|
||||
let iterable_value = fold_state.iterable.peek().unwrap();
|
||||
let call_result = iterable_value.into_resolved_result();
|
||||
from_call_result(call_result)
|
||||
from_call_result(call_result, variable_name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs iterable value from resolved call result.
|
||||
fn from_call_result(call_result: ValueAggregate) -> ExecutionResult<FoldIterableScalar> {
|
||||
use ExecutionError::IncompatibleJValueType;
|
||||
|
||||
fn from_call_result(call_result: ValueAggregate, variable_name: &str) -> ExecutionResult<FoldIterableScalar> {
|
||||
let len = match &call_result.result.deref() {
|
||||
JValue::Array(array) => {
|
||||
if array.is_empty() {
|
||||
@ -108,7 +106,13 @@ fn from_call_result(call_result: ValueAggregate) -> ExecutionResult<FoldIterable
|
||||
}
|
||||
array.len()
|
||||
}
|
||||
v => return exec_err!(IncompatibleJValueType((*v).clone(), "array")),
|
||||
v => {
|
||||
return exec_err!(ExecutionError::IncompatibleJValueType {
|
||||
variable_name: variable_name.to_string(),
|
||||
actual_value: (*v).clone(),
|
||||
expected_value_type: "array",
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let foldable = IterableResolvedCall::init(call_result, len);
|
||||
|
@ -59,8 +59,14 @@ pub(crate) enum ExecutionError {
|
||||
EmptyStreamLambdaError,
|
||||
|
||||
/// Provided JValue has incompatible type with a requested one.
|
||||
#[error("expected JValue type '{1}', but got '{0}' JValue")]
|
||||
IncompatibleJValueType(JValue, &'static str),
|
||||
#[error(
|
||||
"expected JValue type '{expected_value_type}' for the variable `{variable_name}`, but got '{actual_value}'"
|
||||
)]
|
||||
IncompatibleJValueType {
|
||||
variable_name: String,
|
||||
actual_value: JValue,
|
||||
expected_value_type: &'static str,
|
||||
},
|
||||
|
||||
/// Fold state wasn't found for such iterator name.
|
||||
#[error("fold state not found for this iterable '{0}'")]
|
||||
|
@ -18,6 +18,9 @@ use air::LastError;
|
||||
use air::SecurityTetraplet;
|
||||
use air_test_utils::prelude::*;
|
||||
|
||||
use fstrings::f;
|
||||
use fstrings::format_args_f;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -193,3 +196,33 @@ fn track_current_peer_id() {
|
||||
let actual_value = (*args.borrow()).as_ref().unwrap().clone();
|
||||
assert_eq!(actual_value.peer_id, fallible_peer_id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variable_names_shown_in_error() {
|
||||
let set_variable_vm_peer_id = "set_variable_vm_peer_id";
|
||||
let mut set_variable_vm = create_avm(set_variable_call_service(json!(1u32)), set_variable_vm_peer_id);
|
||||
|
||||
let echo_vm_peer_id = "echo_vm_peer_id";
|
||||
let mut echo_vm = create_avm(echo_call_service(), echo_vm_peer_id);
|
||||
|
||||
let script = f!(r#"
|
||||
(xor
|
||||
(seq
|
||||
(call "{set_variable_vm_peer_id}" ("" "") [""] -relay-)
|
||||
(call -relay- ("" "") [])
|
||||
)
|
||||
(call "{echo_vm_peer_id}" ("" "") [%last_error%.$.msg])
|
||||
)
|
||||
"#);
|
||||
|
||||
let result = checked_call_vm!(set_variable_vm, "", &script, "", "");
|
||||
let result = checked_call_vm!(echo_vm, "", script, "", result.data);
|
||||
let trace = trace_from_result(&result);
|
||||
|
||||
assert_eq!(
|
||||
trace[1],
|
||||
executed_state::scalar(json!(
|
||||
"expected JValue type 'string' for variable `-relay-`, but got '1'"
|
||||
))
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user