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 Literal(lit) => literal(lit, expr.location),
15 Id(id) => self.parse_id(id, expr.location),
17 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 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 let deref = inner.indirection(false, struct_type);
75 self.struct_member(deref, id, expr.location)
76 }
77 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 AddressOf(inner) => {
97 let inner = self.expr(*inner);
98 match inner.expr {
99 ExprType::Deref(double_inner) => *double_inner,
102 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 _ 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 PreIncrement(inner, increment) => {
130 self.increment_op(true, increment, *inner, expr.location)
131 }
132 PostIncrement(inner, increment) => {
134 self.increment_op(false, increment, *inner, expr.location)
135 }
136 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 LogicalNot(inner) => self.logical_not(*inner),
159 LogicalAnd(left, right) => {
161 self.binary_helper(left, right, BinaryOp::LogicalAnd, Self::logical_bin_op)
162 }
163 LogicalOr(left, right) => {
165 self.binary_helper(left, right, BinaryOp::LogicalOr, Self::logical_bin_op)
166 }
167 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 #[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 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 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 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 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 }
262 Expr::id(symbol, location)
263 }
264 }
265 }
266 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 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 if !((left_expr.ctype.is_pointer() && left_expr.ctype == right_expr.ctype)
287 || ((token == ComparisonToken::EqualEqual || token == ComparisonToken::NotEqual)
289 && ((left_expr.ctype.is_pointer() && right_expr.ctype.is_void_pointer())
292 || (left_expr.ctype.is_void_pointer() && right_expr.ctype.is_pointer())
294 || (left_expr.is_null() && right_expr.ctype.is_pointer())
296 || (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 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 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 (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, Type::Pointer(to, _))
365 | (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 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 } else if !is_add && left.ctype.is_pointer_to_complete_object() && left.ctype == right.ctype
382 {
383 (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 fn explicit_cast(&mut self, expr: ast::Expr, ctype: Type) -> Expr {
402 let location = expr.location;
403 let expr = self.expr(expr).rval();
404 if ctype == Type::Void {
406 return Expr {
408 lval: false,
409 ctype,
410 expr: ExprType::Cast(Box::new(expr)),
412 location,
413 };
414 }
415 if !ctype.is_scalar() {
417 self.err(SemanticError::NonScalarCast(ctype.clone()), location);
418 } else if expr.ctype.is_floating() && ctype.is_pointer()
420 || expr.ctype.is_pointer() && ctype.is_floating()
422 {
423 self.err(SemanticError::FloatPointerCast(ctype.clone()), location);
424 } else if expr.ctype.is_struct() {
426 self.err(SemanticError::StructCast, location);
428 } 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 fn pointer_arithmetic(
442 &mut self,
443 base: Expr,
444 index: Expr,
445 pointee: &Type,
446 location: Location,
447 ) -> Expr {
448 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 fn func_call(&mut self, func: ast::Expr, args: Vec<ast::Expr>) -> Expr {
489 let mut func = self.expr(func);
490 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, other => {
506 self.err(SemanticError::NotAFunction(other.clone()), func.location);
507 return func;
508 }
509 };
510 let mut expected = functype.params.len();
511 if expected == 1 && functype.params[0].get().ctype == Type::Void {
513 expected = 0;
514 }
515 if !functype.params.is_empty()
517 && (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 Some(expected) => arg
531 .rval()
532 .implicit_cast(&expected.get().ctype, &mut self.error_handler),
533 None => self.default_promote(arg),
535 };
536 promoted_args.push(promoted);
537 }
538 Expr {
539 location: func.location,
540 lval: false, ctype: *functype.return_type.clone(),
542 expr: ExprType::FuncCall(Box::new(func), promoted_args),
543 }
544 }
545 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 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 if members.is_empty() {
560 self.err(
561 SemanticError::IncompleteDefinitionUsed(expr.ctype.clone()),
562 location,
563 );
564 expr
565 } 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 } else {
575 self.err(SemanticError::NotAMember(id, expr.ctype.clone()), location);
576 expr
577 }
578 }
579 _ => {
581 self.err(SemanticError::NotAStruct(expr.ctype.clone()), location);
582 expr
583 }
584 }
585 }
586 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 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 } else {
625 Expr {
626 lval: false,
627 ctype: expr.ctype.clone(),
628 expr: ExprType::PostIncrement(Box::new(expr), increment),
630 location,
631 }
632 }
633 }
634 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 (Type::Pointer(target, _), _) => ((**target).clone(), left, right),
643 (_, 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 addr.lval = true;
654 addr
655 }
656 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 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 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 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 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 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 ctype: Type::Bool,
746 location: a.location,
747 expr: ExprType::Binary(op, Box::new(a), Box::new(b)),
748 }
749 }
750 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 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 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, location,
802 expr: ExprType::Binary(BinaryOp::Assign, Box::new(lval), Box::new(rval)),
803 };
804 }
805 self.scope.enter();
815 let tmp_name = "tmp".into();
816 let ctype = lval.ctype.clone();
817 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 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 let tmp = Expr {
839 expr: ExprType::Id(tmp_var),
840 ctype: ptr_type,
841 lval: true,
842 location,
843 }
844 .rval();
847
848 let lval_as_rval = Expr {
851 ctype: ctype.clone(),
852 lval: false,
853 location,
854 expr: ExprType::Deref(Box::new(tmp.clone())),
856 };
857 let target = tmp.indirection(true, ctype.clone());
859 let new_val = self
861 .desugar_op(lval_as_rval, rval.rval(), token)
862 .implicit_cast(&target.ctype, &mut self.error_handler);
863
864 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
891pub(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
913fn 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 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 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 Enum(_, _) => Ok(true),
969 _ => Err(()),
970 }
971 }
972
973 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 _ => std::usize::MAX,
997 }
998 }
999 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 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); } else if left == Float || right == Float {
1017 return Ok(Float);
1018 }
1019 left = left.integer_promote();
1020 right = right.integer_promote();
1021 let signs = (
1024 left.sign().map_err(|_| left.clone())?,
1025 right.sign().map_err(|_| right.clone())?,
1026 );
1027 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 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 _ => 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 fn is_null(&self) -> bool {
1086 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 ctype: symbol.get().ctype.clone(),
1102 lval: true,
1103 location,
1104 }
1105 }
1106 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 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 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 error_handler.error(SemanticError::NonIntegralExpr(non_int), right.location);
1164 (left, right)
1165 }
1166 }
1167 }
1168 pub(super) fn rval(self) -> Expr {
1176 match self.ctype {
1177 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 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 fn indirection(self, lval: bool, ctype: Type) -> Self {
1218 Expr {
1219 location: self.location,
1220 ctype,
1221 lval,
1222 expr: ExprType::Noop(Box::new(self.rval())),
1226 }
1227 }
1228
1229 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 } else if expr.ctype.is_arithmetic() && ctype.is_arithmetic()
1237 || expr.is_null() && ctype.is_pointer()
1239 || expr.ctype.is_pointer() && ctype.is_bool()
1241 || expr.ctype.is_pointer() && ctype.is_void_pointer()
1243 || 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 } 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 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 fn modifiable_lval(&self) -> Result<(), SemanticError> {
1285 let err = |e| Err(SemanticError::NotAssignable(e));
1286 if !self.lval {
1288 return err("rvalue".to_string());
1289 }
1290 if !self.ctype.is_complete() {
1292 return err(format!("expression with incomplete type '{}'", self.ctype));
1293 }
1294 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 Type::Array(_, _) => err("array".to_string()),
1305 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 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}