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}