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