Skip to main content

saltwater/analyze/
expr.rs

1use super::PureAnalyzer;
2use crate::arch;
3use crate::data::{hir::*, lex::ComparisonToken, *};
4use crate::intern::InternedStr;
5
6impl PureAnalyzer {
7    pub fn expr(&mut self, expr: ast::Expr) -> Expr {
8        use ast::ExprType::*;
9
10        let _guard = self.recursion_check();
11        let _guard2 = self.recursion_check();
12        match expr.data {
13            // 1 | "str" | 'a'
14            Literal(lit) => literal(lit, expr.location),
15            // x
16            Id(id) => self.parse_id(id, expr.location),
17            // (int)x
18            Cast(ctype, inner) => {
19                let ctype = self.parse_typename(ctype, expr.location);
20                self.explicit_cast(*inner, ctype)
21            }
22            Shift(left, right, direction) => {
23                let op = if direction {
24                    BinaryOp::Shl
25                } else {
26                    BinaryOp::Shr
27                };
28                self.binary_helper(left, right, op, Self::parse_integer_op)
29            }
30            BitwiseAnd(left, right) => {
31                self.binary_helper(left, right, BinaryOp::BitwiseAnd, Self::parse_integer_op)
32            }
33            BitwiseOr(left, right) => {
34                self.binary_helper(left, right, BinaryOp::BitwiseOr, Self::parse_integer_op)
35            }
36            Xor(left, right) => {
37                self.binary_helper(left, right, BinaryOp::Xor, Self::parse_integer_op)
38            }
39            Compare(left, right, token) => self.relational_expr(*left, *right, token),
40            Mul(left, right) => self.binary_helper(left, right, BinaryOp::Mul, Self::mul),
41            Div(left, right) => self.binary_helper(left, right, BinaryOp::Div, Self::mul),
42            Mod(left, right) => self.binary_helper(left, right, BinaryOp::Mod, Self::mul),
43            Assign(lval, rval, token) => {
44                let lval = self.expr(*lval);
45                let rval = self.expr(*rval);
46                self.assignment_expr(lval, rval, token, expr.location)
47            }
48            Add(left, right) => self.binary_helper(left, right, BinaryOp::Add, Self::add),
49            Sub(left, right) => self.binary_helper(left, right, BinaryOp::Sub, Self::add),
50            FuncCall(func, args) => self.func_call(*func, args),
51            Member(struct_, id) => {
52                let struct_ = self.expr(*struct_);
53                self.struct_member(struct_, id, expr.location)
54            }
55            // s->p desguars to (*s).p
56            DerefMember(inner, id) => {
57                let inner = self.expr(*inner);
58                let struct_type = match &inner.ctype {
59                    Type::Pointer(ctype, _) => match &**ctype {
60                        Type::Union(_) | Type::Struct(_) => (**ctype).clone(),
61                        other => {
62                            self.err(SemanticError::NotAStruct(other.clone()), inner.location);
63                            return inner;
64                        }
65                    },
66                    other => {
67                        self.err(SemanticError::NotAPointer(other.clone()), inner.location);
68                        return inner;
69                    }
70                };
71                // NOTE: when we pass `deref` to `struct_member`,
72                // it will always mark the resulting expression as an `lval`.
73                // To avoid a double dereference, we mark `deref` as an `rval`.
74                let deref = inner.indirection(false, struct_type);
75                self.struct_member(deref, id, expr.location)
76            }
77            // `*p` or `a[i]`
78            Deref(inner) => {
79                let inner = self.expr(*inner);
80                match &inner.ctype {
81                    Type::Array(t, _) | Type::Pointer(t, _) => {
82                        let ctype = (**t).clone();
83                        inner.indirection(true, ctype)
84                    }
85                    _ => {
86                        self.err(
87                            SemanticError::NotAPointer(inner.ctype.clone()),
88                            expr.location,
89                        );
90                        inner
91                    }
92                }
93            }
94            // &x
95            // 6.5.3.2 Address and indirection operators
96            AddressOf(inner) => {
97                let inner = self.expr(*inner);
98                match inner.expr {
99                    // parse &*x as x
100                    // footnote 102: &*E is equivalent to E (even if E is a null pointer)
101                    ExprType::Deref(double_inner) => *double_inner,
102                    // footnote 121:
103                    // > the address of any part of an object declared with storage-class specifier register cannot be computed,
104                    // > either explicitly (by use of the unary & operator as discussed in 6.5.3.2)
105                    // > or implicitly (by converting an array name to a pointer as discussed in 6.3.2.1).
106                    ExprType::Id(ref sym) if sym.get().storage_class == StorageClass::Register => {
107                        self.err(
108                            SemanticError::InvalidAddressOf("variable declared with `register`"),
109                            expr.location,
110                        );
111                        inner
112                    }
113                    // > The operand of the unary & operator shall be either a function designator,
114                    // > the result of a [] or unary * operator,
115                    // > or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.
116                    _ if inner.lval => Expr {
117                        lval: false,
118                        location: expr.location,
119                        ctype: Type::Pointer(Box::new(inner.ctype.clone()), Qualifiers::default()),
120                        expr: inner.expr,
121                    },
122                    _ => {
123                        self.err(SemanticError::InvalidAddressOf("value"), expr.location);
124                        inner
125                    }
126                }
127            }
128            // ++x
129            PreIncrement(inner, increment) => {
130                self.increment_op(true, increment, *inner, expr.location)
131            }
132            // x++
133            PostIncrement(inner, increment) => {
134                self.increment_op(false, increment, *inner, expr.location)
135            }
136            // a[i]
137            Index(left, right) => self.index(*left, *right, expr.location),
138            AlignofType(type_name) => {
139                let ctype = self.parse_typename(type_name, expr.location);
140                self.align(ctype, expr.location)
141            }
142            AlignofExpr(inner) => {
143                let inner = self.expr(*inner);
144                self.align(inner.ctype, expr.location)
145            }
146            SizeofType(type_name) => {
147                let ctype = self.parse_typename(type_name, expr.location);
148                self.sizeof(ctype, expr.location)
149            }
150            SizeofExpr(inner) => {
151                let inner = self.expr(*inner);
152                self.sizeof(inner.ctype, expr.location)
153            }
154            BitwiseNot(inner) => self.bitwise_not(*inner),
155            UnaryPlus(inner) => self.unary_add(*inner, true, expr.location),
156            Negate(inner) => self.unary_add(*inner, false, expr.location),
157            // !x
158            LogicalNot(inner) => self.logical_not(*inner),
159            // x && y
160            LogicalAnd(left, right) => {
161                self.binary_helper(left, right, BinaryOp::LogicalAnd, Self::logical_bin_op)
162            }
163            // x || y
164            LogicalOr(left, right) => {
165                self.binary_helper(left, right, BinaryOp::LogicalOr, Self::logical_bin_op)
166            }
167            // x, y
168            // evaluate x, discarding its value, then yield the value of y
169            // mostly used to have multiple side effects in a single statement, such as in a for loop:
170            // `for(j = i, k = 0; k < n; j++, k++);`
171            // see also https://stackoverflow.com/a/43561555/7669110
172            Comma(left, right) => {
173                let left = self.expr(*left);
174                let right = self.expr(*right).rval();
175                Expr {
176                    ctype: right.ctype.clone(),
177                    lval: false,
178                    expr: ExprType::Comma(Box::new(left), Box::new(right)),
179                    location: expr.location,
180                }
181            }
182            Ternary(condition, then, otherwise) => {
183                self.ternary(*condition, *then, *otherwise, expr.location)
184            }
185        }
186    }
187    // only meant for use with `expr`
188    // TODO: change ast::Expr to use `ExprType::Binary` as well, which would make this unnecessary
189    // TODO: these functions should have the locations of the parent expression, not the children
190    #[allow(clippy::boxed_local)]
191    fn binary_helper<F>(
192        &mut self,
193        left: Box<ast::Expr>,
194        right: Box<ast::Expr>,
195        op: BinaryOp,
196        expr_checker: F,
197    ) -> Expr
198    where
199        F: FnOnce(&mut Self, Expr, Expr, BinaryOp) -> Expr,
200    {
201        let left = self.expr(*left);
202        let right = self.expr(*right);
203        expr_checker(self, left, right, op)
204    }
205    // left OP right, where OP is an operation that requires integral types
206    fn parse_integer_op(&mut self, left: Expr, right: Expr, op: BinaryOp) -> Expr {
207        let non_scalar = if !left.ctype.is_integral() {
208            Some(&left.ctype)
209        } else if !right.ctype.is_integral() {
210            Some(&right.ctype)
211        } else {
212            None
213        };
214        let location = left.location.merge(right.location);
215        if let Some(ctype) = non_scalar {
216            self.err(SemanticError::NonIntegralExpr(ctype.clone()), location);
217        }
218        let (promoted_expr, next) = Expr::binary_promote(left, right, &mut self.error_handler);
219        Expr {
220            ctype: next.ctype.clone(),
221            expr: ExprType::Binary(op, Box::new(promoted_expr), Box::new(next)),
222            lval: false,
223            location,
224        }
225    }
226    // x
227    fn parse_id(&mut self, name: InternedStr, location: Location) -> Expr {
228        let mut pretend_zero = Expr::zero(location);
229        pretend_zero.ctype = Type::Error;
230        match self.scope.get(&name) {
231            None => {
232                self.err(SemanticError::UndeclaredVar(name), location);
233                pretend_zero
234            }
235            Some(&symbol) => {
236                let meta = symbol.get();
237                // typedef int i; return i + 1;
238                if meta.storage_class == StorageClass::Typedef {
239                    self.err(SemanticError::TypedefInExpressionContext, location);
240                    return pretend_zero;
241                }
242                if let Type::Enum(ident, members) = &meta.ctype {
243                    let mapper = |(member, value): &(InternedStr, i64)| {
244                        if name == *member {
245                            Some(*value)
246                        } else {
247                            None
248                        }
249                    };
250                    let enumerator = members.iter().find_map(mapper);
251                    // enum e { A }; return A;
252                    if let Some(e) = enumerator {
253                        return Expr {
254                            ctype: Type::Enum(*ident, members.clone()),
255                            location,
256                            lval: false,
257                            expr: ExprType::Literal(Literal::Int(e)),
258                        };
259                    }
260                    // otherwise, `enum e { A } my_e; return my_e;`
261                }
262                Expr::id(symbol, location)
263            }
264        }
265    }
266    // `left == right`, `left < right`, or similar
267    // 6.5.9 Equality operators
268    fn relational_expr(
269        &mut self,
270        left: ast::Expr,
271        right: ast::Expr,
272        token: ComparisonToken,
273    ) -> Expr {
274        let location = left.location.merge(right.location);
275        let mut left = self.expr(left);
276        let mut right = self.expr(right);
277
278        // i == i
279        if left.ctype.is_arithmetic() && right.ctype.is_arithmetic() {
280            let tmp = Expr::binary_promote(left, right, &mut self.error_handler);
281            left = tmp.0;
282            right = tmp.1;
283        } else {
284            let (left_expr, right_expr) = (left.rval(), right.rval());
285            // p1 == p2
286            if !((left_expr.ctype.is_pointer() && left_expr.ctype == right_expr.ctype)
287                // equality operations have different rules :(
288                || ((token == ComparisonToken::EqualEqual || token == ComparisonToken::NotEqual)
289                    // shoot me now
290                    // (int*)p1 == (void*)p2
291                    && ((left_expr.ctype.is_pointer() && right_expr.ctype.is_void_pointer())
292                        // (void*)p1 == (int*)p2
293                        || (left_expr.ctype.is_void_pointer() && right_expr.ctype.is_pointer())
294                        // NULL == (int*)p2
295                        || (left_expr.is_null() && right_expr.ctype.is_pointer())
296                        // (int*)p1 == NULL
297                        || (left_expr.ctype.is_pointer() && right_expr.is_null()))))
298            {
299                self.err(
300                    SemanticError::InvalidRelationalType(
301                        token,
302                        left_expr.ctype.clone(),
303                        right_expr.ctype.clone(),
304                    ),
305                    location,
306                );
307            }
308            left = left_expr;
309            right = right_expr;
310        }
311        assert!(!left.lval && !right.lval);
312        Expr {
313            lval: false,
314            location,
315            ctype: Type::Bool,
316            expr: ExprType::Binary(BinaryOp::Compare(token), Box::new(left), Box::new(right)),
317        }
318    }
319    // `left OP right`, where OP is Mul, Div, or Mod
320    // 6.5.5 Multiplicative operators
321    fn mul(&mut self, left: Expr, right: Expr, op: BinaryOp) -> Expr {
322        let location = left.location.merge(right.location);
323
324        if op == BinaryOp::Mod && !(left.ctype.is_integral() && right.ctype.is_integral()) {
325            self.err(
326                SemanticError::from(format!(
327                    "expected integers for both operators of %, got '{}' and '{}'",
328                    left.ctype, right.ctype
329                )),
330                location,
331            );
332        } else if !(left.ctype.is_arithmetic() && right.ctype.is_arithmetic()) {
333            self.err(
334                SemanticError::from(format!(
335                    "expected float or integer types for both operands of {}, got '{}' and '{}'",
336                    op, left.ctype, right.ctype
337                )),
338                location,
339            );
340        }
341        let (left, right) = Expr::binary_promote(left, right, &mut self.error_handler);
342        Expr {
343            ctype: left.ctype.clone(),
344            location,
345            lval: false,
346            expr: ExprType::Binary(op, Box::new(left), Box::new(right)),
347        }
348    }
349    // `a + b` or `a - b`
350    // `op` should only be `Add` or `Sub`
351    // 6.5.6 Additive operators
352    fn add(&mut self, mut left: Expr, mut right: Expr, op: BinaryOp) -> Expr {
353        let is_add = op == BinaryOp::Add;
354        let location = left.location.merge(right.location);
355        match (&left.ctype, &right.ctype) {
356            // `p + i`
357            (Type::Pointer(to, _), i)
358            | (Type::Array(to, _), i) if i.is_integral() && to.is_complete() => {
359                let to = to.clone();
360                let (left, right) = (left.rval(), right.rval());
361                return self.pointer_arithmetic(left, right, &*to, location);
362            }
363            // `i + p`
364            (i, Type::Pointer(to, _))
365                // `i - p` for pointer p is not valid
366            | (i, Type::Array(to, _)) if i.is_integral() && is_add && to.is_complete() => {
367                let to = to.clone();
368                let (left, right) = (left.rval(), right.rval());
369                return self.pointer_arithmetic(right, left, &*to, location);
370            }
371            _ => {}
372        };
373        // `i + i`
374        let (ctype, lval) = if left.ctype.is_arithmetic() && right.ctype.is_arithmetic() {
375            let tmp = Expr::binary_promote(left, right, &mut self.error_handler);
376            left = tmp.0;
377            right = tmp.1;
378            (left.ctype.clone(), false)
379        // `p1 - p2`
380        // `p1 + p2` for pointers p1 and p2 is not valid
381        } else if !is_add && left.ctype.is_pointer_to_complete_object() && left.ctype == right.ctype
382        {
383            // not sure what type to use here, C11 standard doesn't mention it
384            (left.ctype.clone(), true)
385        } else {
386            self.err(
387                SemanticError::InvalidAdd(op, left.ctype.clone(), right.ctype.clone()),
388                location,
389            );
390            (left.ctype.clone(), false)
391        };
392        Expr {
393            ctype,
394            lval,
395            location,
396            expr: ExprType::Binary(op, Box::new(left), Box::new(right)),
397        }
398    }
399    // (int)i
400    // 6.5.4 Cast operators
401    fn explicit_cast(&mut self, expr: ast::Expr, ctype: Type) -> Expr {
402        let location = expr.location;
403        let expr = self.expr(expr).rval();
404        // (void)0;
405        if ctype == Type::Void {
406            // casting anything to void is allowed
407            return Expr {
408                lval: false,
409                ctype,
410                // this just signals to the backend to ignore this outer expr
411                expr: ExprType::Cast(Box::new(expr)),
412                location,
413            };
414        }
415        // (struct s)1
416        if !ctype.is_scalar() {
417            self.err(SemanticError::NonScalarCast(ctype.clone()), location);
418        // (int*)1.0
419        } else if expr.ctype.is_floating() && ctype.is_pointer()
420            // (float)(int*)p
421            || expr.ctype.is_pointer() && ctype.is_floating()
422        {
423            self.err(SemanticError::FloatPointerCast(ctype.clone()), location);
424        // struct { int i; } s; (int)s
425        } else if expr.ctype.is_struct() {
426            // not implemented: galaga (https://github.com/jyn514/rcc/issues/98)
427            self.err(SemanticError::StructCast, location);
428        // void f(); (int)f();
429        } else if expr.ctype == Type::Void {
430            self.err(SemanticError::VoidCast, location);
431        }
432        Expr {
433            lval: false,
434            expr: ExprType::Cast(Box::new(expr)),
435            ctype,
436            location,
437        }
438    }
439    // `base + index`, where `pointee` is the type of `*base`
440    // 6.5.6 Additive operators
441    fn pointer_arithmetic(
442        &mut self,
443        base: Expr,
444        index: Expr,
445        pointee: &Type,
446        location: Location,
447    ) -> Expr {
448        // the idea is to desugar to `base + sizeof(base)*index`
449        let offset = Expr {
450            lval: false,
451            location: index.location,
452            expr: ExprType::Cast(Box::new(index)),
453            ctype: base.ctype.clone(),
454        }
455        .rval();
456        let size = match pointee.sizeof() {
457            Ok(s) => s,
458            Err(_) => {
459                self.err(
460                    SemanticError::PointerAddUnknownSize(base.ctype.clone()),
461                    location,
462                );
463                1
464            }
465        };
466        let size_literal = literal(Literal::UnsignedInt(size), offset.location);
467        let size_cast = Expr {
468            lval: false,
469            location: offset.location,
470            ctype: offset.ctype.clone(),
471            expr: ExprType::Cast(Box::new(size_literal)),
472        };
473        let offset = Expr {
474            lval: false,
475            location: offset.location,
476            ctype: offset.ctype.clone(),
477            expr: ExprType::Binary(BinaryOp::Mul, Box::new(size_cast), Box::new(offset)),
478        };
479        Expr {
480            lval: false,
481            location,
482            ctype: base.ctype.clone(),
483            expr: ExprType::Binary(BinaryOp::Add, Box::new(base), Box::new(offset)),
484        }
485    }
486    // `func(args)`
487    // 6.5.2.2 Function calls
488    fn func_call(&mut self, func: ast::Expr, args: Vec<ast::Expr>) -> Expr {
489        let mut func = self.expr(func);
490        // if fp is a function pointer, fp() desugars to (*fp)()
491        match &func.ctype {
492            Type::Pointer(pointee, _) if pointee.is_function() => {
493                func = Expr {
494                    lval: false,
495                    location: func.location,
496                    ctype: (**pointee).clone(),
497                    expr: ExprType::Deref(Box::new(func)),
498                }
499            }
500            _ => {}
501        };
502        let functype = match &func.ctype {
503            Type::Function(functype) => functype,
504            Type::Error => return func, // we've already reported this error
505            other => {
506                self.err(SemanticError::NotAFunction(other.clone()), func.location);
507                return func;
508            }
509        };
510        let mut expected = functype.params.len();
511        // f(void)
512        if expected == 1 && functype.params[0].get().ctype == Type::Void {
513            expected = 0;
514        }
515        // f() takes _any_ number of arguments
516        if !functype.params.is_empty()
517            // `int f(int); f()` or `int f(int); f(1, 2)`
518            && (args.len() < expected || args.len() > expected && !functype.varargs)
519        {
520            self.err(
521                SemanticError::WrongArgumentNumber(args.len(), expected),
522                func.location,
523            );
524        }
525        let mut promoted_args = vec![];
526        for (i, arg) in args.into_iter().enumerate() {
527            let arg = self.expr(arg);
528            let promoted = match functype.params.get(i) {
529                // int f(int); f(1)
530                Some(expected) => arg
531                    .rval()
532                    .implicit_cast(&expected.get().ctype, &mut self.error_handler),
533                // `int f(); f(1)` or `int f(int, ...); f(1, 2)`
534                None => self.default_promote(arg),
535            };
536            promoted_args.push(promoted);
537        }
538        Expr {
539            location: func.location,
540            lval: false, // no move semantics here!
541            ctype: *functype.return_type.clone(),
542            expr: ExprType::FuncCall(Box::new(func), promoted_args),
543        }
544    }
545    /// 'default promotions' from 6.5.2.2p6
546    fn default_promote(&mut self, expr: Expr) -> Expr {
547        let expr = expr.rval();
548        let ctype = expr.ctype.clone().default_promote();
549        expr.implicit_cast(&ctype, &mut self.error_handler)
550    }
551    // parse a struct member
552    // used for both s.a and s->a
553    // 6.5.2.3 Structure and union members
554    fn struct_member(&mut self, expr: Expr, id: InternedStr, location: Location) -> Expr {
555        match &expr.ctype {
556            Type::Struct(stype) | Type::Union(stype) => {
557                let members = stype.members();
558                // struct s; s.a
559                if members.is_empty() {
560                    self.err(
561                        SemanticError::IncompleteDefinitionUsed(expr.ctype.clone()),
562                        location,
563                    );
564                    expr
565                // struct s { int i; }; s.i
566                } else if let Some(member) = members.iter().find(|member| member.id == id) {
567                    Expr {
568                        ctype: member.ctype.clone(),
569                        lval: true,
570                        location,
571                        expr: ExprType::Member(Box::new(expr), id),
572                    }
573                // struct s { int i; }; s.j
574                } else {
575                    self.err(SemanticError::NotAMember(id, expr.ctype.clone()), location);
576                    expr
577                }
578            }
579            // (1).a
580            _ => {
581                self.err(SemanticError::NotAStruct(expr.ctype.clone()), location);
582                expr
583            }
584        }
585    }
586    // ++i, i--
587    // 6.5.2.4 Postfix increment and decrement operators
588    fn increment_op(
589        &mut self,
590        prefix: bool,
591        increment: bool,
592        expr: ast::Expr,
593        location: Location,
594    ) -> Expr {
595        use crate::data::lex::AssignmentToken;
596
597        let expr = self.expr(expr);
598        if let Err(err) = expr.modifiable_lval() {
599            self.err(err, location);
600        } else if !(expr.ctype.is_arithmetic() || expr.ctype.is_pointer()) {
601            self.err(
602                SemanticError::InvalidIncrement(expr.ctype.clone()),
603                expr.location,
604            );
605        }
606        // ++i is syntactic sugar for i+=1
607        if prefix {
608            let rval = Expr {
609                lval: false,
610                ctype: expr.ctype.clone(),
611                location,
612                expr: ExprType::Cast(Box::new(literal(Literal::Int(1), location))),
613            };
614            let op = if increment {
615                AssignmentToken::AddEqual
616            } else {
617                AssignmentToken::SubEqual
618            };
619            self.assignment_expr(expr, rval, op, location)
620        // i++ requires support from the backend
621        // 6.5.2.4 Postfix increment and decrement operators
622        // evaluate the rvalue of `i` and as a side effect, increment the value at the stored address
623        // ex: `int i = 0, j; j = i++;` leaves a value of 0 in j and a value of 1 in i
624        } else {
625            Expr {
626                lval: false,
627                ctype: expr.ctype.clone(),
628                // true, false: increment/decrement
629                expr: ExprType::PostIncrement(Box::new(expr), increment),
630                location,
631            }
632        }
633    }
634    // a[i] desugars to *(a + i)
635    // 6.5.2.1 Array subscripting
636    fn index(&mut self, left: ast::Expr, right: ast::Expr, location: Location) -> Expr {
637        let left = self.expr(left).rval();
638        let right = self.expr(right).rval();
639
640        let (target_type, array, index) = match (&left.ctype, &right.ctype) {
641            // p[i]
642            (Type::Pointer(target, _), _) => ((**target).clone(), left, right),
643            // i[p]
644            (_, Type::Pointer(target, _)) => ((**target).clone(), right, left),
645            (l, _) => {
646                self.err(SemanticError::NotAPointer(l.clone()), location);
647                return left;
648            }
649        };
650        let mut addr = self.pointer_arithmetic(array, index, &target_type, location);
651        addr.ctype = target_type;
652        // `p + i` -> `*(p + i)`
653        addr.lval = true;
654        addr
655    }
656    // _Alignof(int)
657    fn align(&mut self, ctype: Type, location: Location) -> Expr {
658        let align = ctype.alignof().unwrap_or_else(|err| {
659            self.err(err.into(), location);
660            1
661        });
662        literal(Literal::UnsignedInt(align), location)
663    }
664    // sizeof(int)
665    // 6.5.3.4 The sizeof and _Alignof operators
666    fn sizeof(&mut self, ctype: Type, location: Location) -> Expr {
667        let align = ctype.sizeof().unwrap_or_else(|err| {
668            self.err(err.into(), location);
669            1
670        });
671        literal(Literal::UnsignedInt(align), location)
672    }
673    // ~expr
674    // 6.5.3.3 Unary arithmetic operators
675    fn bitwise_not(&mut self, expr: ast::Expr) -> Expr {
676        let expr = self.expr(expr);
677        if !expr.ctype.is_integral() {
678            self.err(
679                SemanticError::NonIntegralExpr(expr.ctype.clone()),
680                expr.location,
681            );
682            expr
683        } else {
684            let expr = expr.integer_promote(&mut self.error_handler);
685            Expr {
686                lval: false,
687                ctype: expr.ctype.clone(),
688                location: expr.location,
689                expr: ExprType::BitwiseNot(Box::new(expr)),
690            }
691        }
692    }
693    // -x and +x
694    // 6.5.3.3 Unary arithmetic operators
695    fn unary_add(&mut self, expr: ast::Expr, add: bool, location: Location) -> Expr {
696        let expr = self.expr(expr);
697        if !expr.ctype.is_arithmetic() {
698            self.err(SemanticError::NotArithmetic(expr.ctype.clone()), location);
699            return expr;
700        }
701        let expr = expr.integer_promote(&mut self.error_handler);
702        if add {
703            Expr {
704                lval: false,
705                location,
706                ..expr
707            }
708        } else {
709            Expr {
710                lval: false,
711                ctype: expr.ctype.clone(),
712                location,
713                expr: ExprType::Negate(Box::new(expr)),
714            }
715        }
716    }
717    // !expr
718    // 6.5.3.3 Unary arithmetic operators
719    // > The expression !E is equivalent to (0==E).
720    fn logical_not(&mut self, expr: ast::Expr) -> Expr {
721        let expr = self.expr(expr);
722        let boolean = expr.truthy(&mut self.error_handler);
723        debug_assert_eq!(boolean.ctype, Type::Bool);
724        let zero = Expr::zero(boolean.location).implicit_cast(&Type::Bool, &mut self.error_handler);
725        Expr {
726            lval: false,
727            location: boolean.location,
728            ctype: Type::Bool,
729            expr: ExprType::Binary(
730                BinaryOp::Compare(ComparisonToken::EqualEqual),
731                Box::new(boolean),
732                Box::new(zero),
733            ),
734        }
735    }
736    // a || b or a && b
737    // NOTE: this short circuits if possible
738    // 6.5.14 Logical OR operator and 6.5.13 Logical AND operator
739    fn logical_bin_op(&mut self, a: Expr, b: Expr, op: BinaryOp) -> Expr {
740        let a = a.implicit_cast(&Type::Bool, &mut self.error_handler);
741        let b = b.implicit_cast(&Type::Bool, &mut self.error_handler);
742        Expr {
743            lval: false,
744            // TODO: this is wrong, it should be an int
745            ctype: Type::Bool,
746            location: a.location,
747            expr: ExprType::Binary(op, Box::new(a), Box::new(b)),
748        }
749    }
750    // condition ? then : otherwise
751    // like an `if` in Rust: evaluate `condition`, yield the value of `then` if true, otherwise yield the value of `otherwise`
752    fn ternary(
753        &mut self,
754        condition: ast::Expr,
755        then: ast::Expr,
756        otherwise: ast::Expr,
757        location: Location,
758    ) -> Expr {
759        let condition = self.expr(condition).truthy(&mut self.error_handler);
760        let mut then = self.expr(then).rval();
761        let mut otherwise = self.expr(otherwise).rval();
762
763        if then.ctype.is_arithmetic() && otherwise.ctype.is_arithmetic() {
764            let (tmp1, tmp2) = Expr::binary_promote(then, otherwise, &mut self.error_handler);
765            then = tmp1;
766            otherwise = tmp2;
767        } else if !pointer_promote(&mut then, &mut otherwise) {
768            self.err(
769                SemanticError::IncompatibleTypes(then.ctype.clone(), otherwise.ctype.clone()),
770                location,
771            );
772        }
773        Expr {
774            ctype: then.ctype.clone(),
775            lval: false,
776            location,
777            expr: ExprType::Ternary(Box::new(condition), Box::new(then), Box::new(otherwise)),
778        }
779    }
780
781    // `a = b` or `a += b`
782    fn assignment_expr(
783        &mut self,
784        lval: Expr,
785        rval: Expr,
786        token: lex::AssignmentToken,
787        location: Location,
788    ) -> Expr {
789        if let Err(err) = lval.modifiable_lval() {
790            self.err(err, location);
791        }
792        // `a = b`
793        if let lex::AssignmentToken::Equal = token {
794            let mut rval = rval.rval();
795            if rval.ctype != lval.ctype {
796                rval = rval.implicit_cast(&lval.ctype, &mut self.error_handler);
797            }
798            return Expr {
799                ctype: lval.ctype.clone(),
800                lval: false, // `(i = j) = 4`; is invalid
801                location,
802                expr: ExprType::Binary(BinaryOp::Assign, Box::new(lval), Box::new(rval)),
803            };
804        }
805        // Complex assignment is tricky because the left side needs to be evaluated only once
806        // Consider e.g. `*f() += 1`: `f()` should only be called once.
807        // The hack implemented here is to treat `*f()` as a variable then load and store it to memory:
808        // `tmp = &f(); *tmp = *tmp + 1;`
809        // see also footnote 113 which has a similar algorithm (but is more convoluted because of atomics)
810
811        // declare tmp in a new hidden scope
812        // We really should only be modifying the scope in `FunctionAnalyzer`,
813        // but assignment expressions can never appear in an initializer anyway.
814        self.scope.enter();
815        let tmp_name = "tmp".into();
816        let ctype = lval.ctype.clone();
817        // TODO: we could probably make these qualifiers stronger
818        let ptr_type = Type::Pointer(Box::new(ctype.clone()), Qualifiers::default());
819        let meta = Variable {
820            id: tmp_name,
821            ctype: ptr_type.clone(),
822            qualifiers: Qualifiers::NONE,
823            storage_class: StorageClass::Register,
824        };
825        let tmp_var = self.declare(meta, true, location);
826
827        // NOTE: this does _not_ call rval() on `lval`
828        // there's no way to do this in C natively - the closest is `&var`, but that doesn't work on expressions
829        // `T tmp = &*f()` or `T tmp = &sum`
830        let init = Some(Initializer::Scalar(Box::new(lval)));
831        let decl = Declaration {
832            symbol: tmp_var,
833            init,
834        };
835        self.decl_side_channel.push(Locatable::new(decl, location));
836        self.scope.exit();
837        // load `tmp`, i.e. `&*f()`, only evaluated once
838        let tmp = Expr {
839            expr: ExprType::Id(tmp_var),
840            ctype: ptr_type,
841            lval: true,
842            location,
843        }
844        // this `rval` is because we have the (pointless) address of `tmp`
845        // instead we want the address of the lval
846        .rval();
847
848        // before we had `&sum`, now we have `sum`
849        // `*tmp`, i.e. `*f()`
850        let lval_as_rval = Expr {
851            ctype: ctype.clone(),
852            lval: false,
853            location,
854            // this clone is pretty cheap since `tmp_assign_expr` is just an id
855            expr: ExprType::Deref(Box::new(tmp.clone())),
856        };
857        // `*tmp` in an lval context
858        let target = tmp.indirection(true, ctype.clone());
859        // `*tmp + 1`
860        let new_val = self
861            .desugar_op(lval_as_rval, rval.rval(), token)
862            .implicit_cast(&target.ctype, &mut self.error_handler);
863
864        // *tmp = *f() + 1
865        Expr {
866            ctype,
867            lval: false,
868            location,
869            expr: ExprType::Binary(BinaryOp::Assign, Box::new(target), Box::new(new_val)),
870        }
871    }
872    fn desugar_op(&mut self, left: Expr, right: Expr, token: lex::AssignmentToken) -> Expr {
873        use lex::AssignmentToken::*;
874
875        match token {
876            Equal => unreachable!(),
877            OrEqual => self.parse_integer_op(left, right, BinaryOp::BitwiseOr),
878            AndEqual => self.parse_integer_op(left, right, BinaryOp::BitwiseAnd),
879            XorEqual => self.parse_integer_op(left, right, BinaryOp::Xor),
880            ShlEqual => self.parse_integer_op(left, right, BinaryOp::Shl),
881            ShrEqual => self.parse_integer_op(left, right, BinaryOp::Shr),
882            MulEqual => self.mul(left, right, BinaryOp::Mul),
883            DivEqual => self.mul(left, right, BinaryOp::Div),
884            ModEqual => self.mul(left, right, BinaryOp::Mod),
885            AddEqual => self.add(left, right, BinaryOp::Add),
886            SubEqual => self.add(left, right, BinaryOp::Sub),
887        }
888    }
889}
890
891// literal
892pub(super) fn literal(literal: Literal, location: Location) -> Expr {
893    use crate::data::types::ArrayType;
894
895    let ctype = match &literal {
896        Literal::Char(_) => Type::Char(true),
897        Literal::Int(_) => Type::Long(true),
898        Literal::UnsignedInt(_) => Type::Long(false),
899        Literal::Float(_) => Type::Double,
900        Literal::Str(s) => {
901            let len = s.len() as arch::SIZE_T;
902            Type::Array(Box::new(Type::Char(true)), ArrayType::Fixed(len))
903        }
904    };
905    Expr {
906        lval: false,
907        ctype,
908        location,
909        expr: ExprType::Literal(literal),
910    }
911}
912
913// 6.5.15 - Conditional operator
914fn pointer_promote(left: &mut Expr, right: &mut Expr) -> bool {
915    let is_convertible_to_any_pointer = |expr: &Expr| {
916        expr.ctype.is_void_pointer() || expr.ctype.is_char_pointer() || expr.is_null()
917    };
918    if left.ctype == right.ctype {
919        true
920    } else if is_convertible_to_any_pointer(left) && right.ctype.is_pointer() {
921        left.ctype = right.ctype.clone();
922        true
923    } else if is_convertible_to_any_pointer(right) && left.ctype.is_pointer() {
924        right.ctype = left.ctype.clone();
925        true
926    } else {
927        false
928    }
929}
930
931impl Type {
932    #[inline]
933    fn is_void_pointer(&self) -> bool {
934        match self {
935            Type::Pointer(t, _) => **t == Type::Void,
936            _ => false,
937        }
938    }
939    #[inline]
940    fn is_char_pointer(&self) -> bool {
941        match self {
942            Type::Pointer(t, _) => match **t {
943                Type::Char(_) => true,
944                _ => false,
945            },
946            _ => false,
947        }
948    }
949    #[inline]
950    /// used for pointer addition and subtraction, see section 6.5.6 of the C11 standard
951    fn is_pointer_to_complete_object(&self) -> bool {
952        match self {
953            Type::Pointer(ctype, _) => ctype.is_complete() && !ctype.is_function(),
954            Type::Array(_, _) => true,
955            _ => false,
956        }
957    }
958    /// Return whether self is a signed type.
959    ///
960    /// Should only be called on integral types.
961    /// Calling sign() on a floating or derived type will return Err(()).
962    fn sign(&self) -> Result<bool, ()> {
963        use Type::*;
964        match self {
965            Char(sign) | Short(sign) | Int(sign) | Long(sign) => Ok(*sign),
966            Bool => Ok(false),
967            // TODO: allow enums with values of UINT_MAX
968            Enum(_, _) => Ok(true),
969            _ => Err(()),
970        }
971    }
972
973    /// Return the rank of an integral type, according to section 6.3.1.1 of the C standard.
974    ///
975    /// It is an error to take the rank of a non-integral type.
976    ///
977    /// Examples:
978    /// ```ignore
979    /// use saltwater::data::types::Type::*;
980    /// assert!(Long(true).rank() > Int(true).rank());
981    /// assert!(Int(false).rank() > Short(false).rank());
982    /// assert!(Short(true).rank() > Char(true).rank());
983    /// assert!(Char(true).rank() > Bool.rank());
984    /// assert!(Long(false).rank() > Bool.rank());
985    /// assert!(Long(true).rank() == Long(false).rank());
986    /// ```
987    fn rank(&self) -> usize {
988        use Type::*;
989        match self {
990            Bool => 0,
991            Char(_) => 1,
992            Short(_) => 2,
993            Int(_) => 3,
994            Long(_) => 4,
995            // don't make this 5 in case we add `long long` at some point
996            _ => std::usize::MAX,
997        }
998    }
999    // Subclause 2 of 6.3.1.1 Boolean, characters, and integers
1000    fn integer_promote(self) -> Type {
1001        if self.rank() <= Type::Int(true).rank() {
1002            if Type::Int(true).can_represent(&self) {
1003                Type::Int(true)
1004            } else {
1005                Type::Int(false)
1006            }
1007        } else {
1008            self
1009        }
1010    }
1011    // 6.3.1.8 Usual arithmetic conversions
1012    fn binary_promote(mut left: Type, mut right: Type) -> Result<Type, Type> {
1013        use Type::*;
1014        if left == Double || right == Double {
1015            return Ok(Double); // toil and trouble
1016        } else if left == Float || right == Float {
1017            return Ok(Float);
1018        }
1019        left = left.integer_promote();
1020        right = right.integer_promote();
1021        // TODO: we know that `left` can't be used after a move,
1022        // but rustc isn't smart enough to figure it out and let us remove the clone
1023        let signs = (
1024            left.sign().map_err(|_| left.clone())?,
1025            right.sign().map_err(|_| right.clone())?,
1026        );
1027        // same sign
1028        if signs.0 == signs.1 {
1029            return Ok(if left.rank() >= right.rank() {
1030                left
1031            } else {
1032                right
1033            });
1034        };
1035        let (signed, unsigned) = if signs.0 {
1036            (left, right)
1037        } else {
1038            (right, left)
1039        };
1040        if signed.can_represent(&unsigned) {
1041            Ok(signed)
1042        } else {
1043            Ok(unsigned)
1044        }
1045    }
1046    /// 6.5.2.2p6:
1047    /// > If the expression that denotes the called function has a type that does not include a prototype,
1048    /// > the integer promotions are performed on each argument,
1049    /// > and arguments that have type float are promoted to double.
1050    /// > These are called the default argument promotions.
1051    fn default_promote(self) -> Type {
1052        if self.is_integral() {
1053            self.integer_promote()
1054        } else if self == Type::Float {
1055            Type::Double
1056        } else {
1057            self
1058        }
1059    }
1060    fn is_struct(&self) -> bool {
1061        match self {
1062            Type::Struct(_) | Type::Union(_) => true,
1063            _ => false,
1064        }
1065    }
1066    fn is_complete(&self) -> bool {
1067        match self {
1068            Type::Void | Type::Function(_) | Type::Array(_, types::ArrayType::Unbounded) => false,
1069            // TODO: update when we allow incomplete struct and union types (e.g. `struct s;`)
1070            _ => true,
1071        }
1072    }
1073}
1074
1075impl Expr {
1076    pub(super) fn zero(location: Location) -> Expr {
1077        Expr {
1078            ctype: Type::Int(true),
1079            expr: ExprType::Literal(Literal::Int(0)),
1080            lval: false,
1081            location,
1082        }
1083    }
1084    // 6.3.2.3 Pointers
1085    fn is_null(&self) -> bool {
1086        // TODO: I think we need to const fold this to allow `(void*)0`
1087        if let ExprType::Literal(token) = &self.expr {
1088            match token {
1089                Literal::Int(0) | Literal::UnsignedInt(0) | Literal::Char(0) => true,
1090                _ => false,
1091            }
1092        } else {
1093            false
1094        }
1095    }
1096    fn id(symbol: Symbol, location: Location) -> Self {
1097        Self {
1098            expr: ExprType::Id(symbol),
1099            // TODO: maybe pass in the type as well to avoid the lookup?
1100            // but then we need to make sure the type matches the symbol
1101            ctype: symbol.get().ctype.clone(),
1102            lval: true,
1103            location,
1104        }
1105    }
1106    // Convert an expression to _Bool. Section 6.3.1.3 of the C standard:
1107    // "When any scalar value is converted to _Bool,
1108    // the result is 0 if the value compares equal to 0; otherwise, the result is 1."
1109    //
1110    // TODO: this looks like the same as casting to _Bool, can we just offload to the backend instead?
1111    //
1112    // if (expr)
1113    pub(crate) fn truthy(mut self, error_handler: &mut ErrorHandler) -> Expr {
1114        self = self.rval();
1115        if self.ctype == Type::Bool {
1116            return self;
1117        }
1118        if !self.ctype.is_scalar() {
1119            error_handler.error(
1120                SemanticError::Generic(format!(
1121                    "expression of type '{}' cannot be converted to bool",
1122                    self.ctype
1123                )),
1124                self.location,
1125            );
1126            self.ctype = Type::Error;
1127        }
1128        let zero = Expr::zero(self.location).implicit_cast(&self.ctype, error_handler);
1129        Expr {
1130            lval: false,
1131            location: self.location,
1132            ctype: Type::Bool,
1133            expr: ExprType::Binary(
1134                BinaryOp::Compare(ComparisonToken::NotEqual),
1135                Box::new(self),
1136                Box::new(zero),
1137            ),
1138        }
1139    }
1140
1141    // Perform an integer conversion, including all relevant casts.
1142    //
1143    // See `Type::integer_promote` for conversion rules.
1144    fn integer_promote(self, error_handler: &mut ErrorHandler) -> Expr {
1145        let expr = self.rval();
1146        let ctype = expr.ctype.clone().integer_promote();
1147        expr.implicit_cast(&ctype, error_handler)
1148    }
1149
1150    // Perform a binary conversion, including all relevant casts.
1151    //
1152    // See `Type::binary_promote` for conversion rules.
1153    fn binary_promote(left: Expr, right: Expr, error_handler: &mut ErrorHandler) -> (Expr, Expr) {
1154        let (left, right) = (left.rval(), right.rval());
1155        let ctype = Type::binary_promote(left.ctype.clone(), right.ctype.clone());
1156        match ctype {
1157            Ok(promoted) => (
1158                left.implicit_cast(&promoted, error_handler),
1159                right.implicit_cast(&promoted, error_handler),
1160            ),
1161            Err(non_int) => {
1162                // TODO: this location is wrong
1163                error_handler.error(SemanticError::NonIntegralExpr(non_int), right.location);
1164                (left, right)
1165            }
1166        }
1167    }
1168    // ensure an expression has a value. convert
1169    // - arrays -> pointers
1170    // - functions -> pointers
1171    // - variables -> value stored in that variable
1172    // 6.3.2.1 Lvalues, arrays, and function designators
1173    // >  Except when it is the operand of [a bunch of different operators],
1174    // > an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue)
1175    pub(super) fn rval(self) -> Expr {
1176        match self.ctype {
1177            // a + 1 is the same as &a + 1
1178            Type::Array(to, _) => Expr {
1179                lval: false,
1180                ctype: Type::Pointer(to, Qualifiers::default()),
1181                ..self
1182            },
1183            Type::Function(_) => Expr {
1184                lval: false,
1185                ctype: Type::Pointer(
1186                    Box::new(self.ctype),
1187                    Qualifiers {
1188                        c_const: true,
1189                        ..Qualifiers::default()
1190                    },
1191                ),
1192                ..self
1193            },
1194            // HACK: structs can't be dereferenced since they're not scalar, so we just fake it
1195            Type::Struct(_) | Type::Union(_) if self.lval => Expr {
1196                lval: false,
1197                ..self
1198            },
1199            _ if self.lval => Expr {
1200                ctype: self.ctype.clone(),
1201                lval: false,
1202                location: self.location,
1203                expr: ExprType::Deref(Box::new(self)),
1204            },
1205            _ => self,
1206        }
1207    }
1208    // `*p` when p is a pointer
1209    //
1210    // NOTE: this can be in _either_ an lval or an rval context
1211    // in an rval context: `return *p;`
1212    // in an lval context: `*p = 1`
1213    //
1214    // `ctype` is the type of the resulting expression
1215    //
1216    // 6.5.3.2 Address and indirection operators
1217    fn indirection(self, lval: bool, ctype: Type) -> Self {
1218        Expr {
1219            location: self.location,
1220            ctype,
1221            lval,
1222            // this is super hacky but the only way I can think of to prevent
1223            // https://github.com/jyn514/rcc/issues/90
1224            // we need to call `self.rval()` so that if `self` is a variable we get its value, not its address.
1225            expr: ExprType::Noop(Box::new(self.rval())),
1226        }
1227    }
1228
1229    // float f = (double)1.0
1230    // 6.3 Conversions
1231    pub(super) fn implicit_cast(self, ctype: &Type, error_handler: &mut ErrorHandler) -> Expr {
1232        let mut expr = self.rval();
1233        if &expr.ctype == ctype {
1234            expr
1235        // int -> long
1236        } else if expr.ctype.is_arithmetic() && ctype.is_arithmetic()
1237            // NULL -> int*
1238            || expr.is_null() && ctype.is_pointer()
1239            // if ((int*)p)
1240            || expr.ctype.is_pointer() && ctype.is_bool()
1241            // p -> void*
1242            || expr.ctype.is_pointer() && ctype.is_void_pointer()
1243            // p -> char*
1244            || expr.ctype.is_pointer() && ctype.is_char_pointer()
1245        {
1246            Expr {
1247                location: expr.location,
1248                expr: ExprType::Cast(Box::new(expr)),
1249                lval: false,
1250                ctype: ctype.clone(),
1251            }
1252        // `NULL -> int*` or `void* -> int*` or `char* -> int*`
1253        } else if ctype.is_pointer()
1254            && (expr.is_null() || expr.ctype.is_void_pointer() || expr.ctype.is_char_pointer())
1255        {
1256            expr.ctype = ctype.clone();
1257            expr
1258        } else if expr.ctype == Type::Error {
1259            expr
1260        } else {
1261            // allow implicit casts of const pointers
1262            // Standard (in the context `left = right`, i.e. casting `right` to `left`)
1263            // > the left operand has atomic, qualified, or unqualified pointer type,
1264            // > and (considering the type the left operand would have after lvalue conversion)
1265            // > both operands are pointers to qualified or unqualified versions of compatible types,
1266            // > and the type pointed to by the left has all the qualifiers of the type pointed to by the right;
1267            if let (Type::Pointer(a, from), Type::Pointer(b, to)) = (&expr.ctype, ctype) {
1268                if *a == *b && from.contains_all(*to) {
1269                    expr.ctype = ctype.clone();
1270                    return expr;
1271                }
1272            }
1273            error_handler.error(
1274                SemanticError::InvalidCast(expr.ctype.clone(), ctype.clone()),
1275                expr.location,
1276            );
1277            expr
1278        }
1279    }
1280    /// See section 6.3.2.1 of the C Standard. In particular:
1281    /// "A modifiable lvalue is an lvalue that does not have array type,
1282    /// does not  have an incomplete type, does not have a const-qualified type,
1283    /// and if it is a structure or union, does not have any member with a const-qualified type"
1284    fn modifiable_lval(&self) -> Result<(), SemanticError> {
1285        let err = |e| Err(SemanticError::NotAssignable(e));
1286        // rval
1287        if !self.lval {
1288            return err("rvalue".to_string());
1289        }
1290        // incomplete type
1291        if !self.ctype.is_complete() {
1292            return err(format!("expression with incomplete type '{}'", self.ctype));
1293        }
1294        // const-qualified type
1295        // TODO: handle `*const`
1296        if let ExprType::Id(sym) = &self.expr {
1297            let meta = sym.get();
1298            if meta.qualifiers.c_const {
1299                return err(format!("variable '{}' with `const` qualifier", meta.id));
1300            }
1301        }
1302        match &self.ctype {
1303            // array type
1304            Type::Array(_, _) => err("array".to_string()),
1305            // member with const-qualified type
1306            Type::Struct(stype) | Type::Union(stype) => {
1307                if stype
1308                    .members()
1309                    .iter()
1310                    .map(|sym| sym.qualifiers.c_const)
1311                    .any(|x| x)
1312                {
1313                    err("struct or union with `const` qualified member".to_string())
1314                } else {
1315                    Ok(())
1316                }
1317            }
1318            _ => Ok(()),
1319        }
1320    }
1321}
1322
1323impl Qualifiers {
1324    // return whether `self` has all the qualifiers of `right`
1325    // WARNING: this _must_ be updated if you add more fields to `Qualifiers`
1326    fn contains_all(self, other: Self) -> bool {
1327        (self.c_const || !other.c_const) && (self.volatile || !other.volatile)
1328    }
1329}
1330
1331#[cfg(test)]
1332mod test {
1333    use super::*;
1334    use crate::analyze::test::analyze;
1335    use crate::analyze::*;
1336    pub(crate) fn expr(input: &str) -> CompileResult<Expr> {
1337        analyze(input, Parser::expr, PureAnalyzer::expr)
1338    }
1339    fn get_location(r: &CompileResult<Expr>) -> Location {
1340        match r {
1341            Ok(expr) => expr.location,
1342            Err(err) => err.location(),
1343        }
1344    }
1345    fn assert_literal(token: Literal) {
1346        let parsed = expr(&token.to_string());
1347        let location = get_location(&parsed);
1348        assert_eq!(parsed.unwrap(), literal(token, location));
1349    }
1350    fn expr_with_scope<'a>(input: &'a str, variables: &[Symbol]) -> CompileResult<Expr> {
1351        analyze(input, Parser::expr, |a, expr| {
1352            for &meta in variables {
1353                let id = meta.get().id;
1354                a.scope.insert(id, meta);
1355            }
1356            a.expr(expr)
1357        })
1358    }
1359    fn assert_type(input: &str, ctype: Type) {
1360        match expr(input) {
1361            Ok(expr) => assert_eq!(expr.ctype, ctype),
1362            Err(err) => panic!("error: {}", err.data),
1363        };
1364    }
1365    #[test]
1366    fn test_primaries() {
1367        assert_literal(Literal::Int(141));
1368        let parsed = expr("\"hi there\"");
1369
1370        assert_eq!(
1371            parsed,
1372            Ok(literal(
1373                Literal::Str("hi there\0".into()),
1374                get_location(&parsed)
1375            )),
1376        );
1377        assert_literal(Literal::Float(1.5));
1378        let parsed = expr("(1)");
1379        assert_eq!(parsed, Ok(literal(Literal::Int(1), get_location(&parsed))));
1380        let x = Variable {
1381            ctype: Type::Int(true),
1382            id: InternedStr::get_or_intern("x"),
1383            qualifiers: Default::default(),
1384            storage_class: Default::default(),
1385        }
1386        .insert();
1387        let parsed = expr_with_scope("x", &[x]);
1388        assert_eq!(
1389            parsed,
1390            Ok(Expr {
1391                location: get_location(&parsed),
1392                ctype: Type::Int(true),
1393                lval: true,
1394                expr: ExprType::Id(x)
1395            })
1396        );
1397    }
1398    #[test]
1399    fn test_mul() {
1400        assert_type("1*1.0", Type::Double);
1401        assert_type("1*2.0 / 1.3", Type::Double);
1402        assert_type("3%2", Type::Long(true));
1403    }
1404    #[test]
1405    fn test_funcall() {
1406        let f = Variable {
1407            id: InternedStr::get_or_intern("f"),
1408            qualifiers: Default::default(),
1409            storage_class: Default::default(),
1410            ctype: Type::Function(types::FunctionType {
1411                params: vec![Variable {
1412                    ctype: Type::Void,
1413                    id: Default::default(),
1414                    qualifiers: Default::default(),
1415                    storage_class: StorageClass::Auto,
1416                }
1417                .insert()],
1418                return_type: Box::new(Type::Int(true)),
1419                varargs: false,
1420            }),
1421        }
1422        .insert();
1423        assert!(expr_with_scope("f(1,2,3)", &[f]).is_err());
1424        let parsed = expr_with_scope("f()", &[f]);
1425        assert!(match parsed {
1426            Ok(Expr {
1427                expr: ExprType::FuncCall(_, _),
1428                ..
1429            }) => true,
1430            _ => false,
1431        },);
1432    }
1433    #[test]
1434    fn test_type_errors() {
1435        assert!(expr("1 % 2.0").is_err());
1436        assert!(expr("0 ? \"error message\" : 0.0").is_err());
1437    }
1438
1439    #[test]
1440    fn test_explicit_casts() {
1441        assert_type("(int)4.2", Type::Int(true));
1442        assert_type("(unsigned int)4.2", Type::Int(false));
1443        assert_type("(float)4.2", Type::Float);
1444        assert_type("(double)4.2", Type::Double);
1445        assert!(expr("(int*)4.2").is_err());
1446        assert_type(
1447            "(int*)(int)4.2",
1448            Type::Pointer(Box::new(Type::Int(true)), Qualifiers::default()),
1449        );
1450    }
1451}