1use crate::{FromStrRadix as _, Identifier, IntegerType, Literal, LiteralVariant, Type};
18
19use leo_errors::{FlattenError, LeoError, Result};
20use leo_span::{Span, Symbol};
21
22use indexmap::IndexMap;
23use std::{fmt::Display, num::ParseIntError};
24
25#[derive(Clone, Debug, Eq, PartialEq)]
26pub enum Value {
27 Address(String, Span),
28 Boolean(bool, Span),
29 Struct(Identifier, IndexMap<Symbol, Value>),
30 Field(String, Span),
31 Group(String, Span),
32 I8(i8, Span),
33 I16(i16, Span),
34 I32(i32, Span),
35 I64(i64, Span),
36 I128(i128, Span),
37 U8(u8, Span),
38 U16(u16, Span),
39 U32(u32, Span),
40 U64(u64, Span),
41 U128(u128, Span),
42 Scalar(String, Span),
43 Unsuffixed(String, Span),
44 String(String, Span),
45}
46
47impl Display for Value {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 use Value::*;
50 match self {
51 Address(val, _) => write!(f, "{val}"),
52 Struct(val, _) => write!(f, "{}", val.name),
53 Boolean(val, _) => write!(f, "{val}"),
54 Field(val, _) => write!(f, "{val}"),
55 Group(val, _) => write!(f, "{val}"),
56 I8(val, _) => write!(f, "{val}"),
57 I16(val, _) => write!(f, "{val}"),
58 I32(val, _) => write!(f, "{val}"),
59 I64(val, _) => write!(f, "{val}"),
60 I128(val, _) => write!(f, "{val}"),
61 U8(val, _) => write!(f, "{val}"),
62 U16(val, _) => write!(f, "{val}"),
63 U32(val, _) => write!(f, "{val}"),
64 U64(val, _) => write!(f, "{val}"),
65 U128(val, _) => write!(f, "{val}"),
66 Scalar(val, _) => write!(f, "{val}"),
67 Unsuffixed(val, _) => write!(f, "{val}"),
68 String(val, _) => write!(f, "{val}"),
69 }
70 }
71}
72
73impl TryFrom<Value> for i128 {
74 type Error = LeoError;
75
76 fn try_from(value: Value) -> Result<Self, Self::Error> {
77 value.as_ref().try_into()
78 }
79}
80
81impl TryFrom<&Value> for i128 {
82 type Error = LeoError;
83
84 fn try_from(value: &Value) -> Result<Self, Self::Error> {
85 use Value::*;
86 match value {
87 U8(val, _) => Ok(*val as i128),
88 U16(val, _) => Ok(*val as i128),
89 U32(val, _) => Ok(*val as i128),
90 U64(val, _) => Ok(*val as i128),
91 U128(val, span) => {
92 i128::try_from(*val).map_err(|_| FlattenError::u128_to_i128(Type::from(value), *span).into())
93 }
94 I8(val, _) => Ok(*val as i128),
95 I16(val, _) => Ok(*val as i128),
96 I32(val, _) => Ok(*val as i128),
97 I64(val, _) => Ok(*val as i128),
98 I128(val, _) => Ok(*val),
99 _ => unreachable!(),
100 }
101 }
102}
103
104impl TryFrom<Value> for u128 {
105 type Error = LeoError;
106
107 fn try_from(value: Value) -> Result<Self, Self::Error> {
108 value.as_ref().try_into()
109 }
110}
111
112impl TryFrom<&Value> for u128 {
113 type Error = LeoError;
114
115 fn try_from(value: &Value) -> Result<Self, Self::Error> {
116 use Value::*;
117 match value {
118 I8(val, span) => {
119 u128::try_from(*val).map_err(|_| FlattenError::loop_has_neg_value(Type::from(value), *span).into())
120 }
121 I16(val, span) => {
122 u128::try_from(*val).map_err(|_| FlattenError::loop_has_neg_value(Type::from(value), *span).into())
123 }
124 I32(val, span) => {
125 u128::try_from(*val).map_err(|_| FlattenError::loop_has_neg_value(Type::from(value), *span).into())
126 }
127 I64(val, span) => {
128 u128::try_from(*val).map_err(|_| FlattenError::loop_has_neg_value(Type::from(value), *span).into())
129 }
130 I128(val, span) => {
131 u128::try_from(*val).map_err(|_| FlattenError::loop_has_neg_value(Type::from(value), *span).into())
132 }
133 U8(val, _) => Ok(*val as u128),
134 U16(val, _) => Ok(*val as u128),
135 U32(val, _) => Ok(*val as u128),
136 U64(val, _) => Ok(*val as u128),
137 U128(val, _) => Ok(*val),
138 _ => unreachable!(),
139 }
140 }
141}
142
143impl AsRef<Value> for Value {
144 fn as_ref(&self) -> &Self {
145 self
146 }
147}
148
149impl From<Value> for Type {
150 fn from(v: Value) -> Self {
151 v.as_ref().into()
152 }
153}
154
155impl From<&Value> for Type {
156 fn from(v: &Value) -> Self {
157 use Value::*;
158 match v {
159 Address(_, _) => Type::Address,
160 Boolean(_, _) => Type::Boolean,
161 Struct(ident, _) => Type::Identifier(*ident),
162 Field(_, _) => Type::Field,
163 Group(_, _) => Type::Group,
164 I8(_, _) => Type::Integer(IntegerType::I8),
165 I16(_, _) => Type::Integer(IntegerType::I16),
166 I32(_, _) => Type::Integer(IntegerType::I32),
167 I64(_, _) => Type::Integer(IntegerType::I64),
168 I128(_, _) => Type::Integer(IntegerType::I128),
169 U8(_, _) => Type::Integer(IntegerType::U8),
170 U16(_, _) => Type::Integer(IntegerType::U16),
171 U32(_, _) => Type::Integer(IntegerType::U32),
172 U64(_, _) => Type::Integer(IntegerType::U64),
173 U128(_, _) => Type::Integer(IntegerType::U128),
174 Scalar(_, _) => Type::Scalar,
175 Unsuffixed(_, _) => Type::Numeric,
176 String(_, _) => Type::String,
177 }
178 }
179}
180
181impl TryFrom<&Literal> for Value {
182 type Error = ParseIntError;
183
184 fn try_from(literal: &Literal) -> Result<Self, Self::Error> {
186 let span = literal.span;
187 Ok(match &literal.variant {
188 LiteralVariant::Address(string) => Self::Address(string.clone(), span),
189 LiteralVariant::Boolean(bool) => Self::Boolean(*bool, span),
190 LiteralVariant::Field(string) => Self::Field(string.clone(), span),
191 LiteralVariant::Group(string) => Self::Group(string.clone(), span),
192 LiteralVariant::Scalar(string) => Self::Scalar(string.clone(), span),
193 LiteralVariant::Unsuffixed(string) => Self::Unsuffixed(string.clone(), span),
194 LiteralVariant::String(string) => Self::String(string.clone(), span),
195 LiteralVariant::Integer(integer_type, raw_string) => {
196 let string = raw_string.replace('_', "");
197 match integer_type {
198 IntegerType::U8 => Self::U8(u8::from_str_by_radix(&string)?, span),
199 IntegerType::U16 => Self::U16(u16::from_str_by_radix(&string)?, span),
200 IntegerType::U32 => Self::U32(u32::from_str_by_radix(&string)?, span),
201 IntegerType::U64 => Self::U64(u64::from_str_by_radix(&string)?, span),
202 IntegerType::U128 => Self::U128(u128::from_str_by_radix(&string)?, span),
203 IntegerType::I8 => Self::I8(i8::from_str_by_radix(&string)?, span),
204 IntegerType::I16 => Self::I16(i16::from_str_by_radix(&string)?, span),
205 IntegerType::I32 => Self::I32(i32::from_str_by_radix(&string)?, span),
206 IntegerType::I64 => Self::I64(i64::from_str_by_radix(&string)?, span),
207 IntegerType::I128 => Self::I128(i128::from_str_by_radix(&string)?, span),
208 }
209 }
210 })
211 }
212}