1use crate::lcnf::*;
12
13use super::types::{FStringPart, PythonExpr};
14use std::fmt;
15
16impl fmt::Display for PythonExpr {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 match self {
19 PythonExpr::Lit(lit) => write!(f, "{}", lit),
20 PythonExpr::Var(name) => write!(f, "{}", name),
21 PythonExpr::BinOp(op, lhs, rhs) => write!(f, "({} {} {})", lhs, op, rhs),
22 PythonExpr::UnaryOp(op, expr) => {
23 if *op == "not" {
24 write!(f, "not {}", expr)
25 } else {
26 write!(f, "{}{}", op, expr)
27 }
28 }
29 PythonExpr::Call(func, args, kwargs) => {
30 write!(f, "{}(", func)?;
31 let mut first = true;
32 for a in args {
33 if !first {
34 write!(f, ", ")?;
35 }
36 write!(f, "{}", a)?;
37 first = false;
38 }
39 for (k, v) in kwargs {
40 if !first {
41 write!(f, ", ")?;
42 }
43 write!(f, "{}={}", k, v)?;
44 first = false;
45 }
46 write!(f, ")")
47 }
48 PythonExpr::Attr(obj, field) => write!(f, "{}.{}", obj, field),
49 PythonExpr::Subscript(obj, idx) => write!(f, "{}[{}]", obj, idx),
50 PythonExpr::Lambda(params, body) => {
51 write!(f, "lambda ")?;
52 for (i, p) in params.iter().enumerate() {
53 if i > 0 {
54 write!(f, ", ")?;
55 }
56 write!(f, "{}", p)?;
57 }
58 write!(f, ": {}", body)
59 }
60 PythonExpr::IfExpr(then_e, cond, else_e) => {
61 write!(f, "{} if {} else {}", then_e, cond, else_e)
62 }
63 PythonExpr::ListComp(expr, var, iter, cond) => {
64 write!(f, "[{} for {} in {}", expr, var, iter)?;
65 if let Some(c) = cond {
66 write!(f, " if {}", c)?;
67 }
68 write!(f, "]")
69 }
70 PythonExpr::DictComp(key, val, k_var, v_var, iter) => {
71 write!(
72 f,
73 "{{{}: {} for {}, {} in {}}}",
74 key, val, k_var, v_var, iter
75 )
76 }
77 PythonExpr::SetComp(expr, var, iter, cond) => {
78 write!(f, "{{{} for {} in {}", expr, var, iter)?;
79 if let Some(c) = cond {
80 write!(f, " if {}", c)?;
81 }
82 write!(f, "}}")
83 }
84 PythonExpr::GenExpr(expr, var, iter, cond) => {
85 write!(f, "({} for {} in {}", expr, var, iter)?;
86 if let Some(c) = cond {
87 write!(f, " if {}", c)?;
88 }
89 write!(f, ")")
90 }
91 PythonExpr::Tuple(elems) => {
92 if elems.is_empty() {
93 write!(f, "()")
94 } else if elems.len() == 1 {
95 write!(f, "({},)", elems[0])
96 } else {
97 write!(f, "(")?;
98 for (i, e) in elems.iter().enumerate() {
99 if i > 0 {
100 write!(f, ", ")?;
101 }
102 write!(f, "{}", e)?;
103 }
104 write!(f, ")")
105 }
106 }
107 PythonExpr::List(elems) => {
108 write!(f, "[")?;
109 for (i, e) in elems.iter().enumerate() {
110 if i > 0 {
111 write!(f, ", ")?;
112 }
113 write!(f, "{}", e)?;
114 }
115 write!(f, "]")
116 }
117 PythonExpr::Dict(pairs) => {
118 write!(f, "{{")?;
119 for (i, (k, v)) in pairs.iter().enumerate() {
120 if i > 0 {
121 write!(f, ", ")?;
122 }
123 write!(f, "{}: {}", k, v)?;
124 }
125 write!(f, "}}")
126 }
127 PythonExpr::Set(elems) => {
128 if elems.is_empty() {
129 write!(f, "set()")
130 } else {
131 write!(f, "{{")?;
132 for (i, e) in elems.iter().enumerate() {
133 if i > 0 {
134 write!(f, ", ")?;
135 }
136 write!(f, "{}", e)?;
137 }
138 write!(f, "}}")
139 }
140 }
141 PythonExpr::Await(expr) => write!(f, "await {}", expr),
142 PythonExpr::Yield(expr) => match expr {
143 Some(e) => write!(f, "yield {}", e),
144 None => write!(f, "yield"),
145 },
146 PythonExpr::YieldFrom(expr) => write!(f, "yield from {}", expr),
147 PythonExpr::Match(expr) => write!(f, "{}", expr),
148 PythonExpr::FString(parts) => {
149 write!(f, "f\"")?;
150 for part in parts {
151 match part {
152 FStringPart::Literal(s) => {
153 for c in s.chars() {
154 match c {
155 '"' => write!(f, "\\\"")?,
156 '{' => write!(f, "{{")?,
157 '}' => write!(f, "}}")?,
158 '\\' => write!(f, "\\\\")?,
159 '\n' => write!(f, "\\n")?,
160 c => write!(f, "{}", c)?,
161 }
162 }
163 }
164 FStringPart::Expr(e) => write!(f, "{{{}}}", e)?,
165 FStringPart::ExprWithFormat(e, spec) => write!(f, "{{{}:{}}}", e, spec)?,
166 }
167 }
168 write!(f, "\"")
169 }
170 PythonExpr::Walrus(name, expr) => write!(f, "({} := {})", name, expr),
171 PythonExpr::Star(expr) => write!(f, "*{}", expr),
172 PythonExpr::DoubleStar(expr) => write!(f, "**{}", expr),
173 PythonExpr::Slice(start, stop, step) => {
174 if let Some(s) = start {
175 write!(f, "{}", s)?;
176 }
177 write!(f, ":")?;
178 if let Some(s) = stop {
179 write!(f, "{}", s)?;
180 }
181 if let Some(s) = step {
182 write!(f, ":{}", s)?;
183 }
184 Ok(())
185 }
186 }
187 }
188}