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