cairo_lang_sierra/
fmt.rs

1use std::fmt;
2
3use cairo_lang_utils::write_comma_separated;
4
5use crate::ids::{
6    ConcreteLibfuncId, ConcreteTypeId, FunctionId, GenericLibfuncId, GenericTypeId, UserTypeId,
7    VarId,
8};
9use crate::program::{
10    ConcreteLibfuncLongId, ConcreteTypeLongId, Function, GenBranchInfo, GenBranchTarget,
11    GenInvocation, GenStatement, GenericArg, LibfuncDeclaration, Param, Program, StatementIdx,
12    TypeDeclaration,
13};
14
15impl fmt::Display for Program {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17        for declaration in &self.type_declarations {
18            writeln!(f, "{declaration};")?;
19        }
20        writeln!(f)?;
21        for declaration in &self.libfunc_declarations {
22            writeln!(f, "{declaration};")?;
23        }
24        writeln!(f)?;
25        for (i, statement) in self.statements.iter().enumerate() {
26            writeln!(f, "{statement}; // {i}")?;
27        }
28        writeln!(f)?;
29        for func in &self.funcs {
30            writeln!(f, "{func};")?;
31        }
32        Ok(())
33    }
34}
35
36impl fmt::Display for TypeDeclaration {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        let TypeDeclaration { id, long_id, declared_type_info } = self;
39        write!(f, "type {} = {}", id, long_id)?;
40        if let Some(info) = declared_type_info {
41            write!(
42                f,
43                " [storable: {:?}, drop: {:?}, dup: {:?}, zero_sized: {:?}]",
44                info.storable, info.droppable, info.duplicatable, info.zero_sized
45            )?;
46        }
47        Ok(())
48    }
49}
50
51impl fmt::Display for ConcreteTypeLongId {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        write!(f, "{}", self.generic_id)?;
54        write_template_args(f, &self.generic_args)
55    }
56}
57
58impl fmt::Display for LibfuncDeclaration {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        write!(f, "libfunc {} = {}", self.id, self.long_id)
61    }
62}
63
64impl fmt::Display for ConcreteLibfuncLongId {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        write!(f, "{}", self.generic_id)?;
67        write_template_args(f, &self.generic_args)
68    }
69}
70
71impl fmt::Display for Function {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        write!(f, "{}@{}(", self.id, self.entry_point.0)?;
74        write_comma_separated(f, &self.params)?;
75        write!(f, ") -> (")?;
76        write_comma_separated(f, &self.signature.ret_types)?;
77        write!(f, ")")
78    }
79}
80
81impl fmt::Display for Param {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        write!(f, "{}: {}", self.id, self.ty)
84    }
85}
86
87macro_rules! display_generic_identity {
88    ($type_name:tt) => {
89        impl fmt::Display for $type_name {
90            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91                write!(f, "{}", self.0)
92            }
93        }
94    };
95}
96
97display_generic_identity!(GenericLibfuncId);
98display_generic_identity!(GenericTypeId);
99
100macro_rules! display_identity {
101    ($type_name:tt) => {
102        impl fmt::Display for $type_name {
103            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104                match &self.debug_name {
105                    Some(name) => write!(f, "{name}"),
106                    None => write!(f, "[{}]", self.id),
107                }
108            }
109        }
110    };
111}
112
113display_identity!(ConcreteLibfuncId);
114display_identity!(FunctionId);
115display_identity!(UserTypeId);
116display_identity!(VarId);
117display_identity!(ConcreteTypeId);
118
119impl fmt::Display for GenericArg {
120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121        match self {
122            GenericArg::Type(id) => write!(f, "{id}"),
123            GenericArg::UserType(id) => write!(f, "ut@{id}"),
124            GenericArg::Value(v) => write!(f, "{v}"),
125            GenericArg::UserFunc(id) => write!(f, "user@{id}"),
126            GenericArg::Libfunc(id) => write!(f, "lib@{id}"),
127        }
128    }
129}
130
131impl<StatementId: fmt::Display> fmt::Display for GenStatement<StatementId> {
132    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133        match self {
134            GenStatement::Invocation(invocation) => write!(f, "{invocation}"),
135            GenStatement::Return(ids) => {
136                write!(f, "return(")?;
137                write_comma_separated(f, ids)?;
138                write!(f, ")")
139            }
140        }
141    }
142}
143
144impl<StatementId: fmt::Display> fmt::Display for GenInvocation<StatementId> {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146        write!(f, "{}(", self.libfunc_id)?;
147        write_comma_separated(f, &self.args)?;
148        if let [GenBranchInfo { target: GenBranchTarget::Fallthrough, results }] =
149            &self.branches[..]
150        {
151            write!(f, ") -> (")?;
152            write_comma_separated(f, results)?;
153            write!(f, ")")
154        } else {
155            write!(f, ") {{ ")?;
156            self.branches.iter().try_for_each(|branch_info| write!(f, "{branch_info} "))?;
157            write!(f, "}}")
158        }
159    }
160}
161
162impl<StatementId: fmt::Display> fmt::Display for GenBranchInfo<StatementId> {
163    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164        write!(f, "{}(", self.target)?;
165        write_comma_separated(f, &self.results)?;
166        write!(f, ")")
167    }
168}
169
170impl<StatementId: fmt::Display> fmt::Display for GenBranchTarget<StatementId> {
171    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172        match self {
173            GenBranchTarget::Fallthrough => write!(f, "fallthrough"),
174            GenBranchTarget::Statement(id) => write!(f, "{id}"),
175        }
176    }
177}
178
179impl fmt::Display for StatementIdx {
180    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181        write!(f, "{}", self.0)
182    }
183}
184
185fn write_template_args(f: &mut fmt::Formatter<'_>, args: &[GenericArg]) -> fmt::Result {
186    if args.is_empty() {
187        Ok(())
188    } else {
189        write!(f, "<")?;
190        write_comma_separated(f, args)?;
191        write!(f, ">")
192    }
193}