Refactor cgen's writeStatementAssign
diff --git a/internal/cgen/statement.go b/internal/cgen/statement.go
index a5e9e25..a16e66a 100644
--- a/internal/cgen/statement.go
+++ b/internal/cgen/statement.go
@@ -95,22 +95,23 @@
 		}
 	}
 
-	couldSuspend := false
-	if err := g.writeBuiltinQuestionCall(b, rhs, 0); err == nil {
-		// No-op.
-	} else if err != errNoSuchBuiltin {
-		return err
-	} else {
-		if err := g.writeStatementAssign0(b, op, lhs, rhs); err != nil {
+	couldSuspend, skipRHS := false, false
+	if rhs.Effect().Coroutine() {
+		if err := g.writeBuiltinQuestionCall(b, rhs, 0); err == nil {
+			skipRHS = true
+		} else if err != errNoSuchBuiltin {
 			return err
+		} else if op != t.IDEqQuestion {
+			if err := g.writeCoroSuspPoint(b, false); err != nil {
+				return err
+			}
+			b.writes("status = ")
+			couldSuspend = true
 		}
-		couldSuspend = (op != t.IDEqQuestion) && rhs.Effect().Coroutine()
 	}
 
-	if lhs != nil {
-		if err := g.writeStatementAssign1(b, op, lhs, rhs); err != nil {
-			return err
-		}
+	if err := g.writeStatementAssign1(b, op, lhs, rhs, skipRHS); err != nil {
+		return err
 	}
 	if needWriteLoadExprDerivedVars {
 		if err := g.writeLoadExprDerivedVars(b, rhs); err != nil {
@@ -123,69 +124,61 @@
 	return nil
 }
 
-func (g *gen) writeStatementAssign0(b *buffer, op t.ID, lhs *a.Expr, rhs *a.Expr) error {
-	if (lhs == nil) || rhs.Effect().Coroutine() {
-		if op == t.IDEqQuestion {
-			if g.currFunk.tempW > maxTemp {
-				return fmt.Errorf("too many temporary variables required")
-			}
-			temp := g.currFunk.tempW
-			g.currFunk.tempW++
+func (g *gen) writeStatementAssign1(b *buffer, op t.ID, lhs *a.Expr, rhs *a.Expr, skipRHS bool) error {
+	lhsBuf := buffer(nil)
+	opName, closer, disableWconversion := "", "", false
 
-			b.printf("wuffs_base__status %s%d = ", tPrefix, temp)
-		} else if rhs.Effect().Coroutine() {
-			if err := g.writeCoroSuspPoint(b, false); err != nil {
-				return err
-			}
-			b.writes("status = ")
-		}
-
-		if err := g.writeExpr(b, rhs, 0); err != nil {
+	if lhs != nil {
+		if err := g.writeExpr(&lhsBuf, lhs, 0); err != nil {
 			return err
 		}
-		b.writes(";\n")
-	}
 
-	return nil
-}
+		if lTyp := lhs.MType(); lTyp.IsArrayType() {
+			b.writes("memcpy(")
+			opName, closer = ",", fmt.Sprintf(", sizeof(%s))", lhsBuf)
 
-func (g *gen) writeStatementAssign1(b *buffer, op t.ID, lhs *a.Expr, rhs *a.Expr) error {
-	lhsBuf := buffer(nil)
-	if err := g.writeExpr(&lhsBuf, lhs, 0); err != nil {
-		return err
-	}
-
-	opName, closer, disableWconversion := "", "", false
-	if lTyp := lhs.MType(); lTyp.IsArrayType() {
-		b.writes("memcpy(")
-		opName, closer = ",", fmt.Sprintf(", sizeof(%s))", lhsBuf)
-
-	} else {
-		switch op {
-		case t.IDTildeSatPlusEq, t.IDTildeSatMinusEq:
-			uBits := uintBits(lTyp.QID())
-			if uBits == 0 {
-				return fmt.Errorf("unsupported tilde-operator type %q", lTyp.Str(g.tm))
-			}
-			uOp := "add"
-			if op != t.IDTildeSatPlusEq {
-				uOp = "sub"
-			}
-			b.printf("wuffs_base__u%d__sat_%s_indirect(&", uBits, uOp)
-			opName, closer = ", ", ")"
-
-		case t.IDPlusEq, t.IDMinusEq:
-			if lTyp.IsNumType() {
-				if u := lTyp.QID()[1]; u == t.IDU8 || u == t.IDU16 {
-					disableWconversion = true
+		} else {
+			switch op {
+			case t.IDEqQuestion:
+				opName = cOpName(t.IDEqQuestion)
+				if g.currFunk.tempW > maxTemp {
+					return fmt.Errorf("too many temporary variables required")
 				}
-			}
-			fallthrough
+				temp := g.currFunk.tempW
+				g.currFunk.tempW++
 
-		default:
-			opName = cOpName(op)
-			if opName == "" {
-				return fmt.Errorf("unrecognized operator %q", op.AmbiguousForm().Str(g.tm))
+				b.printf("wuffs_base__status %s%d = ", tPrefix, temp)
+
+				if err := g.writeExpr(b, rhs, 0); err != nil {
+					return err
+				}
+				b.writes(";\n")
+
+			case t.IDTildeSatPlusEq, t.IDTildeSatMinusEq:
+				uBits := uintBits(lTyp.QID())
+				if uBits == 0 {
+					return fmt.Errorf("unsupported tilde-operator type %q", lTyp.Str(g.tm))
+				}
+				uOp := "add"
+				if op != t.IDTildeSatPlusEq {
+					uOp = "sub"
+				}
+				b.printf("wuffs_base__u%d__sat_%s_indirect(&", uBits, uOp)
+				opName, closer = ", ", ")"
+
+			case t.IDPlusEq, t.IDMinusEq:
+				if lTyp.IsNumType() {
+					if u := lTyp.QID()[1]; u == t.IDU8 || u == t.IDU16 {
+						disableWconversion = true
+					}
+				}
+				fallthrough
+
+			default:
+				opName = cOpName(op)
+				if opName == "" {
+					return fmt.Errorf("unrecognized operator %q", op.AmbiguousForm().Str(g.tm))
+				}
 			}
 		}
 	}
@@ -200,19 +193,24 @@
 		b.writes("#endif\n")
 	}
 
+	n := len(*b)
 	b.writex(lhsBuf)
 	b.writes(opName)
-	if rhs.Effect().Coroutine() {
+	if g.currFunk.tempR != g.currFunk.tempW {
 		if g.currFunk.tempR != (g.currFunk.tempW - 1) {
 			return fmt.Errorf("internal error: temporary variable count out of sync")
 		}
 		b.printf("%s%d", tPrefix, g.currFunk.tempR)
 		g.currFunk.tempR++
+	} else if skipRHS {
+		// No-op.
 	} else if err := g.writeExpr(b, rhs, 0); err != nil {
 		return err
 	}
 	b.writes(closer)
-	b.writes(";\n")
+	if n != len(*b) {
+		b.writes(";\n")
+	}
 
 	if disableWconversion {
 		b.writes("#if defined(__GNUC__)\n")