sway_core/language/
literal.rs

1use crate::{type_system::*, Engines};
2use serde::{Deserialize, Serialize};
3use std::{
4    fmt,
5    hash::{Hash, Hasher},
6    num::{IntErrorKind, ParseIntError},
7};
8use sway_error::error::CompileError;
9use sway_types::{integer_bits::IntegerBits, span, u256::U256};
10
11#[derive(Debug, Clone, Eq, Serialize, Deserialize)]
12pub enum Literal {
13    U8(u8),
14    U16(u16),
15    U32(u32),
16    U64(u64),
17    U256(U256),
18    String(span::Span),
19    Numeric(u64),
20    Boolean(bool),
21    B256([u8; 32]),
22    Binary(Vec<u8>),
23}
24
25impl Literal {
26    pub fn cast_value_to_u64(&self) -> Option<u64> {
27        match self {
28            Literal::U8(v) => Some(*v as u64),
29            Literal::U16(v) => Some(*v as u64),
30            Literal::U32(v) => Some(*v as u64),
31            Literal::U64(v) => Some(*v),
32            Literal::Numeric(v) => Some(*v),
33            _ => None,
34        }
35    }
36}
37
38impl Hash for Literal {
39    fn hash<H: Hasher>(&self, state: &mut H) {
40        use Literal::*;
41        match self {
42            U8(x) => {
43                state.write_u8(1);
44                x.hash(state);
45            }
46            U16(x) => {
47                state.write_u8(2);
48                x.hash(state);
49            }
50            U32(x) => {
51                state.write_u8(3);
52                x.hash(state);
53            }
54            U64(x) => {
55                state.write_u8(4);
56                x.hash(state);
57            }
58            U256(x) => {
59                state.write_u8(4);
60                x.hash(state);
61            }
62            Numeric(x) => {
63                state.write_u8(5);
64                x.hash(state);
65            }
66            String(inner) => {
67                state.write_u8(6);
68                inner.as_str().hash(state);
69            }
70            Boolean(x) => {
71                state.write_u8(7);
72                x.hash(state);
73            }
74            B256(x) => {
75                state.write_u8(8);
76                x.hash(state);
77            }
78            Binary(x) => {
79                state.write_u8(9);
80                x.hash(state);
81            }
82        }
83    }
84}
85
86impl PartialEq for Literal {
87    fn eq(&self, other: &Self) -> bool {
88        match (self, other) {
89            (Self::U8(l0), Self::U8(r0)) => l0 == r0,
90            (Self::U16(l0), Self::U16(r0)) => l0 == r0,
91            (Self::U32(l0), Self::U32(r0)) => l0 == r0,
92            (Self::U64(l0), Self::U64(r0)) => l0 == r0,
93            (Self::U256(l0), Self::U256(r0)) => l0 == r0,
94            (Self::String(l0), Self::String(r0)) => *l0.as_str() == *r0.as_str(),
95            (Self::Numeric(l0), Self::Numeric(r0)) => l0 == r0,
96            (Self::Boolean(l0), Self::Boolean(r0)) => l0 == r0,
97            (Self::B256(l0), Self::B256(r0)) => l0 == r0,
98            (Self::Binary(l0), Self::Binary(r0)) => l0 == r0,
99            _ => false,
100        }
101    }
102}
103
104impl fmt::Display for Literal {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        let s = match self {
107            Literal::U8(content) => content.to_string(),
108            Literal::U16(content) => content.to_string(),
109            Literal::U32(content) => content.to_string(),
110            Literal::U64(content) => content.to_string(),
111            Literal::U256(content) => content.to_string(),
112            Literal::Numeric(content) => content.to_string(),
113            Literal::String(content) => content.as_str().to_string(),
114            Literal::Boolean(content) => content.to_string(),
115            Literal::B256(content) => content
116                .iter()
117                .map(|x| x.to_string())
118                .collect::<Vec<_>>()
119                .join(", "),
120            Literal::Binary(content) => content
121                .iter()
122                .map(|x| x.to_string())
123                .collect::<Vec<_>>()
124                .join(", "),
125        };
126        write!(f, "{s}")
127    }
128}
129
130impl Literal {
131    #[allow(clippy::wildcard_in_or_patterns)]
132    pub(crate) fn handle_parse_int_error(
133        engines: &Engines,
134        e: ParseIntError,
135        ty: TypeInfo,
136        span: sway_types::Span,
137    ) -> CompileError {
138        match e.kind() {
139            IntErrorKind::PosOverflow => CompileError::IntegerTooLarge {
140                ty: engines.help_out(ty).to_string(),
141                span,
142            },
143            IntErrorKind::NegOverflow => CompileError::IntegerTooSmall {
144                ty: engines.help_out(ty).to_string(),
145                span,
146            },
147            IntErrorKind::InvalidDigit => CompileError::IntegerContainsInvalidDigit {
148                ty: engines.help_out(ty).to_string(),
149                span,
150            },
151            IntErrorKind::Zero | IntErrorKind::Empty | _ => {
152                CompileError::Internal("Called incorrect internal sway-core on literal type.", span)
153            }
154        }
155    }
156
157    pub(crate) fn to_typeinfo(&self) -> TypeInfo {
158        match self {
159            Literal::String(_) => TypeInfo::StringSlice,
160            Literal::Numeric(_) => TypeInfo::Numeric,
161            Literal::U8(_) => TypeInfo::UnsignedInteger(IntegerBits::Eight),
162            Literal::U16(_) => TypeInfo::UnsignedInteger(IntegerBits::Sixteen),
163            Literal::U32(_) => TypeInfo::UnsignedInteger(IntegerBits::ThirtyTwo),
164            Literal::U64(_) => TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
165            Literal::U256(_) => TypeInfo::UnsignedInteger(IntegerBits::V256),
166            Literal::Boolean(_) => TypeInfo::Boolean,
167            Literal::B256(_) => TypeInfo::B256,
168            Literal::Binary(_) => TypeInfo::RawUntypedSlice,
169        }
170    }
171}