1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 |
- """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.
- """
- import typing as t
- from . import nodes
- from .visitor import NodeTransformer
- if t.TYPE_CHECKING:
- from .environment import Environment
- def optimize(node: nodes.Node, environment: "Environment") -> nodes.Node:
- """The context hint can be used to perform an static optimization
- based on the context given."""
- optimizer = Optimizer(environment)
- return t.cast(nodes.Node, optimizer.visit(node))
- class Optimizer(NodeTransformer):
- def __init__(self, environment: "t.Optional[Environment]") -> None:
- self.environment = environment
- def generic_visit(
- self, node: nodes.Node, *args: t.Any, **kwargs: t.Any
- ) -> nodes.Node:
- 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
|