leo_ast/value/
mod.rs

1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use 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    /// Converts a literal to a value.
185    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}