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}