| """The optimizer tries to constant fold expressions and modify the AST | |
| in place so that it should be faster to evaluate. | |
| Because the AST does not contain all the scoping information and the | |
| compiler has to find that out, we cannot do all the optimizations we | |
| want. For example, loop unrolling doesn't work because unrolled loops | |
| would have a different scope. The solution would be a second syntax tree | |
| that stored the scoping rules. | |
| """ | |
| from . import nodes | |
| from .visitor import NodeTransformer | |
| def optimize(node, environment): | |
| """The context hint can be used to perform an static optimization | |
| based on the context given.""" | |
| optimizer = Optimizer(environment) | |
| return optimizer.visit(node) | |
| class Optimizer(NodeTransformer): | |
| def __init__(self, environment): | |
| self.environment = environment | |
| def generic_visit(self, node, *args, **kwargs): | |
| node = super().generic_visit(node, *args, **kwargs) | |
| # Do constant folding. Some other nodes besides Expr have | |
| # as_const, but folding them causes errors later on. | |
| if isinstance(node, nodes.Expr): | |
| try: | |
| return nodes.Const.from_untrusted( | |
| node.as_const(args[0] if args else None), | |
| lineno=node.lineno, | |
| environment=self.environment, | |
| ) | |
| except nodes.Impossible: | |
| pass | |
| return node |