| 645 | } |
| 646 | |
| 647 | bool reshadefx::parser::parse_expression_unary(expression &exp) |
| 648 | { |
| 649 | location location = _token_next.location; |
| 650 | |
| 651 | const bool precise = exp.type.has(type::q_precise); |
| 652 | |
| 653 | // Check if a prefix operator exists |
| 654 | if (accept_unary_op()) |
| 655 | { |
| 656 | // Remember the operator token before parsing the expression that follows it |
| 657 | const tokenid op = _token.id; |
| 658 | |
| 659 | // Parse the actual expression |
| 660 | if (!parse_expression_unary(exp)) |
| 661 | return false; |
| 662 | |
| 663 | // Unary operators are only valid on basic types |
| 664 | if (!exp.type.is_scalar() && !exp.type.is_vector() && !exp.type.is_matrix()) |
| 665 | { |
| 666 | error(exp.location, 3022, "scalar, vector, or matrix expected"); |
| 667 | return false; |
| 668 | } |
| 669 | |
| 670 | // Special handling for the "++" and "--" operators |
| 671 | if (op == tokenid::plus_plus || op == tokenid::minus_minus) |
| 672 | { |
| 673 | if (exp.type.has(type::q_const) || !exp.is_lvalue) |
| 674 | { |
| 675 | error(location, 3025, "l-value specifies const object"); |
| 676 | return false; |
| 677 | } |
| 678 | |
| 679 | // Create a constant one in the type of the expression |
| 680 | const codegen::id constant_one = _codegen->emit_constant(exp.type, 1); |
| 681 | |
| 682 | const codegen::id value = _codegen->emit_load(exp); |
| 683 | const codegen::id result = _codegen->emit_binary_op(location, op, exp.type, value, constant_one); |
| 684 | |
| 685 | // The "++" and "--" operands modify the source variable, so store result back into it |
| 686 | _codegen->emit_store(exp, result); |
| 687 | } |
| 688 | else if (op != tokenid::plus) // Ignore "+" operator since it does not actually do anything |
| 689 | { |
| 690 | // The "~" bitwise operator is only valid on integral types |
| 691 | if (op == tokenid::tilde && !exp.type.is_integral()) |
| 692 | { |
| 693 | error(exp.location, 3082, "int or unsigned int type required"); |
| 694 | return false; |
| 695 | } |
| 696 | |
| 697 | // The logical not operator expects a boolean type as input, so perform cast if necessary |
| 698 | if (op == tokenid::exclaim && !exp.type.is_boolean()) |
| 699 | exp.add_cast_operation({ type::t_bool, exp.type.rows, exp.type.cols }); // The result will be boolean as well |
| 700 | |
| 701 | // Constant expressions can be evaluated at compile time |
| 702 | if (!exp.evaluate_constant_expression(op)) |
| 703 | { |
| 704 | const codegen::id value = _codegen->emit_load(exp); |
nothing calls this directly
no test coverage detected