1use std::fmt::{self, Display, Write};
31
32use crate::{Attribute, BaseType, Formatter, FunctionParam, MethodParam, Type};
33
34#[derive(Debug, Clone)]
36pub enum Expr {
37 Variable {
39 name: String,
40 ty: Type,
41 },
42 ConstNum(u64),
44 ConstString(String),
45 ConstBool(bool),
46 NewObject {
47 name: String,
48 args: Vec<Expr>,
49 },
50 DeleteObject {
51 var: Box<Expr>,
52 },
53 FnCall {
55 name: String,
56 args: Vec<Expr>,
57 },
58 MethodCall {
60 var: Box<Expr>,
61 method: String,
62 args: Vec<Expr>,
63 is_ptr: bool,
64 },
65 Deref(Box<Expr>),
67 AddrOf(Box<Expr>),
69 SizeOf(Box<Expr>),
71 FieldAccess {
73 var: Box<Expr>,
74 field: String,
75 is_ptr: bool,
76 },
77 ArrayElementAccess {
78 var: Box<Expr>,
79 idx: Box<Expr>,
80 is_ptr: bool,
81 },
82 BinOp {
84 lhs: Box<Expr>,
85 rhs: Box<Expr>,
86 op: String,
87 },
88 UnOp {
90 expr: Box<Expr>,
91 op: String,
92 },
93 Ternary {
95 cond: Box<Expr>,
96 then: Box<Expr>,
97 other: Box<Expr>,
98 },
99 Cast {
100 expr: Box<Expr>,
101 ty: Type,
102 },
103 Raw(String),
105}
106
107impl Expr {
108 pub fn new_str(s: &str) -> Self {
109 Expr::ConstString(s.to_string())
110 }
111
112 pub fn new_num(n: u64) -> Self {
113 Expr::ConstNum(n)
114 }
115
116 pub fn new_var(name: &str, ty: Type) -> Self {
117 Expr::Variable {
118 name: name.to_string(),
119 ty,
120 }
121 }
122
123 pub fn btrue() -> Self {
124 Expr::ConstBool(true)
125 }
126
127 pub fn bfalse() -> Self {
128 Expr::ConstBool(false)
129 }
130
131 pub fn uop(op: &str, expr: Expr) -> Self {
132 Expr::UnOp {
133 expr: Box::new(expr),
134 op: op.to_string(),
135 }
136 }
137
138 pub fn lnot(expr: Expr) -> Self {
139 Expr::uop("!", expr)
140 }
141
142 pub fn binop(lhs: Expr, op: &str, rhs: Expr) -> Self {
143 Expr::BinOp {
144 lhs: Box::new(lhs),
145 rhs: Box::new(rhs),
146 op: op.to_string(),
147 }
148 }
149
150 pub fn land(lhs: Expr, rhs: Expr) -> Self {
151 Self::binop(lhs, "&&", rhs)
152 }
153
154 pub fn ternary(cond: Expr, then: Expr, other: Expr) -> Self {
155 Expr::Ternary {
156 cond: Box::new(cond),
157 then: Box::new(then),
158 other: Box::new(other),
159 }
160 }
161
162 pub fn from_fn_param(p: &FunctionParam) -> Self {
163 p.to_expr()
164 }
165
166 pub fn from_method_param(p: &MethodParam) -> Self {
167 p.to_expr()
168 }
169
170 pub fn from_attribuge(p: &Attribute) -> Self {
171 p.to_expr()
172 }
173
174 pub fn this() -> Self {
175 Expr::Variable {
176 name: "this".to_string(),
177 ty: Type::to_ptr(&Type::new(BaseType::Class(String::from("auto")))),
178 }
179 }
180
181 pub fn null() -> Self {
182 Expr::Variable {
183 name: "NULL".to_string(),
184 ty: Type::to_ptr(&Type::new(BaseType::Void)),
185 }
186 }
187
188 pub fn new(class: &str, args: Vec<Expr>) -> Self {
189 Expr::NewObject {
190 name: class.to_string(),
191 args,
192 }
193 }
194
195 pub fn delete(var: Expr) -> Self {
196 Expr::DeleteObject { var: Box::new(var) }
197 }
198
199 pub fn addr_of(&self) -> Self {
200 Expr::AddrOf(Box::new(self.clone()))
201 }
202
203 pub fn size_of(&self) -> Self {
204 Expr::SizeOf(Box::new(self.clone()))
205 }
206
207 pub fn deref(&self) -> Self {
208 Expr::Deref(Box::new(self.clone()))
209 }
210
211 pub fn field_access(&self, field: &str) -> Self {
212 Expr::FieldAccess {
213 var: Box::new(self.clone()),
214 field: field.to_string(),
215 is_ptr: false,
216 }
217 }
218
219 pub fn array_access(var: &Expr, idx: &Expr) -> Self {
220 Expr::ArrayElementAccess {
221 var: Box::new(var.clone()),
222 idx: Box::new(idx.clone()),
223 is_ptr: false,
224 }
225 }
226
227 pub fn method_call(var: &Expr, method: &str, args: Vec<Expr>) -> Self {
229 Expr::MethodCall {
230 var: Box::new(var.clone()),
231 method: method.to_string(),
232 args,
233 is_ptr: false,
234 }
235 }
236
237 pub fn fn_call(name: &str, args: Vec<Expr>) -> Self {
238 Expr::FnCall {
239 name: String::from(name),
240 args,
241 }
242 }
243
244 pub fn cast_to(&self, ty: Type) -> Self {
245 Expr::Cast {
246 expr: Box::new(self.clone()),
247 ty,
248 }
249 }
250
251 pub fn set_ptr(&mut self) {
252 match self {
253 Expr::MethodCall { is_ptr, .. } => {
254 *is_ptr = true;
255 }
256 Expr::FieldAccess { is_ptr, .. } => {
257 *is_ptr = true;
258 }
259 Expr::ArrayElementAccess { is_ptr, .. } => {
260 *is_ptr = true;
261 }
262 _ => (),
263 }
264 }
265
266 pub fn is_ptr(&self) -> bool {
267 match self {
268 Expr::Variable { ty, .. } => ty.is_ptr(),
269 Expr::Deref(e) => e.is_ptr(),
270 Expr::AddrOf(_) => true,
271 Expr::Raw(_) => true,
272 Expr::NewObject { .. } => true,
273 Expr::MethodCall { is_ptr, .. } => *is_ptr,
274 Expr::FieldAccess { is_ptr, .. } => *is_ptr,
275 Expr::ArrayElementAccess { is_ptr, .. } => *is_ptr,
276 Expr::Cast { ty, .. } => ty.is_ptr(),
277 _ => false,
278 }
279 }
280
281 pub fn is_struct(&self) -> bool {
282 match self {
283 Expr::Variable { ty, .. } => ty.is_struct(),
284 Expr::Cast { ty, .. } => ty.is_struct(),
285 Expr::NewObject { .. } => true,
286 Expr::Raw(_) => true,
287 _ => false,
288 }
289 }
290
291 pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
292 match self {
293 Expr::Variable { name, .. } => write!(fmt, "{name}"),
294 Expr::ConstString(x) => write!(fmt, "\"{x}\""),
295 Expr::ConstNum(x) => write!(fmt, "0x{x:x}"),
296 Expr::ConstBool(true) => write!(fmt, "true"),
297 Expr::ConstBool(false) => write!(fmt, "false"),
298 Expr::FnCall { name, args } => {
299 write!(fmt, "{name}(")?;
300 for (i, v) in args.iter().enumerate() {
301 if i != 0 {
302 write!(fmt, ", ")?;
303 }
304 v.fmt(fmt)?;
305 }
306 write!(fmt, ")")
307 }
308 Expr::Deref(e) => {
309 write!(fmt, "*(")?;
310 e.as_ref().fmt(fmt)?;
311 write!(fmt, ")")
312 }
313 Expr::AddrOf(e) => {
314 write!(fmt, "&(")?;
315 e.as_ref().fmt(fmt)?;
316 write!(fmt, ")")
317 }
318 Expr::SizeOf(e) => {
319 write!(fmt, "sizeof(")?;
320 e.as_ref().fmt(fmt)?;
321 write!(fmt, ")")
322 }
323 Expr::FieldAccess { var, field, .. } => {
324 write!(fmt, "({})", var.as_ref())?;
325 if var.is_ptr() {
326 write!(fmt, "->{field}")
327 } else {
328 write!(fmt, ".{field}")
329 }
330 }
331 Expr::ArrayElementAccess { var, idx, is_ptr: _ } => {
332 var.as_ref().fmt(fmt)?;
333 write!(fmt, "[{idx}]")
334 }
335 Expr::MethodCall { var, method, args, .. } => {
336 var.as_ref().fmt(fmt)?;
337 if var.is_ptr() {
338 write!(fmt, "->{method}(")?;
339 } else {
340 write!(fmt, ".{method}(")?;
341 }
342 for (i, v) in args.iter().enumerate() {
343 if i != 0 {
344 write!(fmt, ", ")?;
345 }
346 v.fmt(fmt)?;
347 }
348 write!(fmt, ")")
349 }
350 Expr::BinOp { lhs, rhs, op } => {
351 write!(fmt, "(")?;
352 lhs.as_ref().fmt(fmt)?;
353 write!(fmt, " {op} ")?;
354 rhs.as_ref().fmt(fmt)?;
355 write!(fmt, ")")
356 }
357 Expr::UnOp { expr, op } => {
358 write!(fmt, "{op}(")?;
359 expr.as_ref().fmt(fmt)?;
360 write!(fmt, ")")
361 }
362 Expr::Ternary { cond, then, other } => {
363 write!(fmt, "(")?;
364 cond.as_ref().fmt(fmt)?;
365 write!(fmt, ") ? (")?;
366 then.as_ref().fmt(fmt)?;
367 write!(fmt, ") : (")?;
368 other.as_ref().fmt(fmt)?;
369 write!(fmt, ")")
370 }
371 Expr::NewObject { name, args } => {
372 write!(fmt, "new {}(", name)?;
373 for (i, arg) in args.iter().enumerate() {
374 if i > 0 {
375 write!(fmt, ", ")?;
376 }
377 write!(fmt, "{}", arg)?;
378 }
379 write!(fmt, ")")
380 }
381 Expr::DeleteObject { var } => {
382 write!(fmt, "delete[] {}", var)
383 }
384 Expr::Cast { expr, ty } => {
385 write!(fmt, "({ty})({expr})")
386 }
387 Expr::Raw(s) => write!(fmt, "{s}"),
388 }
389 }
390}
391
392impl Display for Expr {
393 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
394 let mut ret = String::new();
395 self.fmt(&mut Formatter::new(&mut ret)).unwrap();
396 write!(f, "{ret}")
397 }
398}