solscript_ast/
types.rs

1//! Type expression AST nodes (Solidity-Style)
2
3use serde::{Deserialize, Serialize};
4use smol_str::SmolStr;
5
6use crate::{GenericArgs, Ident, Span};
7
8/// A type expression in the source code
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub enum TypeExpr {
11    /// A simple or qualified path type: `uint256`, `address`, `ContractName`
12    Path(TypePath),
13    /// Mapping type: `mapping(address => uint256)`
14    Mapping(Box<MappingType>),
15    /// An array type: `uint256[]` (dynamic) or `uint256[10]` (fixed)
16    Array(Box<ArrayType>),
17    /// A tuple type: `(uint256, bool)`
18    Tuple(TypeTuple),
19}
20
21impl TypeExpr {
22    pub fn span(&self) -> Span {
23        match self {
24            TypeExpr::Path(p) => p.span,
25            TypeExpr::Mapping(m) => m.span,
26            TypeExpr::Array(a) => a.span,
27            TypeExpr::Tuple(t) => t.span,
28        }
29    }
30
31    /// Get a string representation of the type name
32    pub fn name(&self) -> String {
33        match self {
34            TypeExpr::Path(p) => p.name().to_string(),
35            TypeExpr::Mapping(m) => {
36                format!("mapping({} => {})", m.key.name(), m.value.name())
37            }
38            TypeExpr::Array(a) => {
39                let base = a.element.name().to_string();
40                let mut result = base;
41                for size in &a.sizes {
42                    if let Some(n) = size {
43                        result = format!("{}[{}]", result, n);
44                    } else {
45                        result = format!("{}[]", result);
46                    }
47                }
48                result
49            }
50            TypeExpr::Tuple(t) => {
51                let types: Vec<_> = t.elements.iter().map(|ty| ty.name()).collect();
52                format!("({})", types.join(", "))
53            }
54        }
55    }
56}
57
58/// A type path: `uint256`, `address`, `MyContract`
59#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
60pub struct TypePath {
61    pub segments: Vec<Ident>,
62    pub generic_args: Option<GenericArgs>,
63    pub span: Span,
64}
65
66impl TypePath {
67    /// Create a simple type path from a single identifier
68    pub fn simple(name: Ident) -> Self {
69        let span = name.span;
70        Self {
71            segments: vec![name],
72            generic_args: None,
73            span,
74        }
75    }
76
77    /// Get the full path as a string
78    pub fn full_path(&self) -> String {
79        self.segments
80            .iter()
81            .map(|s| s.name.as_str())
82            .collect::<Vec<_>>()
83            .join("::")
84    }
85
86    /// Check if this is a simple (single-segment) path
87    pub fn is_simple(&self) -> bool {
88        self.segments.len() == 1 && self.generic_args.is_none()
89    }
90
91    /// Get the last segment name
92    pub fn name(&self) -> &SmolStr {
93        &self.segments.last().unwrap().name
94    }
95}
96
97/// Mapping type: `mapping(KeyType => ValueType)`
98#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
99pub struct MappingType {
100    pub key: TypeExpr,
101    pub value: TypeExpr,
102    pub span: Span,
103}
104
105/// Array type: `T[]` (dynamic) or `T[N]` (fixed)
106#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
107pub struct ArrayType {
108    pub element: TypePath,
109    pub sizes: Vec<Option<u64>>, // None = dynamic [], Some(n) = fixed [n]
110    pub span: Span,
111}
112
113/// A tuple type: `(T, U, V)`
114#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
115pub struct TypeTuple {
116    pub elements: Vec<TypeExpr>,
117    pub span: Span,
118}
119
120/// Built-in primitive types (Solidity-style naming)
121#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
122pub enum PrimitiveType {
123    // Unsigned integers
124    Uint8,
125    Uint16,
126    Uint24,
127    Uint32,
128    Uint40,
129    Uint48,
130    Uint56,
131    Uint64,
132    Uint72,
133    Uint80,
134    Uint88,
135    Uint96,
136    Uint104,
137    Uint112,
138    Uint120,
139    Uint128,
140    Uint136,
141    Uint144,
142    Uint152,
143    Uint160,
144    Uint168,
145    Uint176,
146    Uint184,
147    Uint192,
148    Uint200,
149    Uint208,
150    Uint216,
151    Uint224,
152    Uint232,
153    Uint240,
154    Uint248,
155    Uint256,
156    // Signed integers
157    Int8,
158    Int16,
159    Int24,
160    Int32,
161    Int40,
162    Int48,
163    Int56,
164    Int64,
165    Int72,
166    Int80,
167    Int88,
168    Int96,
169    Int104,
170    Int112,
171    Int120,
172    Int128,
173    Int136,
174    Int144,
175    Int152,
176    Int160,
177    Int168,
178    Int176,
179    Int184,
180    Int192,
181    Int200,
182    Int208,
183    Int216,
184    Int224,
185    Int232,
186    Int240,
187    Int248,
188    Int256,
189    // Other primitives
190    Bool,
191    Address,
192    String,
193    Bytes,
194    Bytes1,
195    Bytes2,
196    Bytes3,
197    Bytes4,
198    Bytes5,
199    Bytes6,
200    Bytes7,
201    Bytes8,
202    Bytes9,
203    Bytes10,
204    Bytes11,
205    Bytes12,
206    Bytes13,
207    Bytes14,
208    Bytes15,
209    Bytes16,
210    Bytes17,
211    Bytes18,
212    Bytes19,
213    Bytes20,
214    Bytes21,
215    Bytes22,
216    Bytes23,
217    Bytes24,
218    Bytes25,
219    Bytes26,
220    Bytes27,
221    Bytes28,
222    Bytes29,
223    Bytes30,
224    Bytes31,
225    Bytes32,
226}
227
228impl PrimitiveType {
229    /// Try to parse a primitive type from a string
230    pub fn parse(s: &str) -> Option<Self> {
231        match s {
232            // uint aliases
233            "uint" | "uint256" => Some(Self::Uint256),
234            "uint8" => Some(Self::Uint8),
235            "uint16" => Some(Self::Uint16),
236            "uint24" => Some(Self::Uint24),
237            "uint32" => Some(Self::Uint32),
238            "uint40" => Some(Self::Uint40),
239            "uint48" => Some(Self::Uint48),
240            "uint56" => Some(Self::Uint56),
241            "uint64" => Some(Self::Uint64),
242            "uint72" => Some(Self::Uint72),
243            "uint80" => Some(Self::Uint80),
244            "uint88" => Some(Self::Uint88),
245            "uint96" => Some(Self::Uint96),
246            "uint104" => Some(Self::Uint104),
247            "uint112" => Some(Self::Uint112),
248            "uint120" => Some(Self::Uint120),
249            "uint128" => Some(Self::Uint128),
250            "uint136" => Some(Self::Uint136),
251            "uint144" => Some(Self::Uint144),
252            "uint152" => Some(Self::Uint152),
253            "uint160" => Some(Self::Uint160),
254            "uint168" => Some(Self::Uint168),
255            "uint176" => Some(Self::Uint176),
256            "uint184" => Some(Self::Uint184),
257            "uint192" => Some(Self::Uint192),
258            "uint200" => Some(Self::Uint200),
259            "uint208" => Some(Self::Uint208),
260            "uint216" => Some(Self::Uint216),
261            "uint224" => Some(Self::Uint224),
262            "uint232" => Some(Self::Uint232),
263            "uint240" => Some(Self::Uint240),
264            "uint248" => Some(Self::Uint248),
265            // int aliases
266            "int" | "int256" => Some(Self::Int256),
267            "int8" => Some(Self::Int8),
268            "int16" => Some(Self::Int16),
269            "int24" => Some(Self::Int24),
270            "int32" => Some(Self::Int32),
271            "int40" => Some(Self::Int40),
272            "int48" => Some(Self::Int48),
273            "int56" => Some(Self::Int56),
274            "int64" => Some(Self::Int64),
275            "int72" => Some(Self::Int72),
276            "int80" => Some(Self::Int80),
277            "int88" => Some(Self::Int88),
278            "int96" => Some(Self::Int96),
279            "int104" => Some(Self::Int104),
280            "int112" => Some(Self::Int112),
281            "int120" => Some(Self::Int120),
282            "int128" => Some(Self::Int128),
283            "int136" => Some(Self::Int136),
284            "int144" => Some(Self::Int144),
285            "int152" => Some(Self::Int152),
286            "int160" => Some(Self::Int160),
287            "int168" => Some(Self::Int168),
288            "int176" => Some(Self::Int176),
289            "int184" => Some(Self::Int184),
290            "int192" => Some(Self::Int192),
291            "int200" => Some(Self::Int200),
292            "int208" => Some(Self::Int208),
293            "int216" => Some(Self::Int216),
294            "int224" => Some(Self::Int224),
295            "int232" => Some(Self::Int232),
296            "int240" => Some(Self::Int240),
297            "int248" => Some(Self::Int248),
298            // Other types
299            "bool" => Some(Self::Bool),
300            "address" => Some(Self::Address),
301            "string" => Some(Self::String),
302            "bytes" => Some(Self::Bytes),
303            "bytes1" => Some(Self::Bytes1),
304            "bytes2" => Some(Self::Bytes2),
305            "bytes3" => Some(Self::Bytes3),
306            "bytes4" => Some(Self::Bytes4),
307            "bytes5" => Some(Self::Bytes5),
308            "bytes6" => Some(Self::Bytes6),
309            "bytes7" => Some(Self::Bytes7),
310            "bytes8" => Some(Self::Bytes8),
311            "bytes9" => Some(Self::Bytes9),
312            "bytes10" => Some(Self::Bytes10),
313            "bytes11" => Some(Self::Bytes11),
314            "bytes12" => Some(Self::Bytes12),
315            "bytes13" => Some(Self::Bytes13),
316            "bytes14" => Some(Self::Bytes14),
317            "bytes15" => Some(Self::Bytes15),
318            "bytes16" => Some(Self::Bytes16),
319            "bytes17" => Some(Self::Bytes17),
320            "bytes18" => Some(Self::Bytes18),
321            "bytes19" => Some(Self::Bytes19),
322            "bytes20" => Some(Self::Bytes20),
323            "bytes21" => Some(Self::Bytes21),
324            "bytes22" => Some(Self::Bytes22),
325            "bytes23" => Some(Self::Bytes23),
326            "bytes24" => Some(Self::Bytes24),
327            "bytes25" => Some(Self::Bytes25),
328            "bytes26" => Some(Self::Bytes26),
329            "bytes27" => Some(Self::Bytes27),
330            "bytes28" => Some(Self::Bytes28),
331            "bytes29" => Some(Self::Bytes29),
332            "bytes30" => Some(Self::Bytes30),
333            "bytes31" => Some(Self::Bytes31),
334            "bytes32" => Some(Self::Bytes32),
335            _ => None,
336        }
337    }
338
339    /// Get the string representation
340    pub fn as_str(&self) -> &'static str {
341        match self {
342            Self::Uint8 => "uint8",
343            Self::Uint16 => "uint16",
344            Self::Uint24 => "uint24",
345            Self::Uint32 => "uint32",
346            Self::Uint40 => "uint40",
347            Self::Uint48 => "uint48",
348            Self::Uint56 => "uint56",
349            Self::Uint64 => "uint64",
350            Self::Uint72 => "uint72",
351            Self::Uint80 => "uint80",
352            Self::Uint88 => "uint88",
353            Self::Uint96 => "uint96",
354            Self::Uint104 => "uint104",
355            Self::Uint112 => "uint112",
356            Self::Uint120 => "uint120",
357            Self::Uint128 => "uint128",
358            Self::Uint136 => "uint136",
359            Self::Uint144 => "uint144",
360            Self::Uint152 => "uint152",
361            Self::Uint160 => "uint160",
362            Self::Uint168 => "uint168",
363            Self::Uint176 => "uint176",
364            Self::Uint184 => "uint184",
365            Self::Uint192 => "uint192",
366            Self::Uint200 => "uint200",
367            Self::Uint208 => "uint208",
368            Self::Uint216 => "uint216",
369            Self::Uint224 => "uint224",
370            Self::Uint232 => "uint232",
371            Self::Uint240 => "uint240",
372            Self::Uint248 => "uint248",
373            Self::Uint256 => "uint256",
374            Self::Int8 => "int8",
375            Self::Int16 => "int16",
376            Self::Int24 => "int24",
377            Self::Int32 => "int32",
378            Self::Int40 => "int40",
379            Self::Int48 => "int48",
380            Self::Int56 => "int56",
381            Self::Int64 => "int64",
382            Self::Int72 => "int72",
383            Self::Int80 => "int80",
384            Self::Int88 => "int88",
385            Self::Int96 => "int96",
386            Self::Int104 => "int104",
387            Self::Int112 => "int112",
388            Self::Int120 => "int120",
389            Self::Int128 => "int128",
390            Self::Int136 => "int136",
391            Self::Int144 => "int144",
392            Self::Int152 => "int152",
393            Self::Int160 => "int160",
394            Self::Int168 => "int168",
395            Self::Int176 => "int176",
396            Self::Int184 => "int184",
397            Self::Int192 => "int192",
398            Self::Int200 => "int200",
399            Self::Int208 => "int208",
400            Self::Int216 => "int216",
401            Self::Int224 => "int224",
402            Self::Int232 => "int232",
403            Self::Int240 => "int240",
404            Self::Int248 => "int248",
405            Self::Int256 => "int256",
406            Self::Bool => "bool",
407            Self::Address => "address",
408            Self::String => "string",
409            Self::Bytes => "bytes",
410            Self::Bytes1 => "bytes1",
411            Self::Bytes2 => "bytes2",
412            Self::Bytes3 => "bytes3",
413            Self::Bytes4 => "bytes4",
414            Self::Bytes5 => "bytes5",
415            Self::Bytes6 => "bytes6",
416            Self::Bytes7 => "bytes7",
417            Self::Bytes8 => "bytes8",
418            Self::Bytes9 => "bytes9",
419            Self::Bytes10 => "bytes10",
420            Self::Bytes11 => "bytes11",
421            Self::Bytes12 => "bytes12",
422            Self::Bytes13 => "bytes13",
423            Self::Bytes14 => "bytes14",
424            Self::Bytes15 => "bytes15",
425            Self::Bytes16 => "bytes16",
426            Self::Bytes17 => "bytes17",
427            Self::Bytes18 => "bytes18",
428            Self::Bytes19 => "bytes19",
429            Self::Bytes20 => "bytes20",
430            Self::Bytes21 => "bytes21",
431            Self::Bytes22 => "bytes22",
432            Self::Bytes23 => "bytes23",
433            Self::Bytes24 => "bytes24",
434            Self::Bytes25 => "bytes25",
435            Self::Bytes26 => "bytes26",
436            Self::Bytes27 => "bytes27",
437            Self::Bytes28 => "bytes28",
438            Self::Bytes29 => "bytes29",
439            Self::Bytes30 => "bytes30",
440            Self::Bytes31 => "bytes31",
441            Self::Bytes32 => "bytes32",
442        }
443    }
444
445    /// Get the byte size of the type
446    pub fn byte_size(&self) -> Option<usize> {
447        match self {
448            Self::Uint8 | Self::Int8 | Self::Bytes1 => Some(1),
449            Self::Uint16 | Self::Int16 | Self::Bytes2 => Some(2),
450            Self::Uint24 | Self::Int24 | Self::Bytes3 => Some(3),
451            Self::Uint32 | Self::Int32 | Self::Bytes4 => Some(4),
452            Self::Uint40 | Self::Int40 | Self::Bytes5 => Some(5),
453            Self::Uint48 | Self::Int48 | Self::Bytes6 => Some(6),
454            Self::Uint56 | Self::Int56 | Self::Bytes7 => Some(7),
455            Self::Uint64 | Self::Int64 | Self::Bytes8 => Some(8),
456            Self::Uint72 | Self::Int72 | Self::Bytes9 => Some(9),
457            Self::Uint80 | Self::Int80 | Self::Bytes10 => Some(10),
458            Self::Uint88 | Self::Int88 | Self::Bytes11 => Some(11),
459            Self::Uint96 | Self::Int96 | Self::Bytes12 => Some(12),
460            Self::Uint104 | Self::Int104 | Self::Bytes13 => Some(13),
461            Self::Uint112 | Self::Int112 | Self::Bytes14 => Some(14),
462            Self::Uint120 | Self::Int120 | Self::Bytes15 => Some(15),
463            Self::Uint128 | Self::Int128 | Self::Bytes16 => Some(16),
464            Self::Uint136 | Self::Int136 | Self::Bytes17 => Some(17),
465            Self::Uint144 | Self::Int144 | Self::Bytes18 => Some(18),
466            Self::Uint152 | Self::Int152 | Self::Bytes19 => Some(19),
467            Self::Uint160 | Self::Int160 | Self::Bytes20 | Self::Address => Some(20),
468            Self::Uint168 | Self::Int168 | Self::Bytes21 => Some(21),
469            Self::Uint176 | Self::Int176 | Self::Bytes22 => Some(22),
470            Self::Uint184 | Self::Int184 | Self::Bytes23 => Some(23),
471            Self::Uint192 | Self::Int192 | Self::Bytes24 => Some(24),
472            Self::Uint200 | Self::Int200 | Self::Bytes25 => Some(25),
473            Self::Uint208 | Self::Int208 | Self::Bytes26 => Some(26),
474            Self::Uint216 | Self::Int216 | Self::Bytes27 => Some(27),
475            Self::Uint224 | Self::Int224 | Self::Bytes28 => Some(28),
476            Self::Uint232 | Self::Int232 | Self::Bytes29 => Some(29),
477            Self::Uint240 | Self::Int240 | Self::Bytes30 => Some(30),
478            Self::Uint248 | Self::Int248 | Self::Bytes31 => Some(31),
479            Self::Uint256 | Self::Int256 | Self::Bytes32 => Some(32),
480            Self::Bool => Some(1),
481            Self::String | Self::Bytes => None, // Dynamic size
482        }
483    }
484}