Skip to main content

leo_passes/code_generation/
mod.rs

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