|
18 | 18 | import dataclasses
|
19 | 19 | import itertools
|
20 | 20 | import typing
|
21 |
| -from typing import Mapping, TypeVar, Union |
| 21 | +from typing import Generator, Mapping, TypeVar, Union |
22 | 22 |
|
23 | 23 | import pandas as pd
|
24 | 24 |
|
@@ -155,6 +155,16 @@ class Expression(abc.ABC):
|
155 | 155 | def free_variables(self) -> typing.Tuple[str, ...]:
|
156 | 156 | return ()
|
157 | 157 |
|
| 158 | + @property |
| 159 | + def children(self) -> typing.Tuple[Expression, ...]: |
| 160 | + return () |
| 161 | + |
| 162 | + @property |
| 163 | + def expensive(self) -> bool: |
| 164 | + return any( |
| 165 | + isinstance(ex, OpExpression) and ex.op.expensive for ex in self.walk() |
| 166 | + ) |
| 167 | + |
158 | 168 | @property
|
159 | 169 | @abc.abstractmethod
|
160 | 170 | def column_references(self) -> typing.Tuple[ids.ColumnId, ...]:
|
@@ -216,6 +226,11 @@ def is_identity(self) -> bool:
|
216 | 226 | """True for identity operation that does not transform input."""
|
217 | 227 | return False
|
218 | 228 |
|
| 229 | + def walk(self) -> Generator[Expression, None, None]: |
| 230 | + yield self |
| 231 | + for child in self.children: |
| 232 | + yield from child.children |
| 233 | + |
219 | 234 |
|
220 | 235 | @dataclasses.dataclass(frozen=True)
|
221 | 236 | class ScalarConstantExpression(Expression):
|
@@ -389,6 +404,10 @@ def free_variables(self) -> typing.Tuple[str, ...]:
|
389 | 404 | def is_const(self) -> bool:
|
390 | 405 | return all(child.is_const for child in self.inputs)
|
391 | 406 |
|
| 407 | + @property |
| 408 | + def children(self): |
| 409 | + return self.inputs |
| 410 | + |
392 | 411 | def output_type(
|
393 | 412 | self, input_types: dict[ids.ColumnId, dtypes.ExpressionType]
|
394 | 413 | ) -> dtypes.ExpressionType:
|
|
0 commit comments