aquavm/air/src/execution_step/errors/catchable_errors.rs

155 lines
5.6 KiB
Rust
Raw Normal View History

2021-01-15 00:38:58 +03:00
/*
* 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.
*/
2021-12-28 16:59:55 +03:00
use super::Joinable;
use super::LastErrorAffectable;
2021-08-24 16:14:15 +03:00
use super::Stream;
2021-12-29 19:51:18 +03:00
use crate::execution_step::execution_context::LastErrorObjectError;
use crate::execution_step::lambda_applier::LambdaError;
2021-01-15 00:38:58 +03:00
use crate::JValue;
2021-12-17 22:02:16 +03:00
use crate::ToErrorCode;
2021-01-15 00:38:58 +03:00
use strum::IntoEnumIterator;
use strum_macros::EnumDiscriminants;
use strum_macros::EnumIter;
2021-01-15 00:38:58 +03:00
use thiserror::Error as ThisError;
2021-02-11 15:39:37 +03:00
use std::rc::Rc;
2021-12-21 11:37:35 +03:00
/// Catchable errors arisen during AIR script execution. Catchable here means that these errors
/// could be handled by a xor instruction and their error_code could be used in a match
/// instruction.
#[derive(ThisError, EnumDiscriminants, Debug)]
#[strum_discriminants(derive(EnumIter))]
2021-12-21 11:37:35 +03:00
pub enum CatchableError {
2021-01-15 00:38:58 +03:00
/// An error is occurred while calling local service via call_service.
#[error("Local service error, ret_code is {0}, error message is '{1}'")]
2021-02-11 15:39:37 +03:00
LocalServiceError(i32, Rc<String>),
2021-01-15 00:38:58 +03:00
/// Variable with such a name wasn't defined during AIR script execution.
2021-12-21 11:37:35 +03:00
/// This error type is used in order to support the join behaviour and
/// it's ok if some variable hasn't been defined yet, due to the par nature of AIR.
#[error("variable with name '{0}' wasn't defined during script execution")]
2021-01-15 00:38:58 +03:00
VariableNotFound(String),
/// Provided JValue has incompatible type with a requested one.
#[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,
},
2021-01-15 00:38:58 +03:00
/// A fold instruction must iterate over array value.
#[error("lambda '{1}' returned non-array value '{0}' for fold instruction")]
FoldIteratesOverNonArray(JValue, String),
2021-01-27 00:37:58 +03:00
/// This error type is produced by a match to notify xor that compared values aren't equal.
#[error("match is used without corresponding xor")]
2021-12-28 16:59:55 +03:00
MatchValuesNotEqual,
2021-02-11 15:39:37 +03:00
/// This error type is produced by a mismatch to notify xor that compared values aren't equal.
#[error("mismatch is used without corresponding xor")]
2021-12-28 16:59:55 +03:00
MismatchValuesEqual,
2021-02-18 17:30:14 +03:00
2021-12-16 21:34:27 +03:00
/// This error type is produced by a fail instruction.
2021-12-28 16:59:55 +03:00
#[error("fail with '{error}' is used without corresponding xor")]
UserError { error: Rc<JValue> },
2021-12-16 21:34:27 +03:00
2021-12-21 11:37:35 +03:00
/// An error occurred while trying to apply lambda to a value.
#[error(transparent)]
2021-12-21 11:37:35 +03:00
LambdaApplierError(#[from] LambdaError),
2021-08-24 16:14:15 +03:00
/// Errors occurred while insertion of a value inside stream that doesn't have corresponding generation.
#[error("stream {0:?} doesn't have generation with number {1}, probably a supplied to the interpreter data is corrupted")]
StreamDontHaveSuchGeneration(Stream, usize),
2021-12-29 19:51:18 +03:00
/// This error type is produced by a fail instruction that tries to throw a scalar that have inappropriate type.
#[error(transparent)]
InvalidLastErrorObjectError(#[from] LastErrorObjectError),
/// A new with this variable name was met and right after that it was accessed
/// that is prohibited.
#[error("variable with name '{0}' was cleared by new and then wasn't set")]
VariableWasNotInitializedAfterNew(String),
2022-08-26 00:43:43 +03:00
/// Canon instruction can't canonicalize a stream since it's been found.
#[error("stream with name {0} wasn't defined, so canon instruction can't canonicalize it")]
StreamsForCanonNotFound(String),
2021-08-24 16:14:15 +03:00
}
2021-12-21 11:37:35 +03:00
impl From<LambdaError> for Rc<CatchableError> {
fn from(e: LambdaError) -> Self {
2021-12-21 11:37:35 +03:00
Rc::new(CatchableError::LambdaApplierError(e))
}
}
2021-12-21 11:37:35 +03:00
impl ToErrorCode for Rc<CatchableError> {
2021-12-17 22:02:16 +03:00
fn to_error_code(&self) -> i64 {
2021-12-21 11:37:35 +03:00
self.as_ref().to_error_code()
2021-12-17 22:02:16 +03:00
}
}
2021-12-21 11:37:35 +03:00
impl ToErrorCode for CatchableError {
2021-12-17 22:02:16 +03:00
fn to_error_code(&self) -> i64 {
2021-12-21 11:37:35 +03:00
use crate::utils::CATCHABLE_ERRORS_START_ID;
crate::generate_to_error_code!(self, CatchableError, CATCHABLE_ERRORS_START_ID)
2021-01-15 00:38:58 +03:00
}
}
2021-12-28 16:59:55 +03:00
impl LastErrorAffectable for CatchableError {
fn affects_last_error(&self) -> bool {
!matches!(
self,
CatchableError::MatchValuesNotEqual | CatchableError::MismatchValuesEqual
)
}
}
macro_rules! log_join {
($($args:tt)*) => {
log::info!(target: air_log_targets::JOIN_BEHAVIOUR, $($args)*)
}
}
#[rustfmt::skip::macros(log_join)]
2021-12-21 11:37:35 +03:00
impl Joinable for CatchableError {
/// Returns true, if supplied error is related to variable not found errors type.
/// Print log if this is joinable error type.
fn is_joinable(&self) -> bool {
2021-12-21 11:37:35 +03:00
use CatchableError::*;
match self {
VariableNotFound(var_name) => {
log_join!(" waiting for an argument with name '{}'", var_name);
true
}
LambdaApplierError(LambdaError::StreamNotHaveEnoughValues { stream_size, idx }) => {
log_join!(" waiting for an argument with idx '{}' on stream with size '{}'", idx, stream_size);
true
}
2021-12-17 22:02:16 +03:00
LambdaApplierError(LambdaError::EmptyStream) => {
log_join!(" waiting on empty stream for path ");
true
}
2021-08-24 16:14:15 +03:00
_ => false,
}
}
}