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 /= divisor

Why 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") — the op= 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 *= factor

Good

count = count + (Map.get(freq, key, 0))
total = total * (factor)