1e31aef6aSopenharmony_ci"""The optimizer tries to constant fold expressions and modify the AST 2e31aef6aSopenharmony_ciin place so that it should be faster to evaluate. 3e31aef6aSopenharmony_ci 4e31aef6aSopenharmony_ciBecause the AST does not contain all the scoping information and the 5e31aef6aSopenharmony_cicompiler has to find that out, we cannot do all the optimizations we 6e31aef6aSopenharmony_ciwant. For example, loop unrolling doesn't work because unrolled loops 7e31aef6aSopenharmony_ciwould have a different scope. The solution would be a second syntax tree 8e31aef6aSopenharmony_cithat stored the scoping rules. 9e31aef6aSopenharmony_ci""" 10e31aef6aSopenharmony_ciimport typing as t 11e31aef6aSopenharmony_ci 12e31aef6aSopenharmony_cifrom . import nodes 13e31aef6aSopenharmony_cifrom .visitor import NodeTransformer 14e31aef6aSopenharmony_ci 15e31aef6aSopenharmony_ciif t.TYPE_CHECKING: 16e31aef6aSopenharmony_ci from .environment import Environment 17e31aef6aSopenharmony_ci 18e31aef6aSopenharmony_ci 19e31aef6aSopenharmony_cidef optimize(node: nodes.Node, environment: "Environment") -> nodes.Node: 20e31aef6aSopenharmony_ci """The context hint can be used to perform an static optimization 21e31aef6aSopenharmony_ci based on the context given.""" 22e31aef6aSopenharmony_ci optimizer = Optimizer(environment) 23e31aef6aSopenharmony_ci return t.cast(nodes.Node, optimizer.visit(node)) 24e31aef6aSopenharmony_ci 25e31aef6aSopenharmony_ci 26e31aef6aSopenharmony_ciclass Optimizer(NodeTransformer): 27e31aef6aSopenharmony_ci def __init__(self, environment: "t.Optional[Environment]") -> None: 28e31aef6aSopenharmony_ci self.environment = environment 29e31aef6aSopenharmony_ci 30e31aef6aSopenharmony_ci def generic_visit( 31e31aef6aSopenharmony_ci self, node: nodes.Node, *args: t.Any, **kwargs: t.Any 32e31aef6aSopenharmony_ci ) -> nodes.Node: 33e31aef6aSopenharmony_ci node = super().generic_visit(node, *args, **kwargs) 34e31aef6aSopenharmony_ci 35e31aef6aSopenharmony_ci # Do constant folding. Some other nodes besides Expr have 36e31aef6aSopenharmony_ci # as_const, but folding them causes errors later on. 37e31aef6aSopenharmony_ci if isinstance(node, nodes.Expr): 38e31aef6aSopenharmony_ci try: 39e31aef6aSopenharmony_ci return nodes.Const.from_untrusted( 40e31aef6aSopenharmony_ci node.as_const(args[0] if args else None), 41e31aef6aSopenharmony_ci lineno=node.lineno, 42e31aef6aSopenharmony_ci environment=self.environment, 43e31aef6aSopenharmony_ci ) 44e31aef6aSopenharmony_ci except nodes.Impossible: 45e31aef6aSopenharmony_ci pass 46e31aef6aSopenharmony_ci 47e31aef6aSopenharmony_ci return node 48