Rewrite an expression This leverages the ``._{kind}_down`` and ``._{kind}_up`` methods defined on each class Returns ------- expr: output expression changed: whether or not any change occurred
(self, kind: str, rewritten)
| 292 | } |
| 293 | |
| 294 | def rewrite(self, kind: str, rewritten): |
| 295 | """Rewrite an expression |
| 296 | |
| 297 | This leverages the ``._{kind}_down`` and ``._{kind}_up`` |
| 298 | methods defined on each class |
| 299 | |
| 300 | Returns |
| 301 | ------- |
| 302 | expr: |
| 303 | output expression |
| 304 | changed: |
| 305 | whether or not any change occurred |
| 306 | """ |
| 307 | if self._name in rewritten: |
| 308 | return rewritten[self._name] |
| 309 | |
| 310 | expr = self |
| 311 | down_name = f"_{kind}_down" |
| 312 | up_name = f"_{kind}_up" |
| 313 | while True: |
| 314 | _continue = False |
| 315 | |
| 316 | # Rewrite this node |
| 317 | out = getattr(expr, down_name)() |
| 318 | if out is None: |
| 319 | out = expr |
| 320 | if not isinstance(out, Expr): |
| 321 | return out |
| 322 | if out._name != expr._name: |
| 323 | expr = out |
| 324 | continue |
| 325 | |
| 326 | # Allow children to rewrite their parents |
| 327 | for child in expr.dependencies(): |
| 328 | out = getattr(child, up_name)(expr) |
| 329 | if out is None: |
| 330 | out = expr |
| 331 | if not isinstance(out, Expr): |
| 332 | return out |
| 333 | if out is not expr and out._name != expr._name: |
| 334 | expr = out |
| 335 | _continue = True |
| 336 | break |
| 337 | |
| 338 | if _continue: |
| 339 | continue |
| 340 | |
| 341 | # Rewrite all of the children |
| 342 | new_operands = [] |
| 343 | changed = False |
| 344 | for operand in expr.operands: |
| 345 | if isinstance(operand, Expr): |
| 346 | new = operand.rewrite(kind=kind, rewritten=rewritten) |
| 347 | rewritten[operand._name] = new |
| 348 | if new._name != operand._name: |
| 349 | changed = True |
| 350 | else: |
| 351 | new = operand |