use crate::IntegerType;
use super::*;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub struct Literal {
pub span: Span,
pub id: NodeID,
pub variant: LiteralVariant,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
pub enum LiteralVariant {
Address(String),
Boolean(bool),
Field(String),
Group(String),
Integer(IntegerType, String),
None,
Identifier(String),
Scalar(String),
Signature(String),
String(String),
Unsuffixed(String),
}
impl fmt::Display for LiteralVariant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
Self::Address(address) => write!(f, "{address}"),
Self::Boolean(boolean) => write!(f, "{boolean}"),
Self::Field(field) => write!(f, "{field}field"),
Self::Group(group) => write!(f, "{group}group"),
Self::Integer(type_, value) => write!(f, "{value}{type_}"),
Self::None => write!(f, "none"),
Self::Identifier(string) => write!(f, "'{string}'"),
Self::Scalar(scalar) => write!(f, "{scalar}scalar"),
Self::Signature(signature) => write!(f, "{signature}"),
Self::String(string) => write!(f, "\"{string}\""),
Self::Unsuffixed(value) => write!(f, "{value}"),
}
}
}
impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.variant.fmt(f)
}
}
crate::simple_node_impl!(Literal);
impl Literal {
pub fn address(s: String, span: Span, id: NodeID) -> Self {
Literal { variant: LiteralVariant::Address(s), span, id }
}
pub fn boolean(s: bool, span: Span, id: NodeID) -> Self {
Literal { variant: LiteralVariant::Boolean(s), span, id }
}
pub fn field(s: String, span: Span, id: NodeID) -> Self {
Literal { variant: LiteralVariant::Field(s), span, id }
}
pub fn group(s: String, span: Span, id: NodeID) -> Self {
Literal { variant: LiteralVariant::Group(s), span, id }
}
pub fn integer(integer_type: IntegerType, s: String, span: Span, id: NodeID) -> Self {
Literal { variant: LiteralVariant::Integer(integer_type, s), span, id }
}
pub fn none(span: Span, id: NodeID) -> Self {
Literal { variant: LiteralVariant::None, span, id }
}
pub fn identifier(s: String, span: Span, id: NodeID) -> Self {
Literal { variant: LiteralVariant::Identifier(s), span, id }
}
pub fn scalar(s: String, span: Span, id: NodeID) -> Self {
Literal { variant: LiteralVariant::Scalar(s), span, id }
}
pub fn signature(s: String, span: Span, id: NodeID) -> Self {
Literal { variant: LiteralVariant::Signature(s), span, id }
}
pub fn string(s: String, span: Span, id: NodeID) -> Self {
Literal { variant: LiteralVariant::String(s), span, id }
}
pub fn unsuffixed(s: String, span: Span, id: NodeID) -> Self {
Literal { variant: LiteralVariant::Unsuffixed(s), span, id }
}
pub fn as_u32(&self) -> Option<u32> {
if let LiteralVariant::Integer(_, s) = &self.variant {
u32::from_str_by_radix(&s.replace("_", "")).ok()
} else {
None
}
}
}
impl From<Literal> for Expression {
fn from(value: Literal) -> Self {
Expression::Literal(value)
}
}
pub trait FromStrRadix: Sized {
fn from_str_by_radix(src: &str) -> Result<Self, std::num::ParseIntError>;
}
macro_rules! implement_from_str_radix {
($($ty:ident)*) => {
$(
impl FromStrRadix for $ty {
fn from_str_by_radix(src: &str) -> Result<Self, std::num::ParseIntError> {
if let Some(stripped) = src.strip_prefix("0x") {
Self::from_str_radix(stripped, 16)
} else if let Some(stripped) = src.strip_prefix("0o") {
Self::from_str_radix(stripped, 8)
} else if let Some(stripped) = src.strip_prefix("0b") {
Self::from_str_radix(stripped, 2)
} else if let Some(stripped) = src.strip_prefix("-0x") {
let mut s = String::new();
s.push('-');
s.push_str(stripped);
Self::from_str_radix(&s, 16)
} else if let Some(stripped) = src.strip_prefix("-0o") {
let mut s = String::new();
s.push('-');
s.push_str(stripped);
Self::from_str_radix(&s, 8)
} else if let Some(stripped) = src.strip_prefix("-0b") {
let mut s = String::new();
s.push('-');
s.push_str(stripped);
Self::from_str_radix(&s, 2)
} else {
Self::from_str_radix(src, 10)
}
}
}
)*
};
}
implement_from_str_radix! { u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 }