Previously, we would generate parentheses proactively when generating
binary ops, however, this leads to uglier code and hits warnings in
compilers when used as a conditional.
There was a potential problem if variables were invalidated and SPIR-V
read expressions which depended on other expression which in turn depended on the
invalidated variable.
Also fixes issue where variables were considered immutable if they were
forwardable. This allowed some incorrect optimizations to slip through.