Credence.Syntax.FixPythonAugmentedAssignment
(credence v0.7.1)
Copy Markdown
Replaces Python's augmented assignment operators (+=, -=, *=, /=)
with Elixir's rebinding syntax.
LLMs translating from Python carry over augmented assignment operators.
In Elixir, += and friends are not valid — variables are rebound with =,
so x += expr must become x = x + (expr).
This is a Syntax rule because x += y won't parse in Elixir.
Detected patterns
Only a standalone statement whose left-hand side is a bare variable is
rewritten — the line must be <indent><identifier> <op>= <expr> and nothing
else:
count += 1 x -= delta
total *= factor value /= divisorWhy the right-hand side is parenthesised
Python's x op= expr means x = x op (expr) — the whole right-hand side is
one operand. A naive textual rewrite to x = x op expr changes the answer
whenever expr contains a lower-precedence operator: x *= a + b would
become x = x * a + b ((x*a)+b) instead of x = x * (a + b). Wrapping the
right-hand side in parentheses keeps the result bit-identical to Python
semantics for every expression.
Not flagged
Anything that isn't a bare-variable augmented assignment is left untouched, so no valid code is ever corrupted:
- operators appearing inside string literals (
x = "a += b") — theop=is not the line's leading token, so it never matches; - qualified or indexed targets (
map.count += 1,arr[i] += 1) — Elixir can't rebind those anyway, and a bare-identifier rewrite would be wrong; - comment lines.
+=, -=, *=, and /= are not substrings of any valid Elixir operator,
so an anchored, leading-identifier match cannot fire on legitimate code.
Bad
count += Map.get(freq, key, 0)
total *= factorGood
count = count + (Map.get(freq, key, 0))
total = total * (factor)