1use crate::ast::*;
4use std::fmt::Write;
5
6const INDENT_STEP: &str = " ";
7
8pub fn write_source_unit(source_unit: &SourceUnit) -> String {
9 let mut output = String::new();
10 let mut indent = String::new();
11
12 for item in &source_unit.items {
13 write_source_unit_item(&mut output, item, &mut indent);
14 writeln!(output).unwrap();
15 }
16
17 output.trim_end().to_string()
18}
19
20fn write_source_unit_item(output: &mut String, item: &SourceUnitItem, indent: &mut String) {
21 match item {
22 SourceUnitItem::Pragma(pragma) => write_pragma(output, pragma, indent),
23 SourceUnitItem::Import(import) => write_import(output, import, indent),
24 SourceUnitItem::Contract(contract) => write_contract(output, contract, indent),
25 SourceUnitItem::Interface(interface) => write_interface(output, interface, indent),
26 SourceUnitItem::Library(library) => write_library(output, library, indent),
27 SourceUnitItem::Function(function) => write_function(output, function, indent),
28 SourceUnitItem::ConstantVariable(var) => write_constant_variable(output, var, indent),
29 SourceUnitItem::Struct(struct_def) => write_struct(output, struct_def, indent),
30 SourceUnitItem::Enum(enum_def) => write_enum(output, enum_def, indent),
31 SourceUnitItem::Error(error_def) => write_error(output, error_def, indent),
32 SourceUnitItem::Event(event_def) => write_event(output, event_def, indent),
33 SourceUnitItem::Using(using_def) => write_using(output, using_def, indent),
34 }
35}
36
37fn write_pragma(output: &mut String, pragma: &PragmaDirective, indent: &str) {
38 write!(output, "{}pragma", indent).unwrap();
39 for token in &pragma.tokens {
40 write!(output, " {}", token).unwrap();
41 }
42 writeln!(output, ";").unwrap();
43}
44
45fn write_import(output: &mut String, import: &ImportDirective, indent: &str) {
46 write!(output, "{}import", indent).unwrap();
47
48 if let Some(symbols) = &import.symbols {
49 write!(output, " {{").unwrap();
50 for (i, symbol) in symbols.iter().enumerate() {
51 if i > 0 {
52 write!(output, ", ").unwrap();
53 }
54 write!(output, "{}", symbol.name).unwrap();
55 if let Some(alias) = &symbol.alias {
56 write!(output, " as {}", alias).unwrap();
57 }
58 }
59 write!(output, "}} from \"{}\"", import.path).unwrap();
60 } else if let Some(alias) = &import.alias {
61 write!(output, " * as {} from \"{}\"", alias, import.path).unwrap();
62 } else {
63 write!(output, " \"{}\"", import.path).unwrap();
64 }
65
66 writeln!(output, ";").unwrap();
67}
68
69fn write_contract(output: &mut String, contract: &ContractDefinition, indent: &mut String) {
70 if contract.is_abstract {
71 write!(output, "{}abstract ", indent).unwrap();
72 }
73 write!(output, "contract {}", contract.name).unwrap();
74
75 if !contract.inheritance.is_empty() {
76 write!(output, " is ").unwrap();
77 for (i, inheritance) in contract.inheritance.iter().enumerate() {
78 if i > 0 {
79 write!(output, ", ").unwrap();
80 }
81 write_identifier_path(output, &inheritance.name);
82 if let Some(args) = &inheritance.arguments {
83 write!(output, "(").unwrap();
84 write_expression_list(output, args);
85 write!(output, ")").unwrap();
86 }
87 }
88 }
89
90 writeln!(output, " {{").unwrap();
91
92 indent.push_str(INDENT_STEP);
93 for element in &contract.body {
94 write_contract_body_element(output, element, indent);
95 writeln!(output).unwrap();
96 }
97 indent.truncate(indent.len() - INDENT_STEP.len());
98
99 writeln!(output, "{}}}", indent).unwrap();
100}
101
102fn write_interface(output: &mut String, interface: &InterfaceDefinition, indent: &mut String) {
103 write!(output, "{}interface {}", indent, interface.name).unwrap();
104
105 if !interface.inheritance.is_empty() {
106 write!(output, " is ").unwrap();
107 for (i, inheritance) in interface.inheritance.iter().enumerate() {
108 if i > 0 {
109 write!(output, ", ").unwrap();
110 }
111 write_identifier_path(output, &inheritance.name);
112 if let Some(args) = &inheritance.arguments {
113 write!(output, "(").unwrap();
114 write_expression_list(output, args);
115 write!(output, ")").unwrap();
116 }
117 }
118 }
119
120 writeln!(output, " {{").unwrap();
121
122 indent.push_str(INDENT_STEP);
123 for element in &interface.body {
124 write_contract_body_element(output, element, indent);
125 writeln!(output).unwrap();
126 }
127 indent.truncate(indent.len() - INDENT_STEP.len());
128
129 writeln!(output, "{}}}", indent).unwrap();
130}
131
132fn write_library(output: &mut String, library: &LibraryDefinition, indent: &mut String) {
133 write!(output, "{}library {}", indent, library.name).unwrap();
134 writeln!(output, " {{").unwrap();
135
136 indent.push_str(INDENT_STEP);
137 for element in &library.body {
138 write_contract_body_element(output, element, indent);
139 writeln!(output).unwrap();
140 }
141 indent.truncate(indent.len() - INDENT_STEP.len());
142
143 writeln!(output, "{}}}", indent).unwrap();
144}
145
146fn write_contract_body_element(
147 output: &mut String,
148 element: &ContractBodyElement,
149 indent: &mut str,
150) {
151 match element {
152 ContractBodyElement::Constructor(constructor) => {
153 write_constructor(output, constructor, indent)
154 }
155 ContractBodyElement::Function(function) => write_function(output, function, indent),
156 ContractBodyElement::Modifier(modifier) => write_modifier(output, modifier, indent),
157 ContractBodyElement::StateVariable(var) => write_state_variable(output, var, indent),
158 ContractBodyElement::Event(event) => write_event(output, event, indent),
159 ContractBodyElement::Error(error) => write_error(output, error, indent),
160 ContractBodyElement::Struct(struct_def) => write_struct(output, struct_def, indent),
161 ContractBodyElement::Enum(enum_def) => write_enum(output, enum_def, indent),
162 ContractBodyElement::Using(using_def) => write_using(output, using_def, indent),
163 }
164}
165
166fn write_function(output: &mut String, function: &FunctionDefinition, indent: &str) {
167 write!(output, "{}function", indent).unwrap();
168
169 if let Some(name) = &function.name {
170 write!(output, " {}", name).unwrap();
171 }
172
173 write!(output, "(").unwrap();
174 write_parameter_list(output, &function.parameters);
175 write!(output, ")").unwrap();
176
177 if let Some(visibility) = &function.visibility {
178 write!(output, " {}", visibility.to_string()).unwrap();
179 }
180
181 if let Some(state_mutability) = &function.state_mutability {
182 write!(output, " {}", state_mutability.to_string()).unwrap();
183 }
184
185 if function.is_virtual {
186 write!(output, " virtual").unwrap();
187 }
188
189 if let Some(override_spec) = &function.override_specifier {
190 write!(output, " override").unwrap();
191 if !override_spec.overrides.is_empty() {
192 write!(output, "(").unwrap();
193 for (i, path) in override_spec.overrides.iter().enumerate() {
194 if i > 0 {
195 write!(output, ", ").unwrap();
196 }
197 write_identifier_path(output, path);
198 }
199 write!(output, ")").unwrap();
200 }
201 }
202
203 for modifier in &function.modifiers {
204 write!(output, " ").unwrap();
205 write_identifier_path(output, &modifier.name);
206 if let Some(args) = &modifier.arguments {
207 write!(output, "(").unwrap();
208 write_expression_list(output, args);
209 write!(output, ")").unwrap();
210 }
211 }
212
213 if let Some(returns) = &function.returns {
214 write!(output, " returns (").unwrap();
215 write_parameter_list(output, returns);
216 write!(output, ")").unwrap();
217 }
218
219 if let Some(body) = &function.body {
220 write!(output, " ").unwrap();
221 write_block(output, body, &mut indent.to_string());
222 } else {
223 writeln!(output, ";").unwrap();
224 }
225}
226
227fn write_constructor(output: &mut String, constructor: &ConstructorDefinition, indent: &str) {
228 write!(output, "{}constructor(", indent).unwrap();
229 write_parameter_list(output, &constructor.parameters);
230 write!(output, ")").unwrap();
231
232 if let Some(visibility) = &constructor.visibility {
233 write!(output, " {}", visibility.to_string()).unwrap();
234 }
235
236 if constructor.is_payable {
237 write!(output, " payable").unwrap();
238 }
239
240 for modifier in &constructor.modifiers {
241 write!(output, " ").unwrap();
242 write_identifier_path(output, &modifier.name);
243 if let Some(args) = &modifier.arguments {
244 write!(output, "(").unwrap();
245 write_expression_list(output, args);
246 write!(output, ")").unwrap();
247 }
248 }
249
250 write!(output, " ").unwrap();
251 write_block(output, &constructor.body, &mut indent.to_string());
252}
253
254fn write_modifier(output: &mut String, modifier: &ModifierDefinition, indent: &str) {
255 write!(output, "{}modifier {}(", indent, modifier.name).unwrap();
256 write_parameter_list(output, &modifier.parameters);
257 write!(output, ")").unwrap();
258
259 if modifier.is_virtual {
260 write!(output, " virtual").unwrap();
261 }
262
263 if let Some(override_spec) = &modifier.override_specifier {
264 write!(output, " override").unwrap();
265 if !override_spec.overrides.is_empty() {
266 write!(output, "(").unwrap();
267 for (i, path) in override_spec.overrides.iter().enumerate() {
268 if i > 0 {
269 write!(output, ", ").unwrap();
270 }
271 write_identifier_path(output, path);
272 }
273 write!(output, ")").unwrap();
274 }
275 }
276
277 if let Some(body) = &modifier.body {
278 write!(output, " ").unwrap();
279 write_block(output, body, &mut indent.to_string());
280 } else {
281 writeln!(output, ";").unwrap();
282 }
283}
284
285fn write_state_variable(output: &mut String, var: &StateVariableDeclaration, indent: &str) {
286 write!(output, "{}", indent).unwrap();
287 write_type_name(output, &var.type_name);
288
289 if let Some(visibility) = &var.visibility {
290 write!(output, " {}", visibility.to_string()).unwrap();
291 }
292
293 if var.is_constant {
294 write!(output, " constant").unwrap();
295 }
296
297 if var.is_immutable {
298 write!(output, " immutable").unwrap();
299 }
300
301 if var.is_transient {
302 write!(output, " transient").unwrap();
303 }
304
305 if let Some(override_spec) = &var.override_specifier {
306 write!(output, " override").unwrap();
307 if !override_spec.overrides.is_empty() {
308 write!(output, "(").unwrap();
309 for (i, path) in override_spec.overrides.iter().enumerate() {
310 if i > 0 {
311 write!(output, ", ").unwrap();
312 }
313 write_identifier_path(output, path);
314 }
315 write!(output, ")").unwrap();
316 }
317 }
318
319 write!(output, " {}", var.name).unwrap();
320
321 if let Some(initial_value) = &var.initial_value {
322 write!(output, " = ").unwrap();
323 write_expression(output, initial_value);
324 }
325
326 writeln!(output, ";").unwrap();
327}
328
329fn write_constant_variable(output: &mut String, var: &ConstantVariableDeclaration, indent: &str) {
330 write!(output, "{}", indent).unwrap();
331 write_type_name(output, &var.type_name);
332 write!(output, " constant {} = ", var.name).unwrap();
333 write_expression(output, &var.initial_value);
334 writeln!(output, ";").unwrap();
335}
336
337fn write_struct(output: &mut String, struct_def: &StructDefinition, indent: &str) {
338 writeln!(output, "{}struct {} {{", indent, struct_def.name).unwrap();
339
340 let mut inner_indent = indent.to_string();
341 inner_indent.push_str(INDENT_STEP);
342
343 for member in &struct_def.members {
344 write!(output, "{}", inner_indent).unwrap();
345 write_type_name(output, &member.type_name);
346 writeln!(output, " {};", member.name).unwrap();
347 }
348
349 writeln!(output, "{}}}", indent).unwrap();
350}
351
352fn write_enum(output: &mut String, enum_def: &EnumDefinition, indent: &str) {
353 write!(output, "{}enum {} {{ ", indent, enum_def.name).unwrap();
354 for (i, value) in enum_def.values.iter().enumerate() {
355 if i > 0 {
356 write!(output, ", ").unwrap();
357 }
358 write!(output, "{}", value).unwrap();
359 }
360 writeln!(output, " }}").unwrap();
361}
362
363fn write_event(output: &mut String, event: &EventDefinition, indent: &str) {
365 write!(output, "{}event {}(", indent, event.name).unwrap();
366
367 for (i, param) in event.parameters.iter().enumerate() {
368 if i > 0 {
369 write!(output, ", ").unwrap();
370 }
371 write_type_name(output, ¶m.type_name);
372 if param.is_indexed {
373 write!(output, " indexed").unwrap();
374 }
375 if let Some(name) = ¶m.name {
376 write!(output, " {}", name).unwrap();
377 }
378 }
379
380 write!(output, ")").unwrap();
381
382 if event.is_anonymous {
383 write!(output, " anonymous").unwrap();
384 }
385
386 writeln!(output, ";").unwrap();
387}
388
389fn write_error(output: &mut String, error: &ErrorDefinition, indent: &str) {
390 write!(output, "{}error {}(", indent, error.name).unwrap();
391
392 for (i, param) in error.parameters.iter().enumerate() {
393 if i > 0 {
394 write!(output, ", ").unwrap();
395 }
396 write_type_name(output, ¶m.type_name);
397 if let Some(name) = ¶m.name {
398 write!(output, " {}", name).unwrap();
399 }
400 }
401
402 writeln!(output, ");").unwrap();
403}
404
405fn write_using(output: &mut String, using: &UsingDirective, indent: &str) {
406 write!(output, "{}using ", indent).unwrap();
407 write_identifier_path(output, &using.library);
408 write!(output, " for").unwrap();
409
410 if let Some(type_name) = &using.type_name {
411 write!(output, " ").unwrap();
412 write_type_name(output, type_name);
413 } else {
414 write!(output, " *").unwrap();
415 }
416
417 if using.is_global {
418 write!(output, " global").unwrap();
419 }
420
421 writeln!(output, ";").unwrap();
422}
423
424fn write_parameter_list(output: &mut String, parameters: &[Parameter]) {
425 for (i, param) in parameters.iter().enumerate() {
426 if i > 0 {
427 write!(output, ", ").unwrap();
428 }
429 write_type_name(output, ¶m.type_name);
430 if let Some(data_location) = ¶m.data_location {
431 write!(output, " {}", data_location.to_string()).unwrap();
432 }
433 if let Some(name) = ¶m.name {
434 write!(output, " {}", name).unwrap();
435 }
436 }
437}
438
439fn write_type_name(output: &mut String, type_name: &TypeName) {
440 match type_name {
441 TypeName::Elementary(elem) => write_elementary_type(output, elem),
442 TypeName::UserDefined(path) => write_identifier_path(output, path),
443 TypeName::Array(base_type, size) => {
444 write_type_name(output, base_type);
445 write!(output, "[").unwrap();
446 if let Some(size_expr) = size {
447 write_expression(output, size_expr);
448 }
449 write!(output, "]").unwrap();
450 }
451 TypeName::Mapping(mapping) => {
452 write!(output, "mapping(").unwrap();
453 write_type_name(output, &mapping.key_type);
454 if let Some(key_name) = &mapping.key_name {
455 write!(output, " {}", key_name).unwrap();
456 }
457 write!(output, " => ").unwrap();
458 write_type_name(output, &mapping.value_type);
459 if let Some(value_name) = &mapping.value_name {
460 write!(output, " {}", value_name).unwrap();
461 }
462 write!(output, ")").unwrap();
463 }
464 TypeName::Function(func_type) => {
465 write!(output, "function(").unwrap();
466 write_parameter_list(output, &func_type.parameters);
467 write!(output, ")").unwrap();
468
469 if let Some(visibility) = &func_type.visibility {
470 write!(output, " {}", visibility.to_string()).unwrap();
471 }
472
473 if let Some(state_mutability) = &func_type.state_mutability {
474 write!(output, " {}", state_mutability.to_string()).unwrap();
475 }
476
477 if let Some(returns) = &func_type.returns {
478 write!(output, " returns (").unwrap();
479 write_parameter_list(output, returns);
480 write!(output, ")").unwrap();
481 }
482 }
483 }
484}
485
486fn write_elementary_type(output: &mut String, elem_type: &ElementaryTypeName) {
487 match elem_type {
488 ElementaryTypeName::Address => write!(output, "address").unwrap(),
489 ElementaryTypeName::AddressPayable => write!(output, "address payable").unwrap(),
490 ElementaryTypeName::Bool => write!(output, "bool").unwrap(),
491 ElementaryTypeName::String => write!(output, "string").unwrap(),
492 ElementaryTypeName::Bytes => write!(output, "bytes").unwrap(),
493 ElementaryTypeName::SignedInteger(size) => {
494 write!(output, "int").unwrap();
495 if let Some(bits) = size {
496 write!(output, "{}", bits).unwrap();
497 }
498 }
499 ElementaryTypeName::UnsignedInteger(size) => {
500 write!(output, "uint").unwrap();
501 if let Some(bits) = size {
502 write!(output, "{}", bits).unwrap();
503 }
504 }
505 ElementaryTypeName::FixedBytes(size) => {
506 write!(output, "bytes").unwrap();
507 if let Some(bytes) = size {
508 write!(output, "{}", bytes).unwrap();
509 }
510 }
511 ElementaryTypeName::Fixed => write!(output, "fixed").unwrap(),
512 ElementaryTypeName::Ufixed => write!(output, "ufixed").unwrap(),
513 }
514}
515
516fn write_identifier_path(output: &mut String, path: &IdentifierPath) {
517 for (i, part) in path.parts.iter().enumerate() {
518 if i > 0 {
519 write!(output, ".").unwrap();
520 }
521 write!(output, "{}", part).unwrap();
522 }
523}
524
525fn write_expression_list(output: &mut String, expressions: &[Expression]) {
526 for (i, expr) in expressions.iter().enumerate() {
527 if i > 0 {
528 write!(output, ", ").unwrap();
529 }
530 write_expression(output, expr);
531 }
532}
533
534fn write_expression(output: &mut String, expression: &Expression) {
535 match expression {
536 Expression::Identifier(name) => write!(output, "{}", name).unwrap(),
537 Expression::Literal(literal) => write_literal(output, literal),
538 Expression::Binary(binary) => {
539 write_expression(output, &binary.left);
540 write!(output, " {} ", binary.operator.to_string()).unwrap();
541 write_expression(output, &binary.right);
542 }
543 Expression::Unary(unary) => {
544 if unary.is_prefix {
545 write!(output, "{}", unary.operator.to_string()).unwrap();
546 write_expression(output, &unary.operand);
547 } else {
548 write_expression(output, &unary.operand);
549 write!(output, "{}", unary.operator.to_string()).unwrap();
550 }
551 }
552 Expression::FunctionCall(call) => {
553 write_expression(output, &call.function);
554 write!(output, "(").unwrap();
555 write_expression_list(output, &call.arguments);
556 write!(output, ")").unwrap();
557 }
558 Expression::MemberAccess(access) => {
559 write_expression(output, &access.object);
560 write!(output, ".{}", access.member).unwrap();
561 }
562 Expression::IndexAccess(access) => {
563 write_expression(output, &access.object);
564 write!(output, "[").unwrap();
565 if let Some(index) = &access.index {
566 write_expression(output, index);
567 }
568 write!(output, "]").unwrap();
569 }
570 Expression::Conditional(conditional) => {
571 write_expression(output, &conditional.condition);
572 write!(output, " ? ").unwrap();
573 write_expression(output, &conditional.true_expr);
574 write!(output, " : ").unwrap();
575 write_expression(output, &conditional.false_expr);
576 }
577 Expression::Assignment(assignment) => {
578 write_expression(output, &assignment.left);
579 write!(output, " {} ", assignment.operator.to_string()).unwrap();
580 write_expression(output, &assignment.right);
581 }
582 Expression::Tuple(tuple) => {
583 write!(output, "(").unwrap();
584 for (i, element) in tuple.elements.iter().enumerate() {
585 if i > 0 {
586 write!(output, ", ").unwrap();
587 }
588 if let Some(expr) = element {
589 write_expression(output, expr);
590 }
591 }
592 write!(output, ")").unwrap();
593 }
594 Expression::Array(array) => {
595 write!(output, "[").unwrap();
596 write_expression_list(output, &array.elements);
597 write!(output, "]").unwrap();
598 }
599 Expression::TypeConversion(conversion) => {
600 write_type_name(output, &conversion.type_name);
601 write!(output, "(").unwrap();
602 write_expression(output, &conversion.expression);
603 write!(output, ")").unwrap();
604 }
605 Expression::New(new_expr) => {
606 write!(output, "new ").unwrap();
607 write_type_name(output, &new_expr.type_name);
608 }
609 }
610}
611
612fn write_literal(output: &mut String, literal: &Literal) {
613 match literal {
614 Literal::Boolean(value) => write!(output, "{}", value).unwrap(),
615 Literal::Number(number) => {
616 write!(output, "{}", number.value).unwrap();
617 if let Some(sub_denom) = &number.sub_denomination {
618 write!(output, " {}", sub_denom).unwrap();
619 }
620 }
621 Literal::String(string) => write!(output, "\"{}\"", string.value).unwrap(),
622 Literal::HexString(hex_string) => write!(output, "hex\"{}\"", hex_string.value).unwrap(),
623 Literal::UnicodeString(unicode_string) => {
624 write!(output, "unicode\"{}\"", unicode_string.value).unwrap()
625 }
626 }
627}
628
629fn write_block(output: &mut String, block: &Block, indent: &mut String) {
630 writeln!(output, "{{").unwrap();
631
632 indent.push_str(INDENT_STEP);
633 for statement in &block.statements {
634 write_statement(output, statement, indent);
635 }
636 indent.truncate(indent.len() - INDENT_STEP.len());
637
638 writeln!(output, "{}}}", indent).unwrap();
639}
640
641fn write_statement(output: &mut String, statement: &Statement, indent: &str) {
643 match statement {
644 Statement::Block(block) => {
645 write!(output, "{}", indent).unwrap();
646 write_block(output, block, &mut indent.to_string());
647 }
648 Statement::Expression(expr_stmt) => {
649 write!(output, "{}", indent).unwrap();
650 write_expression(output, &expr_stmt.expression);
651 writeln!(output, ";").unwrap();
652 }
653 Statement::Variable(var_stmt) => {
654 write!(output, "{}", indent).unwrap();
655 write_type_name(output, &var_stmt.declaration.type_name);
656 if let Some(data_location) = &var_stmt.declaration.data_location {
657 write!(output, " {}", data_location.to_string()).unwrap();
658 }
659 write!(output, " {}", var_stmt.declaration.name).unwrap();
660 if let Some(initial_value) = &var_stmt.initial_value {
661 write!(output, " = ").unwrap();
662 write_expression(output, initial_value);
663 }
664 writeln!(output, ";").unwrap();
665 }
666 Statement::If(if_stmt) => {
667 write!(output, "{}if (", indent).unwrap();
668 write_expression(output, &if_stmt.condition);
669 write!(output, ") ").unwrap();
670 write_statement(output, &if_stmt.then_statement, "");
671 if let Some(else_stmt) = &if_stmt.else_statement {
672 write!(output, " else ").unwrap();
673 write_statement(output, else_stmt, "");
674 }
675 }
676 Statement::For(for_stmt) => {
677 write!(output, "{}for (", indent).unwrap();
678 if let Some(init) = &for_stmt.init {
679 write_statement(output, init, "");
680 } else {
681 write!(output, ";").unwrap();
682 }
683 write!(output, " ").unwrap();
684 if let Some(condition) = &for_stmt.condition {
685 write_expression(output, condition);
686 }
687 write!(output, "; ").unwrap();
688 if let Some(update) = &for_stmt.update {
689 write_expression(output, update);
690 }
691 write!(output, ") ").unwrap();
692 write_statement(output, &for_stmt.body, "");
693 }
694 Statement::While(while_stmt) => {
695 write!(output, "{}while (", indent).unwrap();
696 write_expression(output, &while_stmt.condition);
697 write!(output, ") ").unwrap();
698 write_statement(output, &while_stmt.body, "");
699 }
700 Statement::DoWhile(do_while_stmt) => {
701 write!(output, "{}do ", indent).unwrap();
702 write_statement(output, &do_while_stmt.body, "");
703 write!(output, " while (").unwrap();
704 write_expression(output, &do_while_stmt.condition);
705 writeln!(output, ");").unwrap();
706 }
707 Statement::Continue(_) => writeln!(output, "{}continue;", indent).unwrap(),
708 Statement::Break(_) => writeln!(output, "{}break;", indent).unwrap(),
709 Statement::Return(return_stmt) => {
710 write!(output, "{}return", indent).unwrap();
711 if let Some(expr) = &return_stmt.expression {
712 write!(output, " ").unwrap();
713 write_expression(output, expr);
714 }
715 writeln!(output, ";").unwrap();
716 }
717 Statement::Emit(emit_stmt) => {
718 write!(output, "{}emit ", indent).unwrap();
719 write_expression(output, &emit_stmt.event_call);
720 writeln!(output, ";").unwrap();
721 }
722 Statement::Revert(revert_stmt) => {
723 write!(output, "{}revert ", indent).unwrap();
724 write_expression(output, &revert_stmt.error_call);
725 writeln!(output, ";").unwrap();
726 }
727 Statement::Try(try_stmt) => {
728 write!(output, "{}try ", indent).unwrap();
729 write_expression(output, &try_stmt.expression);
730 if let Some(returns) = &try_stmt.returns {
731 write!(output, " returns (").unwrap();
732 write_parameter_list(output, returns);
733 write!(output, ")").unwrap();
734 }
735 write!(output, " ").unwrap();
736 write_block(output, &try_stmt.body, &mut indent.to_string());
737 for catch_clause in &try_stmt.catch_clauses {
738 write!(output, " catch").unwrap();
739 if let Some(identifier) = &catch_clause.identifier {
740 write!(output, " {}", identifier).unwrap();
741 }
742 if let Some(parameters) = &catch_clause.parameters {
743 write!(output, "(").unwrap();
744 write_parameter_list(output, parameters);
745 write!(output, ")").unwrap();
746 }
747 write!(output, " ").unwrap();
748 write_block(output, &catch_clause.body, &mut indent.to_string());
749 }
750 }
751 Statement::Assembly(assembly_stmt) => {
752 write!(output, "{}assembly", indent).unwrap();
753 if let Some(dialect) = &assembly_stmt.dialect {
754 write!(output, " \"{}\"", dialect).unwrap();
755 }
756 for flag in &assembly_stmt.flags {
757 write!(output, " (\"{}\"))", flag).unwrap();
758 }
759 write!(output, " ").unwrap();
760 write_yul_block(output, &assembly_stmt.body, &mut indent.to_string());
761 }
762 Statement::Unchecked(unchecked_stmt) => {
763 write!(output, "{}unchecked ", indent).unwrap();
764 write_block(output, &unchecked_stmt.body, &mut indent.to_string());
765 }
766 }
767}
768
769fn write_yul_block(output: &mut String, block: &YulBlock, indent: &mut String) {
770 writeln!(output, "{{").unwrap();
771
772 indent.push_str(INDENT_STEP);
773 for statement in &block.statements {
774 write_yul_statement(output, statement, indent);
775 }
776 indent.truncate(indent.len() - INDENT_STEP.len());
777
778 writeln!(output, "{}}}", indent).unwrap();
779}
780
781fn write_yul_statement(output: &mut String, statement: &YulStatement, indent: &str) {
782 match statement {
783 YulStatement::Block(block) => {
784 write!(output, "{}", indent).unwrap();
785 write_yul_block(output, block, &mut indent.to_string());
786 }
787 YulStatement::VariableDeclaration(var_decl) => {
788 write!(output, "{}let ", indent).unwrap();
789 for (i, var) in var_decl.variables.iter().enumerate() {
790 if i > 0 {
791 write!(output, ", ").unwrap();
792 }
793 write!(output, "{}", var).unwrap();
794 }
795 if let Some(expr) = &var_decl.expression {
796 write!(output, " := ").unwrap();
797 write_yul_expression(output, expr);
798 }
799 writeln!(output).unwrap();
800 }
801 YulStatement::Assignment(assignment) => {
802 write!(output, "{}", indent).unwrap();
803 for (i, var) in assignment.variables.iter().enumerate() {
804 if i > 0 {
805 write!(output, ", ").unwrap();
806 }
807 write_yul_path(output, var);
808 }
809 write!(output, " := ").unwrap();
810 write_yul_expression(output, &assignment.expression);
811 writeln!(output).unwrap();
812 }
813 YulStatement::FunctionCall(call) => {
814 write!(output, "{}", indent).unwrap();
815 write_yul_function_call(output, call);
816 writeln!(output).unwrap();
817 }
818 YulStatement::If(if_stmt) => {
819 write!(output, "{}if ", indent).unwrap();
820 write_yul_expression(output, &if_stmt.condition);
821 write!(output, " ").unwrap();
822 write_yul_block(output, &if_stmt.body, &mut indent.to_string());
823 }
824 YulStatement::For(for_stmt) => {
825 write!(output, "{}for ", indent).unwrap();
826 write_yul_block(output, &for_stmt.init, &mut indent.to_string());
827 write!(output, " ").unwrap();
828 write_yul_expression(output, &for_stmt.condition);
829 write!(output, " ").unwrap();
830 write_yul_block(output, &for_stmt.post, &mut indent.to_string());
831 write!(output, " ").unwrap();
832 write_yul_block(output, &for_stmt.body, &mut indent.to_string());
833 }
834 YulStatement::Switch(switch_stmt) => {
835 write!(output, "{}switch ", indent).unwrap();
836 write_yul_expression(output, &switch_stmt.expression);
837 writeln!(output).unwrap();
838 for case in &switch_stmt.cases {
839 write!(output, "{}case ", indent).unwrap();
840 write_yul_literal(output, &case.value);
841 write!(output, " ").unwrap();
842 write_yul_block(output, &case.body, &mut indent.to_string());
843 }
844 if let Some(default) = &switch_stmt.default {
845 write!(output, "{}default ", indent).unwrap();
846 write_yul_block(output, default, &mut indent.to_string());
847 }
848 }
849 YulStatement::FunctionDefinition(func_def) => {
850 write!(output, "{}function {}(", indent, func_def.name).unwrap();
851 for (i, param) in func_def.parameters.iter().enumerate() {
852 if i > 0 {
853 write!(output, ", ").unwrap();
854 }
855 write!(output, "{}", param).unwrap();
856 }
857 write!(output, ")").unwrap();
858 if !func_def.returns.is_empty() {
859 write!(output, " -> ").unwrap();
860 for (i, ret) in func_def.returns.iter().enumerate() {
861 if i > 0 {
862 write!(output, ", ").unwrap();
863 }
864 write!(output, "{}", ret).unwrap();
865 }
866 }
867 write!(output, " ").unwrap();
868 write_yul_block(output, &func_def.body, &mut indent.to_string());
869 }
870 YulStatement::Leave => writeln!(output, "{}leave", indent).unwrap(),
871 YulStatement::Break => writeln!(output, "{}break", indent).unwrap(),
872 YulStatement::Continue => writeln!(output, "{}continue", indent).unwrap(),
873 }
874}
875
876fn write_yul_expression(output: &mut String, expression: &YulExpression) {
877 match expression {
878 YulExpression::Path(path) => write_yul_path(output, path),
879 YulExpression::FunctionCall(call) => write_yul_function_call(output, call),
880 YulExpression::Literal(literal) => write_yul_literal(output, literal),
881 }
882}
883
884fn write_yul_path(output: &mut String, path: &YulPath) {
885 for (i, part) in path.parts.iter().enumerate() {
886 if i > 0 {
887 write!(output, ".").unwrap();
888 }
889 write!(output, "{}", part).unwrap();
890 }
891}
892
893fn write_yul_function_call(output: &mut String, call: &YulFunctionCall) {
894 write!(output, "{}(", call.function).unwrap();
895 for (i, arg) in call.arguments.iter().enumerate() {
896 if i > 0 {
897 write!(output, ", ").unwrap();
898 }
899 write_yul_expression(output, arg);
900 }
901 write!(output, ")").unwrap();
902}
903
904fn write_yul_literal(output: &mut String, literal: &YulLiteral) {
905 match literal {
906 YulLiteral::Number(value) => write!(output, "{}", value).unwrap(),
907 YulLiteral::String(value) => write!(output, "\"{}\"", value).unwrap(),
908 YulLiteral::HexNumber(value) => write!(output, "{}", value).unwrap(),
909 YulLiteral::Boolean(value) => write!(output, "{}", value).unwrap(),
910 YulLiteral::HexString(value) => write!(output, "hex\"{}\"", value).unwrap(),
911 }
912}
913
914impl Visibility {
915 pub fn to_string(&self) -> &'static str {
916 match self {
917 Visibility::Public => "public",
918 Visibility::Private => "private",
919 Visibility::Internal => "internal",
920 Visibility::External => "external",
921 }
922 }
923}
924
925impl StateMutability {
926 pub fn to_string(&self) -> &'static str {
927 match self {
928 StateMutability::Pure => "pure",
929 StateMutability::View => "view",
930 StateMutability::Payable => "payable",
931 }
932 }
933}
934
935impl DataLocation {
936 pub fn to_string(&self) -> &'static str {
937 match self {
938 DataLocation::Memory => "memory",
939 DataLocation::Storage => "storage",
940 DataLocation::Calldata => "calldata",
941 }
942 }
943}
944
945impl BinaryOperator {
946 pub fn to_string(&self) -> &'static str {
947 match self {
948 BinaryOperator::Add => "+",
949 BinaryOperator::Sub => "-",
950 BinaryOperator::Mul => "*",
951 BinaryOperator::Div => "/",
952 BinaryOperator::Mod => "%",
953 BinaryOperator::Exp => "**",
954 BinaryOperator::Equal => "==",
955 BinaryOperator::NotEqual => "!=",
956 BinaryOperator::LessThan => "<",
957 BinaryOperator::LessThanOrEqual => "<=",
958 BinaryOperator::GreaterThan => ">",
959 BinaryOperator::GreaterThanOrEqual => ">=",
960 BinaryOperator::And => "&&",
961 BinaryOperator::Or => "||",
962 BinaryOperator::BitAnd => "&",
963 BinaryOperator::BitOr => "|",
964 BinaryOperator::BitXor => "^",
965 BinaryOperator::ShiftLeft => "<<",
966 BinaryOperator::ShiftRight => ">>",
967 BinaryOperator::ShiftRightArithmetic => ">>>",
968 }
969 }
970}
971
972impl UnaryOperator {
973 pub fn to_string(&self) -> &'static str {
974 match self {
975 UnaryOperator::Plus => "+",
976 UnaryOperator::Minus => "-",
977 UnaryOperator::Not => "!",
978 UnaryOperator::BitNot => "~",
979 UnaryOperator::Increment => "++",
980 UnaryOperator::Decrement => "--",
981 UnaryOperator::Delete => "delete ",
982 }
983 }
984}
985
986impl AssignmentOperator {
987 pub fn to_string(&self) -> &'static str {
988 match self {
989 AssignmentOperator::Assign => "=",
990 AssignmentOperator::AddAssign => "+=",
991 AssignmentOperator::SubAssign => "-=",
992 AssignmentOperator::MulAssign => "*=",
993 AssignmentOperator::DivAssign => "/=",
994 AssignmentOperator::ModAssign => "%=",
995 AssignmentOperator::BitAndAssign => "&=",
996 AssignmentOperator::BitOrAssign => "|=",
997 AssignmentOperator::BitXorAssign => "^=",
998 AssignmentOperator::ShiftLeftAssign => "<<=",
999 AssignmentOperator::ShiftRightAssign => ">>=",
1000 AssignmentOperator::ShiftRightArithmeticAssign => ">>>=",
1001 }
1002 }
1003}
1004
1005pub fn write_expression_to_string(expression: &Expression) -> String {
1006 let mut output = String::new();
1007 write_expression(&mut output, expression);
1008 output
1009}
1010
1011pub fn write_literal_to_string(literal: &Literal) -> String {
1012 let mut output = String::new();
1013 write_literal(&mut output, literal);
1014 output
1015}
1016
1017pub fn write_type_name_to_string(type_name: &TypeName) -> String {
1018 let mut output = String::new();
1019 write_type_name(&mut output, type_name);
1020 output
1021}
1022
1023pub fn format_value_for_expression(value: &crate::interpreter::Value) -> String {
1024 use crate::interpreter::Value;
1025 match value {
1026 Value::Bool(b) => b.to_string(),
1027 Value::UInt(n) => n.to_string(),
1028 Value::Int(n) => n.to_string(),
1029 Value::String(s) => format!("\"{}\"", s),
1030 Value::Address(addr) => addr.clone(),
1031 Value::Bytes(b) => format!("0x{}", hex::encode(b)),
1032 Value::Null => "null".to_string(),
1033 }
1034}