leo_passes/code_generation/
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 std::fmt::Display;
18
19use crate::Pass;
20
21use itertools::Itertools;
22use leo_ast::{Mode, ProgramId};
23use leo_errors::Result;
24
25mod expression;
26
27mod program;
28
29mod statement;
30
31mod type_;
32
33mod visitor;
34use snarkvm::{
35    prelude::{ArrayType, LiteralType, Network, PlaintextType},
36    synthesizer::program::{CommitVariant, DeserializeVariant, ECDSAVerifyVariant, HashVariant, SerializeVariant},
37};
38use visitor::*;
39
40pub struct CodeGenerating;
41
42impl Pass for CodeGenerating {
43    type Input = ();
44    type Output = AleoProgram;
45
46    const NAME: &str = "CodeGenerating";
47
48    fn do_pass(_input: Self::Input, state: &mut crate::CompilerState) -> Result<Self::Output> {
49        let mut visitor = CodeGeneratingVisitor {
50            state,
51            next_register: 0,
52            current_function: None,
53            variable_mapping: Default::default(),
54            composite_mapping: Default::default(),
55            global_mapping: Default::default(),
56            variant: None,
57            program: &state.ast.ast,
58            program_id: None,
59            finalize_caller: None,
60            next_label: 0,
61            conditional_depth: 0,
62            internal_record_inputs: Default::default(),
63        };
64        let code = visitor.visit_program(visitor.state.ast.as_repr());
65        Ok(code)
66    }
67}
68
69#[derive(Debug)]
70pub struct AleoProgram {
71    imports: Vec<String>,
72    program_id: ProgramId,
73    data_types: Vec<AleoDatatype>, // order matters
74    mappings: Vec<AleoMapping>,
75    functions: Vec<AleoFunctional>,
76    constructor: Option<AleoConstructor>,
77}
78
79impl Display for AleoProgram {
80    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        self.imports
82            .iter()
83            .map(|program_name| format!("import {program_name}.aleo;"))
84            .chain(std::iter::once(format!("program {};\n", self.program_id)))
85            .chain(self.data_types.iter().map(ToString::to_string))
86            .chain(self.mappings.iter().map(ToString::to_string))
87            .chain(self.functions.iter().map(ToString::to_string))
88            .chain(self.constructor.iter().map(ToString::to_string))
89            .join("\n")
90            .fmt(f)
91    }
92}
93
94#[derive(Debug)]
95pub enum AleoDatatype {
96    Struct(AleoStruct),
97    Record(AleoRecord),
98}
99
100impl Display for AleoDatatype {
101    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102        match self {
103            Self::Struct(s) => s.fmt(f),
104            Self::Record(r) => r.fmt(f),
105        }
106    }
107}
108
109#[derive(Debug)]
110pub struct AleoStruct {
111    name: String,
112    fields: Vec<(String, AleoType)>,
113}
114impl Display for AleoStruct {
115    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116        writeln!(f, "struct {}:", self.name)?;
117        for (id, ty) in self.fields.iter() {
118            writeln!(f, "    {id} as {ty};")?;
119        }
120        Ok(())
121    }
122}
123
124#[derive(Debug)]
125pub struct AleoRecord {
126    name: String,
127    fields: Vec<(String, AleoType, AleoVisibility)>,
128}
129impl Display for AleoRecord {
130    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131        writeln!(f, "record {}:", self.name)?;
132        for (id, ty, mode) in self.fields.iter() {
133            writeln!(f, "    {id} as {ty}.{mode};")?;
134        }
135        Ok(())
136    }
137}
138
139#[derive(Debug)]
140pub enum AleoVisibility {
141    Constant,
142    Public,
143    Private,
144}
145impl AleoVisibility {
146    fn maybe_from(mode: Mode) -> Option<Self> {
147        match mode {
148            Mode::None => None,
149            Mode::Constant => Some(Self::Constant),
150            Mode::Private => Some(Self::Private),
151            Mode::Public => Some(Self::Public),
152        }
153    }
154}
155
156impl Display for AleoVisibility {
157    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158        write!(f, "{}", match self {
159            Self::Constant => "constant",
160            Self::Public => "public",
161            Self::Private => "private",
162        })
163    }
164}
165
166#[derive(Debug)]
167pub struct AleoMapping {
168    name: String,
169    key_type: AleoType,
170    key_visibility: Option<AleoVisibility>,
171    value_type: AleoType,
172    value_visibility: Option<AleoVisibility>,
173}
174impl Display for AleoMapping {
175    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176        writeln!(f, "mapping {}:", self.name)?;
177        if let Some(key_viz) = &self.key_visibility {
178            writeln!(f, "    key as {}.{};", self.key_type, key_viz)?;
179        } else {
180            writeln!(f, "    key as {};", self.key_type)?;
181        }
182        if let Some(value_viz) = &self.value_visibility {
183            writeln!(f, "    value as {}.{};", self.value_type, value_viz)?;
184        } else {
185            writeln!(f, "    value as {};", self.value_type)?;
186        }
187        Ok(())
188    }
189}
190
191#[derive(Debug)]
192pub struct AleoClosure {
193    name: String,
194    inputs: Vec<AleoInput>,
195    statements: Vec<AleoStmt>,
196}
197impl Display for AleoClosure {
198    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
199        writeln!(f, "closure {}:", self.name)?;
200        for input in &self.inputs {
201            write!(f, "{}", input)?;
202        }
203        for stm in &self.statements {
204            write!(f, "{}", stm)?;
205        }
206        Ok(())
207    }
208}
209
210#[derive(Debug)]
211pub enum AleoFunctional {
212    Closure(AleoClosure),
213    Function(AleoFunction),
214    Finalize(AleoFinalize),
215}
216impl AleoFunctional {
217    pub fn as_closure(self) -> AleoClosure {
218        if let Self::Closure(c) = self { c } else { panic!("this is not a closure") }
219    }
220
221    pub fn as_function(self) -> AleoFunction {
222        if let Self::Function(c) = self { c } else { panic!("this is not a function") }
223    }
224
225    pub fn as_function_ref_mut(&mut self) -> &mut AleoFunction {
226        if let Self::Function(c) = self { c } else { panic!("this is not a function") }
227    }
228
229    pub fn as_finalize(self) -> AleoFinalize {
230        if let Self::Finalize(c) = self { c } else { panic!("this is not a finalize") }
231    }
232}
233impl Display for AleoFunctional {
234    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235        match self {
236            Self::Closure(c) => c.fmt(f),
237            Self::Function(fun) => fun.fmt(f),
238            Self::Finalize(fin) => fin.fmt(f),
239        }
240    }
241}
242
243#[derive(Debug)]
244pub struct AleoFunction {
245    name: String,
246    inputs: Vec<AleoInput>,
247    statements: Vec<AleoStmt>,
248    finalize: Option<AleoFinalize>,
249}
250impl Display for AleoFunction {
251    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
252        writeln!(f, "function {}:", self.name)?;
253        for input in &self.inputs {
254            write!(f, "{}", input)?;
255        }
256        for stm in &self.statements {
257            write!(f, "{}", stm)?;
258        }
259        if let Some(finalize) = &self.finalize {
260            write!(f, "\n{}", finalize)?;
261        }
262        Ok(())
263    }
264}
265
266#[derive(Debug)]
267pub struct AleoFinalize {
268    caller_name: String,
269    inputs: Vec<AleoInput>,
270    statements: Vec<AleoStmt>,
271}
272impl Display for AleoFinalize {
273    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
274        writeln!(f, "finalize {}:", self.caller_name)?;
275        for input in &self.inputs {
276            write!(f, "{}", input)?;
277        }
278        for stm in &self.statements {
279            write!(f, "{}", stm)?;
280        }
281        Ok(())
282    }
283}
284
285#[derive(Debug)]
286pub struct AleoInput {
287    register: AleoReg,
288    type_: AleoType,
289    visibility: Option<AleoVisibility>,
290}
291impl Display for AleoInput {
292    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
293        if let Some(visibility) = &self.visibility {
294            writeln!(f, "    input {} as {}.{};", self.register, self.type_, visibility)
295        } else {
296            writeln!(f, "    input {} as {};", self.register, self.type_)
297        }
298    }
299}
300
301#[derive(Debug)]
302pub struct AleoConstructor {
303    statements: Vec<AleoStmt>,
304    // FIXME: remove later, needed for the exact same behavior as previous codegen
305    is_custom: bool,
306}
307impl Display for AleoConstructor {
308    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
309        writeln!(f, "constructor:")?;
310        for stm in &self.statements {
311            write!(f, "{}", stm)?;
312        }
313        if self.is_custom {
314            writeln!(f)?;
315        }
316        Ok(())
317    }
318}
319
320#[derive(Hash, Eq, PartialEq, Clone, Debug)]
321pub enum AleoExpr {
322    Reg(AleoReg),
323    Tuple(Vec<AleoExpr>),
324    ArrayAccess(Box<AleoExpr>, Box<AleoExpr>),
325    MemberAccess(Box<AleoExpr>, String),
326    RawName(String),
327    // Literals
328    Address(String),
329    Bool(bool),
330    Field(String),
331    Group(String),
332    Scalar(String),
333    String(String),
334    U8(u8),
335    U16(u16),
336    U32(u32),
337    U64(u64),
338    U128(u128),
339    I8(i8),
340    I16(i16),
341    I32(i32),
342    I64(i64),
343    I128(i128),
344}
345impl Display for AleoExpr {
346    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
347        match self {
348            Self::Reg(reg) => write!(f, "{reg}"),
349            Self::Tuple(regs) => write!(f, "{}", regs.iter().map(|reg| reg.to_string()).join(" ")),
350            Self::ArrayAccess(array, index) => write!(f, "{array}[{index}]"),
351            Self::MemberAccess(comp, member) => write!(f, "{comp}.{member}"),
352            Self::RawName(n) => write!(f, "{n}"),
353            Self::Address(val) => write!(f, "{val}"),
354            Self::Bool(val) => write!(f, "{val}"),
355            Self::Field(val) => write!(f, "{val}field"),
356            Self::Group(val) => write!(f, "{val}group"),
357            Self::Scalar(val) => write!(f, "{val}scalar"),
358            Self::String(val) => write!(f, "\"{val}\""),
359            Self::U8(val) => write!(f, "{val}u8"),
360            Self::U16(val) => write!(f, "{val}u16"),
361            Self::U32(val) => write!(f, "{val}u32"),
362            Self::U64(val) => write!(f, "{val}u64"),
363            Self::U128(val) => write!(f, "{val}u128"),
364            Self::I8(val) => write!(f, "{val}i8"),
365            Self::I16(val) => write!(f, "{val}i16"),
366            Self::I32(val) => write!(f, "{val}i32"),
367            Self::I64(val) => write!(f, "{val}i64"),
368            Self::I128(val) => write!(f, "{val}i128"),
369        }
370    }
371}
372
373#[derive(Debug)]
374pub enum AleoStmt {
375    Output(AleoExpr, AleoType, Option<AleoVisibility>),
376    AssertEq(AleoExpr, AleoExpr),
377    AssertNeq(AleoExpr, AleoExpr),
378    Cast(AleoExpr, AleoReg, AleoType),
379    Abs(AleoExpr, AleoReg),
380    AbsW(AleoExpr, AleoReg),
381    Double(AleoExpr, AleoReg),
382    Inv(AleoExpr, AleoReg),
383    Not(AleoExpr, AleoReg),
384    Neg(AleoExpr, AleoReg),
385    Square(AleoExpr, AleoReg),
386    Sqrt(AleoExpr, AleoReg),
387    Ternary(AleoExpr, AleoExpr, AleoExpr, AleoReg),
388    Commit(CommitVariant, AleoExpr, AleoExpr, AleoReg, AleoType),
389    Hash(HashVariant, AleoExpr, AleoReg, AleoType),
390    Get(AleoExpr, AleoExpr, AleoReg),
391    GetOrUse(AleoExpr, AleoExpr, AleoExpr, AleoReg),
392    Set(AleoExpr, AleoExpr, AleoExpr),
393    Remove(AleoExpr, AleoExpr),
394    Contains(AleoExpr, AleoExpr, AleoReg),
395    RandChacha(AleoReg, AleoType),
396    SignVerify(AleoExpr, AleoExpr, AleoExpr, AleoReg),
397    EcdsaVerify(ECDSAVerifyVariant, AleoExpr, AleoExpr, AleoExpr, AleoReg),
398    Await(AleoExpr),
399    Serialize(SerializeVariant, AleoExpr, AleoType, AleoReg, AleoType),
400    Deserialize(DeserializeVariant, AleoExpr, AleoType, AleoReg, AleoType),
401    Call(String, Vec<AleoExpr>, Vec<AleoReg>),
402    Async(String, Vec<AleoExpr>, Vec<AleoReg>),
403    BranchEq(AleoExpr, AleoExpr, String),
404    Position(String),
405    Add(AleoExpr, AleoExpr, AleoReg),
406    AddWrapped(AleoExpr, AleoExpr, AleoReg),
407    And(AleoExpr, AleoExpr, AleoReg),
408    Div(AleoExpr, AleoExpr, AleoReg),
409    DivWrapped(AleoExpr, AleoExpr, AleoReg),
410    Eq(AleoExpr, AleoExpr, AleoReg),
411    Gte(AleoExpr, AleoExpr, AleoReg),
412    Gt(AleoExpr, AleoExpr, AleoReg),
413    Lte(AleoExpr, AleoExpr, AleoReg),
414    Lt(AleoExpr, AleoExpr, AleoReg),
415    Mod(AleoExpr, AleoExpr, AleoReg),
416    Mul(AleoExpr, AleoExpr, AleoReg),
417    MulWrapped(AleoExpr, AleoExpr, AleoReg),
418    Nand(AleoExpr, AleoExpr, AleoReg),
419    Neq(AleoExpr, AleoExpr, AleoReg),
420    Nor(AleoExpr, AleoExpr, AleoReg),
421    Or(AleoExpr, AleoExpr, AleoReg),
422    Pow(AleoExpr, AleoExpr, AleoReg),
423    PowWrapped(AleoExpr, AleoExpr, AleoReg),
424    Rem(AleoExpr, AleoExpr, AleoReg),
425    RemWrapped(AleoExpr, AleoExpr, AleoReg),
426    Shl(AleoExpr, AleoExpr, AleoReg),
427    ShlWrapped(AleoExpr, AleoExpr, AleoReg),
428    Shr(AleoExpr, AleoExpr, AleoReg),
429    ShrWrapped(AleoExpr, AleoExpr, AleoReg),
430    Sub(AleoExpr, AleoExpr, AleoReg),
431    SubWrapped(AleoExpr, AleoExpr, AleoReg),
432    Xor(AleoExpr, AleoExpr, AleoReg),
433}
434impl Display for AleoStmt {
435    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
436        match self {
437            Self::Output(arg, type_, viz) => {
438                if let Some(viz) = &viz {
439                    writeln!(f, "    output {} as {}.{};", arg, type_, viz)
440                } else {
441                    writeln!(f, "    output {} as {};", arg, type_)
442                }
443            }
444            Self::AssertEq(left, right) => writeln!(f, "    assert.eq {left} {right};"),
445            Self::AssertNeq(left, right) => writeln!(f, "    assert.neq {left} {right};"),
446            Self::Cast(operands, dest, type_) => {
447                writeln!(f, "    cast {operands} into {dest} as {type_};")
448            }
449            Self::Abs(op, dest) => writeln!(f, "    abs {op} into {dest};"),
450            Self::AbsW(op, dest) => writeln!(f, "    abs.w {op} into {dest};"),
451            Self::Double(op, dest) => writeln!(f, "    double {op} into {dest};"),
452            Self::Inv(op, dest) => writeln!(f, "    inv {op} into {dest};"),
453            Self::Not(op, dest) => writeln!(f, "    not {op} into {dest};"),
454            Self::Neg(op, dest) => writeln!(f, "    neg {op} into {dest};"),
455            Self::Square(op, dest) => writeln!(f, "    square {op} into {dest};"),
456            Self::Sqrt(op, dest) => writeln!(f, "    sqrt {op} into {dest};"),
457            Self::Ternary(cond, if_true, if_false, dest) => {
458                writeln!(f, "    ternary {cond} {if_true} {if_false} into {dest};")
459            }
460            Self::Commit(variant, arg0, arg1, dest, type_) => {
461                writeln!(
462                    f,
463                    "    {} {arg0} {arg1} into {dest} as {type_};",
464                    CommitVariant::opcode(variant.clone() as u8)
465                )
466            }
467            Self::Hash(variant, arg0, dest, type_) => {
468                writeln!(f, "    {} {arg0} into {dest} as {type_};", variant.opcode())
469            }
470            Self::Get(mapping, key, dest) => writeln!(f, "    get {mapping}[{key}] into {dest};"),
471            Self::GetOrUse(mapping, key, default, dest) => {
472                writeln!(f, "    get.or_use {mapping}[{key}] {default} into {dest};")
473            }
474            Self::Set(value, mapping, key) => writeln!(f, "    set {value} into {mapping}[{key}];"),
475            Self::Remove(mapping, key) => writeln!(f, "    remove {mapping}[{key}];"),
476            Self::Contains(mapping, key, dest) => writeln!(f, "    contains {mapping}[{key}] into {dest};"),
477            Self::RandChacha(dest, type_) => writeln!(f, "    rand.chacha into {dest} as {type_};"),
478            Self::SignVerify(arg0, arg1, arg2, dest) => {
479                writeln!(f, "    sign.verify {arg0} {arg1} {arg2} into {dest};")
480            }
481            Self::EcdsaVerify(variant, arg0, arg1, arg2, dest) => {
482                writeln!(f, "    {} {arg0} {arg1} {arg2} into {dest};", variant.opcode())
483            }
484            Self::Await(exp) => writeln!(f, "    await {exp};"),
485            Self::Serialize(variant, input, input_ty, dest, dest_ty) => {
486                writeln!(
487                    f,
488                    "    {} {input} ({input_ty}) into {dest} ({dest_ty});",
489                    SerializeVariant::opcode(variant.clone() as u8),
490                )
491            }
492            Self::Deserialize(variant, input, input_ty, dest, dest_ty) => {
493                writeln!(
494                    f,
495                    "    {} {input} ({input_ty}) into {dest} ({dest_ty});",
496                    DeserializeVariant::opcode(variant.clone() as u8),
497                )
498            }
499            Self::Call(id, inputs, dests) => {
500                write!(f, "    call {id}")?;
501                if !inputs.is_empty() {
502                    write!(f, " {}", inputs.iter().map(|input| input.to_string()).join(" "))?;
503                }
504                if !dests.is_empty() {
505                    write!(f, " into {}", dests.iter().map(|input| input.to_string()).join(" "))?;
506                }
507                writeln!(f, ";")
508            }
509            Self::Async(id, inputs, dests) => {
510                write!(f, "    async {id}")?;
511                if !inputs.is_empty() {
512                    write!(f, " {}", inputs.iter().map(|input| input.to_string()).join(" "))?;
513                }
514                if !dests.is_empty() {
515                    write!(f, " into {}", dests.iter().map(|input| input.to_string()).join(" "))?;
516                }
517                writeln!(f, ";")
518            }
519            Self::BranchEq(arg0, arg1, label) => {
520                writeln!(f, "    branch.eq {arg0} {arg1} to {label};")
521            }
522            Self::Position(label) => writeln!(f, "    position {label};"),
523            Self::Add(arg0, arg1, dest) => writeln!(f, "    add {arg0} {arg1} into {dest};"),
524            Self::AddWrapped(arg0, arg1, dest) => writeln!(f, "    add.w {arg0} {arg1} into {dest};"),
525            Self::And(arg0, arg1, dest) => writeln!(f, "    and {arg0} {arg1} into {dest};"),
526            Self::Div(arg0, arg1, dest) => writeln!(f, "    div {arg0} {arg1} into {dest};"),
527            Self::DivWrapped(arg0, arg1, dest) => writeln!(f, "    div.w {arg0} {arg1} into {dest};"),
528            Self::Eq(arg0, arg1, dest) => writeln!(f, "    is.eq {arg0} {arg1} into {dest};"),
529            Self::Gte(arg0, arg1, dest) => writeln!(f, "    gte {arg0} {arg1} into {dest};"),
530            Self::Gt(arg0, arg1, dest) => writeln!(f, "    gt {arg0} {arg1} into {dest};"),
531            Self::Lte(arg0, arg1, dest) => writeln!(f, "    lte {arg0} {arg1} into {dest};"),
532            Self::Lt(arg0, arg1, dest) => writeln!(f, "    lt {arg0} {arg1} into {dest};"),
533            Self::Mod(arg0, arg1, dest) => writeln!(f, "    mod {arg0} {arg1} into {dest};"),
534            Self::Mul(arg0, arg1, dest) => writeln!(f, "    mul {arg0} {arg1} into {dest};"),
535            Self::MulWrapped(arg0, arg1, dest) => writeln!(f, "    mul.w {arg0} {arg1} into {dest};"),
536            Self::Nand(arg0, arg1, dest) => writeln!(f, "    nand {arg0} {arg1} into {dest};"),
537            Self::Neq(arg0, arg1, dest) => writeln!(f, "    is.neq {arg0} {arg1} into {dest};"),
538            Self::Nor(arg0, arg1, dest) => writeln!(f, "    nor {arg0} {arg1} into {dest};"),
539            Self::Or(arg0, arg1, dest) => writeln!(f, "    or {arg0} {arg1} into {dest};"),
540            Self::Pow(arg0, arg1, dest) => writeln!(f, "    pow {arg0} {arg1} into {dest};"),
541            Self::PowWrapped(arg0, arg1, dest) => writeln!(f, "    pow.w {arg0} {arg1} into {dest};"),
542            Self::Rem(arg0, arg1, dest) => writeln!(f, "    rem {arg0} {arg1} into {dest};"),
543            Self::RemWrapped(arg0, arg1, dest) => writeln!(f, "    rem.w {arg0} {arg1} into {dest};"),
544            Self::Shl(arg0, arg1, dest) => writeln!(f, "    shl {arg0} {arg1} into {dest};"),
545            Self::ShlWrapped(arg0, arg1, dest) => writeln!(f, "    shl.w {arg0} {arg1} into {dest};"),
546            Self::Shr(arg0, arg1, dest) => writeln!(f, "    shr {arg0} {arg1} into {dest};"),
547            Self::ShrWrapped(arg0, arg1, dest) => writeln!(f, "    shr.w {arg0} {arg1} into {dest};"),
548            Self::Sub(arg0, arg1, dest) => writeln!(f, "    sub {arg0} {arg1} into {dest};"),
549            Self::SubWrapped(arg0, arg1, dest) => writeln!(f, "    sub.w {arg0} {arg1} into {dest};"),
550            Self::Xor(arg0, arg1, dest) => writeln!(f, "    xor {arg0} {arg1} into {dest};"),
551        }
552    }
553}
554
555#[derive(Debug)]
556pub enum AleoType {
557    Future { name: String, program: String },
558    Record { name: String, program: Option<String> },
559    Ident { name: String },
560    Array { inner: Box<AleoType>, len: u32 },
561    GroupX,
562    GroupY,
563    Address,
564    Boolean,
565    Field,
566    Group,
567    I8,
568    I16,
569    I32,
570    I64,
571    I128,
572    U8,
573    U16,
574    U32,
575    U64,
576    U128,
577    Scalar,
578    Signature,
579    String,
580}
581impl Display for AleoType {
582    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
583        match self {
584            Self::Future { name, program } => write!(f, "{program}.aleo/{name}.future"),
585            Self::Record { name, program: Some(program_name) } => write!(f, "{program_name}.aleo/{name}.record"),
586            Self::Record { name, program: None } => write!(f, "{name}.record"),
587            Self::GroupX => write!(f, "group.x"),
588            Self::GroupY => write!(f, "group.y"),
589            Self::Ident { name } => write!(f, "{name}"),
590            Self::Address => write!(f, "address"),
591            Self::Boolean => write!(f, "boolean"),
592            Self::Field => write!(f, "field"),
593            Self::Group => write!(f, "group"),
594            Self::I8 => write!(f, "i8"),
595            Self::I16 => write!(f, "i16"),
596            Self::I32 => write!(f, "i32"),
597            Self::I64 => write!(f, "i64"),
598            Self::I128 => write!(f, "i128"),
599            Self::U8 => write!(f, "u8"),
600            Self::U16 => write!(f, "u16"),
601            Self::U32 => write!(f, "u32"),
602            Self::U64 => write!(f, "u64"),
603            Self::U128 => write!(f, "u128"),
604            Self::Scalar => write!(f, "scalar"),
605            Self::Signature => write!(f, "signature"),
606            Self::String => write!(f, "string"),
607            Self::Array { inner, len } => write!(f, "[{inner}; {len}u32]"),
608        }
609    }
610}
611impl<N: Network> From<PlaintextType<N>> for AleoType {
612    fn from(value: PlaintextType<N>) -> Self {
613        match value {
614            PlaintextType::Literal(lit) => lit.into(),
615            PlaintextType::Struct(id) => Self::Ident { name: id.to_string() },
616            PlaintextType::Array(arr) => arr.into(),
617        }
618    }
619}
620impl From<LiteralType> for AleoType {
621    fn from(value: LiteralType) -> Self {
622        match value {
623            LiteralType::Address => Self::Address,
624            LiteralType::Boolean => Self::Boolean,
625            LiteralType::Field => Self::Field,
626            LiteralType::Group => Self::Group,
627            LiteralType::I8 => Self::I8,
628            LiteralType::I16 => Self::I16,
629            LiteralType::I32 => Self::I32,
630            LiteralType::I64 => Self::I64,
631            LiteralType::I128 => Self::I128,
632            LiteralType::U8 => Self::U8,
633            LiteralType::U16 => Self::U16,
634            LiteralType::U32 => Self::U32,
635            LiteralType::U64 => Self::U64,
636            LiteralType::U128 => Self::U128,
637            LiteralType::Scalar => Self::Scalar,
638            LiteralType::Signature => Self::Signature,
639            LiteralType::String => Self::String,
640        }
641    }
642}
643impl<N: Network> From<ArrayType<N>> for AleoType {
644    fn from(value: ArrayType<N>) -> Self {
645        Self::Array { len: **value.length(), inner: Box::new(AleoType::from(value.next_element_type().clone())) }
646    }
647}
648
649#[derive(Hash, Eq, PartialEq, Clone, Debug)]
650pub enum AleoReg {
651    Self_,
652    Block,
653    Network,
654    R(u64),
655}
656impl Display for AleoReg {
657    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
658        match self {
659            Self::Self_ => write!(f, "self"),
660            Self::Block => write!(f, "block"),
661            Self::Network => write!(f, "network"),
662            Self::R(n) => write!(f, "r{n}"),
663        }
664    }
665}