Every programming language aims to be performant in its niche and achieving superior performance requires a lot of compiler level optimizations. One famous optimization technique is Constant Folding where during compile time the engine tries to recognize constant expressions, evaluate them, and replaces the expression with this newly evaluated value, making the runtime leaner.
A subtle point: because constant folding is applied recursively on the already-generated AST, its ability to fold is impacted by how that tree was constructed by the parser. For example, it cannot reorder commutative operations:
```
dis.dis("foo = bar * 2 * foo * 3")
1 0 LOAD_NAME 0 (bar)
3 LOAD_CONST 0 (2)
6 BINARY_MULTIPLY
7 LOAD_NAME 1 (foo)
10 BINARY_MULTIPLY
11 LOAD_CONST 1 (3)
14 BINARY_MULTIPLY
15 STORE_NAME 1 (foo)
18 LOAD_CONST 2 (None)
21 RETURN_VALUE
```
If you manually reorder the expression so the constants appear next to each other, the parser will drop them in the AST as children of the same binop node. In that case, constant folding will work.
A subtle point: because constant folding is applied recursively on the already-generated AST, its ability to fold is impacted by how that tree was constructed by the parser. For example, it cannot reorder commutative operations:
```
dis.dis("foo = bar * 2 * foo * 3")
1 0 LOAD_NAME 0 (bar)
3 LOAD_CONST 0 (2)
6 BINARY_MULTIPLY
7 LOAD_NAME 1 (foo)
10 BINARY_MULTIPLY
11 LOAD_CONST 1 (3)
14 BINARY_MULTIPLY
15 STORE_NAME 1 (foo)
18 LOAD_CONST 2 (None)
21 RETURN_VALUE
```
If you manually reorder the expression so the constants appear next to each other, the parser will drop them in the AST as children of the same binop node. In that case, constant folding will work.
```
dis.dis("foo = 2 * 3 * bar * foo")
1 0 LOAD_CONST 3 (6)
3 LOAD_NAME 0 (bar)
6 BINARY_MULTIPLY
7 LOAD_NAME 1 (foo)
10 BINARY_MULTIPLY
11 STORE_NAME 1 (foo)
14 LOAD_CONST 2 (None)
17 RETURN_VALUE
```