neo-devpack-solidity 0.22.0

Production-focused Solidity-to-NeoVM compilation system
Documentation
use super::*;

impl ExecutionContext {
    pub(crate) fn sign_stack_item(&self, value: StackItem) -> Result<i64, RuntimeError> {
        match value {
            StackItem::Integer(v) => Ok(v.signum()),
            StackItem::UnsignedInteger(v) => Ok(if v == 0 { 0 } else { 1 }),
            StackItem::Boolean(b) => Ok(if b { 1 } else { 0 }),
            _ => Err(RuntimeError::ExecutionError {
                message: "Invalid operand for SIGN".to_string(),
            }),
        }
    }

    pub(crate) fn abs_stack_item(&self, value: StackItem) -> Result<StackItem, RuntimeError> {
        match value {
            StackItem::Integer(v) => {
                v.checked_abs()
                    .map(StackItem::Integer)
                    .ok_or(RuntimeError::ExecutionError {
                        message: "ABS overflow".to_string(),
                    })
            }
            StackItem::UnsignedInteger(v) => Ok(StackItem::UnsignedInteger(v)),
            _ => Err(RuntimeError::ExecutionError {
                message: "Invalid operand for ABS".to_string(),
            }),
        }
    }

    pub(crate) fn negate_stack_item(&self, value: StackItem) -> Result<StackItem, RuntimeError> {
        match value {
            StackItem::Integer(v) => {
                v.checked_neg()
                    .map(StackItem::Integer)
                    .ok_or(RuntimeError::ExecutionError {
                        message: "NEGATE overflow: cannot negate i64::MIN".to_string(),
                    })
            }
            StackItem::UnsignedInteger(v) => {
                if v <= i64::MAX as u64 {
                    Ok(StackItem::Integer(-(v as i64)))
                } else {
                    Err(RuntimeError::ExecutionError {
                        message: "NEGATE overflow for unsigned value".to_string(),
                    })
                }
            }
            _ => Err(RuntimeError::ExecutionError {
                message: "Invalid operand for NEGATE".to_string(),
            }),
        }
    }

    pub(crate) fn inc_stack_item(&self, value: StackItem) -> Result<StackItem, RuntimeError> {
        match value {
            StackItem::Integer(v) => {
                if self.strict_arithmetic {
                    v.checked_add(1)
                        .map(StackItem::Integer)
                        .ok_or(RuntimeError::ExecutionError {
                            message: format!("Integer overflow in INC: {v}"),
                        })
                } else {
                    Ok(StackItem::Integer(v.wrapping_add(1)))
                }
            }
            StackItem::UnsignedInteger(v) => {
                if self.strict_arithmetic {
                    v.checked_add(1).map(StackItem::UnsignedInteger).ok_or(
                        RuntimeError::ExecutionError {
                            message: format!("Unsigned integer overflow in INC: {v}"),
                        },
                    )
                } else {
                    Ok(StackItem::UnsignedInteger(v.wrapping_add(1)))
                }
            }
            _ => Err(RuntimeError::ExecutionError {
                message: "Invalid operand for INC".to_string(),
            }),
        }
    }

    pub(crate) fn dec_stack_item(&self, value: StackItem) -> Result<StackItem, RuntimeError> {
        match value {
            StackItem::Integer(v) => {
                if self.strict_arithmetic {
                    v.checked_sub(1)
                        .map(StackItem::Integer)
                        .ok_or(RuntimeError::ExecutionError {
                            message: format!("Integer underflow in DEC: {v}"),
                        })
                } else {
                    Ok(StackItem::Integer(v.wrapping_sub(1)))
                }
            }
            StackItem::UnsignedInteger(v) => {
                if self.strict_arithmetic {
                    v.checked_sub(1).map(StackItem::UnsignedInteger).ok_or(
                        RuntimeError::ExecutionError {
                            message: format!("Unsigned integer underflow in DEC: {v}"),
                        },
                    )
                } else {
                    Ok(StackItem::UnsignedInteger(v.wrapping_sub(1)))
                }
            }
            _ => Err(RuntimeError::ExecutionError {
                message: "Invalid operand for DEC".to_string(),
            }),
        }
    }
}