References to known unassigned variables are now statically optimized to exception raises and warned about if the according option is enabled.

Unhashable keys in dictionaries are now statically optimized to exception raises and warned about if the according option is enabled.

Enable forward propagation for classes too, resulting in some classes to create only static dictionaries. Currently this never happens for Python3, but it will, once we can statically optimize __prepare__ too.

Enable inlining of class dictionary creations if they are mere return statements of the created dictionary. Currently this never happens for Python3, see above for why.

Python2: Selecting the metaclass is now visible in the tree and can be statically optimized.

For executables, we now also use a freelist for traceback objects, which also makes exception cases slightly faster.

Generator expressions no longer require the use of a function call with a .0 argument value to carry the iterator value, instead their creation is directly inlined.

Remove "pass through" frames for Python2 list contractions, they are no longer needed. Minimal gain for generated code, but more lightweight at compile time.

When compiling Windows x64 with MinGW64 a link library needs to be created for linking against the Python DLL. This one is now cached and re-used if already done.

Use common code for NameError and UnboundLocalError exception code raises. In some cases it was creating the full string at compile time, in others at run time. Since the later is more efficient in terms of code size, we now use that everywhere, saving a bit of binary size.

Make sure to release unused functions from a module. This saves memory and can be decided after a full pass.

Avoid using OrderedDict in a couple of places, where they are not needed, but can be replaced with a later sorting, e.g. temporary variables by name, to achieve deterministic output. This saves memory at compile time.

Add specialized return nodes for the most frequent constant values, which are None , True , and False . Also a general one, for constant value return, which avoids the constant references. This saves quite a bit of memory and makes traversal of the tree a lot faster, due to not having any child nodes for the new forms of return statements.

Previously the empty dictionary constant reference was specialized to save memory. Now we also specialize empty set, list, and tuple constants to the same end. Also the hack to make is not say that {} is {} was made more general, mutable constant references and now known to never alias.

The source references can be marked internal, which means that they should never be visible to the user, but that was tracked as a flag to each of the many source references attached to each node in the tree. Making a special class for internal references avoids storing this in the object, but instead it's now a class property.

The nodes for named variable reference, assignment, and deletion got split into separate nodes, one to be used before the actual variable can be determined during tree building, and one for use later on. This makes their API clearer and saves a tiny bit of memory at compile time.

Also eliminated target variable references, which were pseudo children of assignments and deletion nodes for variable names, that didn't really do much, but consume processing time and memory.

Added optimization for calls to staticmethod and classmethod built-in methods along with type shapes.

Added optimization for open built-in on Python3, also adding the type shape file for the result.

Added optimization for bytearray built-in and constant values. These mutable constants can now be compile time computed as well.

Added optimization for frozenset built-in and constant values. These mutable constants can now be compile time computed as well.

Added optimization for divmod built-in.

Treat all built-in constant types, e.g. type itself as a constant. So far we did this only for constant values types, but of course this applies to all types, giving slightly more compact code for their uses.

Detect static raises if iterating over non-iterables and warn about them if the option is enabled.

Split of locals node into different types, one which needs the updated value, and one which just makes a copy. Properly track if a functions needs an updated locals dict, and if it doesn't, don't use that. This gives more efficient code for Python2 classes, and exec using functions in Python2.

Build all constant values without use of the pickle module which has a lot more overhead than marshal , instead use that for too large long values, non-UTF8 unicode values, nan float, etc.