We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
AssertionError when comparing two functions with Binary operation
The following contract causes an assertion error:
```
contract FunctionComparisonTest {
    function f() public returns (bool) {
        return f == f;
    }
}
```

Output:
```
ERROR:root:Error in .\function_comparison.sol
ERROR:root:Traceback (most recent call last):
  File "c:\users\x\documents\github\slither\slither\__main__.py", line 610, in main_impl
    (slither_instances, results_detectors, results_printers, number_contracts) = process_all(filename, args,
  File "c:\users\x\documents\github\slither\slither\__main__.py", line 67, in process_all
    (slither, current_results_detectors, current_results_printers, current_analyzed_count) = process_single(
  File "c:\users\x\documents\github\slither\slither\__main__.py", line 53, in process_single
    slither = Slither(target,
  File "c:\users\x\documents\github\slither\slither\slither.py", line 86, in __init__
    self._parser.analyze_contracts()
  File "c:\users\x\documents\github\slither\slither\solc_parsing\slitherSolc.py", line 345, in analyze_contracts
    self._convert_to_slithir()
  File "c:\users\x\documents\github\slither\slither\solc_parsing\slitherSolc.py", line 489, in _convert_to_slithir
    func.generate_slithir_and_analyze()
  File "c:\users\x\documents\github\slither\slither\core\declarations\function.py", line 1652, in generate_slithir_and_analyze
    node.slithir_generation()
  File "c:\users\x\documents\github\slither\slither\core\cfg\node.py", line 702, in slithir_generation
    self._irs = convert_expression(expression, self)
  File "c:\users\x\documents\github\slither\slither\slithir\convert.py", line 64, in convert_expression
    visitor = ExpressionToSlithIR(expression, node)
  File "c:\users\x\documents\github\slither\slither\visitors\slithir\expression_to_slithir.py", line 103, in __init__
    self._visit_expression(self.expression)
  File "c:\users\x\documents\github\slither\slither\visitors\expression\expression.py", line 95, in _visit_expression
    self._post_visit(expression)
  File "c:\users\x\documents\github\slither\slither\visitors\expression\expression.py", line 268, in _post_visit
    self._post_binary_operation(expression)
  File "c:\users\x\documents\github\slither\slither\visitors\slithir\expression_to_slithir.py", line 192, in _post_binary_operation
    operation = Binary(val, left, right, _binary_to_binary[expression.type])
  File "c:\users\x\documents\github\slither\slither\slithir\operations\binary.py", line 133, in __init__
    assert is_valid_rvalue(left_variable)
AssertionError
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `slither/slithir/operations/binary.py`
Content:
```
1 import logging
2 from enum import Enum
3 
4 from slither.core.solidity_types import ElementaryType
5 from slither.slithir.exceptions import SlithIRError
6 from slither.slithir.operations.lvalue import OperationWithLValue
7 from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue
8 from slither.slithir.variables import ReferenceVariable
9 
10 logger = logging.getLogger("BinaryOperationIR")
11 
12 
13 class BinaryType(Enum):
14     POWER = 0  # **
15     MULTIPLICATION = 1  # *
16     DIVISION = 2  # /
17     MODULO = 3  # %
18     ADDITION = 4  # +
19     SUBTRACTION = 5  # -
20     LEFT_SHIFT = 6  # <<
21     RIGHT_SHIFT = 7  # >>
22     AND = 8  # &
23     CARET = 9  # ^
24     OR = 10  # |
25     LESS = 11  # <
26     GREATER = 12  # >
27     LESS_EQUAL = 13  # <=
28     GREATER_EQUAL = 14  # >=
29     EQUAL = 15  # ==
30     NOT_EQUAL = 16  # !=
31     ANDAND = 17  # &&
32     OROR = 18  # ||
33 
34     @staticmethod
35     def return_bool(operation_type):
36         return operation_type in [
37             BinaryType.OROR,
38             BinaryType.ANDAND,
39             BinaryType.LESS,
40             BinaryType.GREATER,
41             BinaryType.LESS_EQUAL,
42             BinaryType.GREATER_EQUAL,
43             BinaryType.EQUAL,
44             BinaryType.NOT_EQUAL,
45         ]
46 
47     @staticmethod
48     def get_type(operation_type):  # pylint: disable=too-many-branches
49         if operation_type == "**":
50             return BinaryType.POWER
51         if operation_type == "*":
52             return BinaryType.MULTIPLICATION
53         if operation_type == "/":
54             return BinaryType.DIVISION
55         if operation_type == "%":
56             return BinaryType.MODULO
57         if operation_type == "+":
58             return BinaryType.ADDITION
59         if operation_type == "-":
60             return BinaryType.SUBTRACTION
61         if operation_type == "<<":
62             return BinaryType.LEFT_SHIFT
63         if operation_type == ">>":
64             return BinaryType.RIGHT_SHIFT
65         if operation_type == "&":
66             return BinaryType.AND
67         if operation_type == "^":
68             return BinaryType.CARET
69         if operation_type == "|":
70             return BinaryType.OR
71         if operation_type == "<":
72             return BinaryType.LESS
73         if operation_type == ">":
74             return BinaryType.GREATER
75         if operation_type == "<=":
76             return BinaryType.LESS_EQUAL
77         if operation_type == ">=":
78             return BinaryType.GREATER_EQUAL
79         if operation_type == "==":
80             return BinaryType.EQUAL
81         if operation_type == "!=":
82             return BinaryType.NOT_EQUAL
83         if operation_type == "&&":
84             return BinaryType.ANDAND
85         if operation_type == "||":
86             return BinaryType.OROR
87 
88         raise SlithIRError("get_type: Unknown operation type {})".format(operation_type))
89 
90     def __str__(self):  # pylint: disable=too-many-branches
91         if self == BinaryType.POWER:
92             return "**"
93         if self == BinaryType.MULTIPLICATION:
94             return "*"
95         if self == BinaryType.DIVISION:
96             return "/"
97         if self == BinaryType.MODULO:
98             return "%"
99         if self == BinaryType.ADDITION:
100             return "+"
101         if self == BinaryType.SUBTRACTION:
102             return "-"
103         if self == BinaryType.LEFT_SHIFT:
104             return "<<"
105         if self == BinaryType.RIGHT_SHIFT:
106             return ">>"
107         if self == BinaryType.AND:
108             return "&"
109         if self == BinaryType.CARET:
110             return "^"
111         if self == BinaryType.OR:
112             return "|"
113         if self == BinaryType.LESS:
114             return "<"
115         if self == BinaryType.GREATER:
116             return ">"
117         if self == BinaryType.LESS_EQUAL:
118             return "<="
119         if self == BinaryType.GREATER_EQUAL:
120             return ">="
121         if self == BinaryType.EQUAL:
122             return "=="
123         if self == BinaryType.NOT_EQUAL:
124             return "!="
125         if self == BinaryType.ANDAND:
126             return "&&"
127         if self == BinaryType.OROR:
128             return "||"
129         raise SlithIRError("str: Unknown operation type {} {})".format(self, type(self)))
130 
131 
132 class Binary(OperationWithLValue):
133     def __init__(self, result, left_variable, right_variable, operation_type):
134         assert is_valid_rvalue(left_variable)
135         assert is_valid_rvalue(right_variable)
136         assert is_valid_lvalue(result)
137         assert isinstance(operation_type, BinaryType)
138         super().__init__()
139         self._variables = [left_variable, right_variable]
140         self._type = operation_type
141         self._lvalue = result
142         if BinaryType.return_bool(operation_type):
143             result.set_type(ElementaryType("bool"))
144         else:
145             result.set_type(left_variable.type)
146 
147     @property
148     def read(self):
149         return [self.variable_left, self.variable_right]
150 
151     @property
152     def get_variable(self):
153         return self._variables
154 
155     @property
156     def variable_left(self):
157         return self._variables[0]
158 
159     @property
160     def variable_right(self):
161         return self._variables[1]
162 
163     @property
164     def type(self):
165         return self._type
166 
167     @property
168     def type_str(self):
169         return str(self._type)
170 
171     def __str__(self):
172         if isinstance(self.lvalue, ReferenceVariable):
173             points = self.lvalue.points_to
174             while isinstance(points, ReferenceVariable):
175                 points = points.points_to
176             return "{}(-> {}) = {} {} {}".format(
177                 str(self.lvalue),
178                 points,
179                 self.variable_left,
180                 self.type_str,
181                 self.variable_right,
182             )
183         return "{}({}) = {} {} {}".format(
184             str(self.lvalue),
185             self.lvalue.type,
186             self.variable_left,
187             self.type_str,
188             self.variable_right,
189         )
190
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/slither/slithir/operations/binary.py b/slither/slithir/operations/binary.py
--- a/slither/slithir/operations/binary.py
+++ b/slither/slithir/operations/binary.py
@@ -1,6 +1,7 @@
 import logging
 from enum import Enum
 
+from slither.core.declarations import Function
 from slither.core.solidity_types import ElementaryType
 from slither.slithir.exceptions import SlithIRError
 from slither.slithir.operations.lvalue import OperationWithLValue
@@ -131,8 +132,8 @@
 
 class Binary(OperationWithLValue):
     def __init__(self, result, left_variable, right_variable, operation_type):
-        assert is_valid_rvalue(left_variable)
-        assert is_valid_rvalue(right_variable)
+        assert is_valid_rvalue(left_variable) or isinstance(left_variable, Function)
+        assert is_valid_rvalue(right_variable) or isinstance(right_variable, Function)
         assert is_valid_lvalue(result)
         assert isinstance(operation_type, BinaryType)
         super().__init__()

{"golden_diff": "diff --git a/slither/slithir/operations/binary.py b/slither/slithir/operations/binary.py\n--- a/slither/slithir/operations/binary.py\n+++ b/slither/slithir/operations/binary.py\n@@ -1,6 +1,7 @@\n import logging\n from enum import Enum\n \n+from slither.core.declarations import Function\n from slither.core.solidity_types import ElementaryType\n from slither.slithir.exceptions import SlithIRError\n from slither.slithir.operations.lvalue import OperationWithLValue\n@@ -131,8 +132,8 @@\n \n class Binary(OperationWithLValue):\n     def __init__(self, result, left_variable, right_variable, operation_type):\n-        assert is_valid_rvalue(left_variable)\n-        assert is_valid_rvalue(right_variable)\n+        assert is_valid_rvalue(left_variable) or isinstance(left_variable, Function)\n+        assert is_valid_rvalue(right_variable) or isinstance(right_variable, Function)\n         assert is_valid_lvalue(result)\n         assert isinstance(operation_type, BinaryType)\n         super().__init__()\n", "issue": "AssertionError when comparing two functions with Binary operation\nThe following contract causes an assertion error:\r\n```\r\ncontract FunctionComparisonTest {\r\n    function f() public returns (bool) {\r\n        return f == f;\r\n    }\r\n}\r\n```\r\n\r\nOutput:\r\n```\r\nERROR:root:Error in .\\function_comparison.sol\r\nERROR:root:Traceback (most recent call last):\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\__main__.py\", line 610, in main_impl\r\n    (slither_instances, results_detectors, results_printers, number_contracts) = process_all(filename, args,\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\__main__.py\", line 67, in process_all\r\n    (slither, current_results_detectors, current_results_printers, current_analyzed_count) = process_single(\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\__main__.py\", line 53, in process_single\r\n    slither = Slither(target,\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\slither.py\", line 86, in __init__\r\n    self._parser.analyze_contracts()\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\solc_parsing\\slitherSolc.py\", line 345, in analyze_contracts\r\n    self._convert_to_slithir()\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\solc_parsing\\slitherSolc.py\", line 489, in _convert_to_slithir\r\n    func.generate_slithir_and_analyze()\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\core\\declarations\\function.py\", line 1652, in generate_slithir_and_analyze\r\n    node.slithir_generation()\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\core\\cfg\\node.py\", line 702, in slithir_generation\r\n    self._irs = convert_expression(expression, self)\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\slithir\\convert.py\", line 64, in convert_expression\r\n    visitor = ExpressionToSlithIR(expression, node)\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\visitors\\slithir\\expression_to_slithir.py\", line 103, in __init__\r\n    self._visit_expression(self.expression)\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\visitors\\expression\\expression.py\", line 95, in _visit_expression\r\n    self._post_visit(expression)\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\visitors\\expression\\expression.py\", line 268, in _post_visit\r\n    self._post_binary_operation(expression)\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\visitors\\slithir\\expression_to_slithir.py\", line 192, in _post_binary_operation\r\n    operation = Binary(val, left, right, _binary_to_binary[expression.type])\r\n  File \"c:\\users\\x\\documents\\github\\slither\\slither\\slithir\\operations\\binary.py\", line 133, in __init__\r\n    assert is_valid_rvalue(left_variable)\r\nAssertionError\r\n```\n", "before_files": [{"content": "import logging\nfrom enum import Enum\n\nfrom slither.core.solidity_types import ElementaryType\nfrom slither.slithir.exceptions import SlithIRError\nfrom slither.slithir.operations.lvalue import OperationWithLValue\nfrom slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue\nfrom slither.slithir.variables import ReferenceVariable\n\nlogger = logging.getLogger(\"BinaryOperationIR\")\n\n\nclass BinaryType(Enum):\n    POWER = 0  # **\n    MULTIPLICATION = 1  # *\n    DIVISION = 2  # /\n    MODULO = 3  # %\n    ADDITION = 4  # +\n    SUBTRACTION = 5  # -\n    LEFT_SHIFT = 6  # <<\n    RIGHT_SHIFT = 7  # >>\n    AND = 8  # &\n    CARET = 9  # ^\n    OR = 10  # |\n    LESS = 11  # <\n    GREATER = 12  # >\n    LESS_EQUAL = 13  # <=\n    GREATER_EQUAL = 14  # >=\n    EQUAL = 15  # ==\n    NOT_EQUAL = 16  # !=\n    ANDAND = 17  # &&\n    OROR = 18  # ||\n\n    @staticmethod\n    def return_bool(operation_type):\n        return operation_type in [\n            BinaryType.OROR,\n            BinaryType.ANDAND,\n            BinaryType.LESS,\n            BinaryType.GREATER,\n            BinaryType.LESS_EQUAL,\n            BinaryType.GREATER_EQUAL,\n            BinaryType.EQUAL,\n            BinaryType.NOT_EQUAL,\n        ]\n\n    @staticmethod\n    def get_type(operation_type):  # pylint: disable=too-many-branches\n        if operation_type == \"**\":\n            return BinaryType.POWER\n        if operation_type == \"*\":\n            return BinaryType.MULTIPLICATION\n        if operation_type == \"/\":\n            return BinaryType.DIVISION\n        if operation_type == \"%\":\n            return BinaryType.MODULO\n        if operation_type == \"+\":\n            return BinaryType.ADDITION\n        if operation_type == \"-\":\n            return BinaryType.SUBTRACTION\n        if operation_type == \"<<\":\n            return BinaryType.LEFT_SHIFT\n        if operation_type == \">>\":\n            return BinaryType.RIGHT_SHIFT\n        if operation_type == \"&\":\n            return BinaryType.AND\n        if operation_type == \"^\":\n            return BinaryType.CARET\n        if operation_type == \"|\":\n            return BinaryType.OR\n        if operation_type == \"<\":\n            return BinaryType.LESS\n        if operation_type == \">\":\n            return BinaryType.GREATER\n        if operation_type == \"<=\":\n            return BinaryType.LESS_EQUAL\n        if operation_type == \">=\":\n            return BinaryType.GREATER_EQUAL\n        if operation_type == \"==\":\n            return BinaryType.EQUAL\n        if operation_type == \"!=\":\n            return BinaryType.NOT_EQUAL\n        if operation_type == \"&&\":\n            return BinaryType.ANDAND\n        if operation_type == \"||\":\n            return BinaryType.OROR\n\n        raise SlithIRError(\"get_type: Unknown operation type {})\".format(operation_type))\n\n    def __str__(self):  # pylint: disable=too-many-branches\n        if self == BinaryType.POWER:\n            return \"**\"\n        if self == BinaryType.MULTIPLICATION:\n            return \"*\"\n        if self == BinaryType.DIVISION:\n            return \"/\"\n        if self == BinaryType.MODULO:\n            return \"%\"\n        if self == BinaryType.ADDITION:\n            return \"+\"\n        if self == BinaryType.SUBTRACTION:\n            return \"-\"\n        if self == BinaryType.LEFT_SHIFT:\n            return \"<<\"\n        if self == BinaryType.RIGHT_SHIFT:\n            return \">>\"\n        if self == BinaryType.AND:\n            return \"&\"\n        if self == BinaryType.CARET:\n            return \"^\"\n        if self == BinaryType.OR:\n            return \"|\"\n        if self == BinaryType.LESS:\n            return \"<\"\n        if self == BinaryType.GREATER:\n            return \">\"\n        if self == BinaryType.LESS_EQUAL:\n            return \"<=\"\n        if self == BinaryType.GREATER_EQUAL:\n            return \">=\"\n        if self == BinaryType.EQUAL:\n            return \"==\"\n        if self == BinaryType.NOT_EQUAL:\n            return \"!=\"\n        if self == BinaryType.ANDAND:\n            return \"&&\"\n        if self == BinaryType.OROR:\n            return \"||\"\n        raise SlithIRError(\"str: Unknown operation type {} {})\".format(self, type(self)))\n\n\nclass Binary(OperationWithLValue):\n    def __init__(self, result, left_variable, right_variable, operation_type):\n        assert is_valid_rvalue(left_variable)\n        assert is_valid_rvalue(right_variable)\n        assert is_valid_lvalue(result)\n        assert isinstance(operation_type, BinaryType)\n        super().__init__()\n        self._variables = [left_variable, right_variable]\n        self._type = operation_type\n        self._lvalue = result\n        if BinaryType.return_bool(operation_type):\n            result.set_type(ElementaryType(\"bool\"))\n        else:\n            result.set_type(left_variable.type)\n\n    @property\n    def read(self):\n        return [self.variable_left, self.variable_right]\n\n    @property\n    def get_variable(self):\n        return self._variables\n\n    @property\n    def variable_left(self):\n        return self._variables[0]\n\n    @property\n    def variable_right(self):\n        return self._variables[1]\n\n    @property\n    def type(self):\n        return self._type\n\n    @property\n    def type_str(self):\n        return str(self._type)\n\n    def __str__(self):\n        if isinstance(self.lvalue, ReferenceVariable):\n            points = self.lvalue.points_to\n            while isinstance(points, ReferenceVariable):\n                points = points.points_to\n            return \"{}(-> {}) = {} {} {}\".format(\n                str(self.lvalue),\n                points,\n                self.variable_left,\n                self.type_str,\n                self.variable_right,\n            )\n        return \"{}({}) = {} {} {}\".format(\n            str(self.lvalue),\n            self.lvalue.type,\n            self.variable_left,\n            self.type_str,\n            self.variable_right,\n        )\n", "path": "slither/slithir/operations/binary.py"}], "after_files": [{"content": "import logging\nfrom enum import Enum\n\nfrom slither.core.declarations import Function\nfrom slither.core.solidity_types import ElementaryType\nfrom slither.slithir.exceptions import SlithIRError\nfrom slither.slithir.operations.lvalue import OperationWithLValue\nfrom slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue\nfrom slither.slithir.variables import ReferenceVariable\n\nlogger = logging.getLogger(\"BinaryOperationIR\")\n\n\nclass BinaryType(Enum):\n    POWER = 0  # **\n    MULTIPLICATION = 1  # *\n    DIVISION = 2  # /\n    MODULO = 3  # %\n    ADDITION = 4  # +\n    SUBTRACTION = 5  # -\n    LEFT_SHIFT = 6  # <<\n    RIGHT_SHIFT = 7  # >>\n    AND = 8  # &\n    CARET = 9  # ^\n    OR = 10  # |\n    LESS = 11  # <\n    GREATER = 12  # >\n    LESS_EQUAL = 13  # <=\n    GREATER_EQUAL = 14  # >=\n    EQUAL = 15  # ==\n    NOT_EQUAL = 16  # !=\n    ANDAND = 17  # &&\n    OROR = 18  # ||\n\n    @staticmethod\n    def return_bool(operation_type):\n        return operation_type in [\n            BinaryType.OROR,\n            BinaryType.ANDAND,\n            BinaryType.LESS,\n            BinaryType.GREATER,\n            BinaryType.LESS_EQUAL,\n            BinaryType.GREATER_EQUAL,\n            BinaryType.EQUAL,\n            BinaryType.NOT_EQUAL,\n        ]\n\n    @staticmethod\n    def get_type(operation_type):  # pylint: disable=too-many-branches\n        if operation_type == \"**\":\n            return BinaryType.POWER\n        if operation_type == \"*\":\n            return BinaryType.MULTIPLICATION\n        if operation_type == \"/\":\n            return BinaryType.DIVISION\n        if operation_type == \"%\":\n            return BinaryType.MODULO\n        if operation_type == \"+\":\n            return BinaryType.ADDITION\n        if operation_type == \"-\":\n            return BinaryType.SUBTRACTION\n        if operation_type == \"<<\":\n            return BinaryType.LEFT_SHIFT\n        if operation_type == \">>\":\n            return BinaryType.RIGHT_SHIFT\n        if operation_type == \"&\":\n            return BinaryType.AND\n        if operation_type == \"^\":\n            return BinaryType.CARET\n        if operation_type == \"|\":\n            return BinaryType.OR\n        if operation_type == \"<\":\n            return BinaryType.LESS\n        if operation_type == \">\":\n            return BinaryType.GREATER\n        if operation_type == \"<=\":\n            return BinaryType.LESS_EQUAL\n        if operation_type == \">=\":\n            return BinaryType.GREATER_EQUAL\n        if operation_type == \"==\":\n            return BinaryType.EQUAL\n        if operation_type == \"!=\":\n            return BinaryType.NOT_EQUAL\n        if operation_type == \"&&\":\n            return BinaryType.ANDAND\n        if operation_type == \"||\":\n            return BinaryType.OROR\n\n        raise SlithIRError(\"get_type: Unknown operation type {})\".format(operation_type))\n\n    def __str__(self):  # pylint: disable=too-many-branches\n        if self == BinaryType.POWER:\n            return \"**\"\n        if self == BinaryType.MULTIPLICATION:\n            return \"*\"\n        if self == BinaryType.DIVISION:\n            return \"/\"\n        if self == BinaryType.MODULO:\n            return \"%\"\n        if self == BinaryType.ADDITION:\n            return \"+\"\n        if self == BinaryType.SUBTRACTION:\n            return \"-\"\n        if self == BinaryType.LEFT_SHIFT:\n            return \"<<\"\n        if self == BinaryType.RIGHT_SHIFT:\n            return \">>\"\n        if self == BinaryType.AND:\n            return \"&\"\n        if self == BinaryType.CARET:\n            return \"^\"\n        if self == BinaryType.OR:\n            return \"|\"\n        if self == BinaryType.LESS:\n            return \"<\"\n        if self == BinaryType.GREATER:\n            return \">\"\n        if self == BinaryType.LESS_EQUAL:\n            return \"<=\"\n        if self == BinaryType.GREATER_EQUAL:\n            return \">=\"\n        if self == BinaryType.EQUAL:\n            return \"==\"\n        if self == BinaryType.NOT_EQUAL:\n            return \"!=\"\n        if self == BinaryType.ANDAND:\n            return \"&&\"\n        if self == BinaryType.OROR:\n            return \"||\"\n        raise SlithIRError(\"str: Unknown operation type {} {})\".format(self, type(self)))\n\n\nclass Binary(OperationWithLValue):\n    def __init__(self, result, left_variable, right_variable, operation_type):\n        assert is_valid_rvalue(left_variable) or isinstance(left_variable, Function)\n        assert is_valid_rvalue(right_variable) or isinstance(right_variable, Function)\n        assert is_valid_lvalue(result)\n        assert isinstance(operation_type, BinaryType)\n        super().__init__()\n        self._variables = [left_variable, right_variable]\n        self._type = operation_type\n        self._lvalue = result\n        if BinaryType.return_bool(operation_type):\n            result.set_type(ElementaryType(\"bool\"))\n        else:\n            result.set_type(left_variable.type)\n\n    @property\n    def read(self):\n        return [self.variable_left, self.variable_right]\n\n    @property\n    def get_variable(self):\n        return self._variables\n\n    @property\n    def variable_left(self):\n        return self._variables[0]\n\n    @property\n    def variable_right(self):\n        return self._variables[1]\n\n    @property\n    def type(self):\n        return self._type\n\n    @property\n    def type_str(self):\n        return str(self._type)\n\n    def __str__(self):\n        if isinstance(self.lvalue, ReferenceVariable):\n            points = self.lvalue.points_to\n            while isinstance(points, ReferenceVariable):\n                points = points.points_to\n            return \"{}(-> {}) = {} {} {}\".format(\n                str(self.lvalue),\n                points,\n                self.variable_left,\n                self.type_str,\n                self.variable_right,\n            )\n        return \"{}({}) = {} {} {}\".format(\n            str(self.lvalue),\n            self.lvalue.type,\n            self.variable_left,\n            self.type_str,\n            self.variable_right,\n        )\n", "path": "slither/slithir/operations/binary.py"}]}