use num_bigint::BigInt;
use super::super::{
DecimalNumberExpressionStruct, FunctionCallExpressionStruct, HexNumberExpressionStruct,
StringExpression,
};
use crate::backend::binder::Typing;
use crate::backend::ir::ir2_flat_contracts as input_ir;
use crate::backend::types::ConstantValue;
impl StringExpression {
pub fn value(&self) -> Vec<u8> {
let (terminals, prefix) = match self {
StringExpression::Strings(terminals) => (terminals, ""),
StringExpression::HexStrings(terminals) => (terminals, "hex"),
StringExpression::UnicodeStrings(terminals) => (terminals, "unicode"),
};
let total_len: usize = terminals
.iter()
.map(|terminal| terminal.text.len().saturating_sub(prefix.len() + 2))
.sum();
let mut result = Vec::with_capacity(total_len);
for terminal in terminals {
let content = Self::strip_quotes(&terminal.text, prefix);
if prefix == "hex" {
result.extend(
(0..content.len())
.step_by(2)
.map(|i| u8::from_str_radix(&content[i..i + 2], 16).unwrap()),
);
} else {
result.extend_from_slice(content.as_bytes());
}
}
result
}
pub fn strip_quotes<'a>(text: &'a str, prefix: &str) -> &'a str {
text.strip_prefix(prefix)
.and_then(|stripped| {
stripped
.strip_prefix('"')
.and_then(|s| s.strip_suffix('"'))
.or_else(|| {
stripped
.strip_prefix('\'')
.and_then(|s| s.strip_suffix('\''))
})
})
.unwrap_or(text)
}
}
impl DecimalNumberExpressionStruct {
pub fn integer_value(&self) -> Option<BigInt> {
ConstantValue::from_decimal_number(&self.ir_node)
.map(|ConstantValue::Integer(integer)| integer)
}
}
impl HexNumberExpressionStruct {
pub fn integer_value(&self) -> Option<BigInt> {
ConstantValue::from_hex_number(&self.ir_node).map(|ConstantValue::Integer(integer)| integer)
}
}
impl FunctionCallExpressionStruct {
pub fn is_type_conversion(&self) -> bool {
match &self.ir_node.operand {
input_ir::Expression::ElementaryType(_) | input_ir::Expression::PayableKeyword => true,
input_ir::Expression::Identifier(terminal) => matches!(
self.semantic.binder.node_typing(terminal.id()),
Typing::MetaType(_) | Typing::UserMetaType(_)
),
input_ir::Expression::MemberAccessExpression(mae) => matches!(
self.semantic.binder.node_typing(mae.node_id),
Typing::MetaType(_) | Typing::UserMetaType(_)
),
_ => false,
}
}
}