tools/fix: rewrite integer division

This is the next step in phasing out the
integer division operators.

Change-Id: I652302855d3cd5611acd7871f02ba1ffee008d4d
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7824
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/tools/fix/fix.go b/tools/fix/fix.go
index e617edf..ce82077 100644
--- a/tools/fix/fix.go
+++ b/tools/fix/fix.go
@@ -31,6 +31,24 @@
 
 // File applies fixes to f and returns it. It alters the original f.
 func File(f *ast.File) *ast.File {
+	// Rewrite integer division operations to use builtins.
+	f = astutil.Apply(f, func(c astutil.Cursor) bool {
+		n := c.Node()
+		switch x := n.(type) {
+		case *ast.BinaryExpr:
+			switch x.Op {
+			case token.IDIV, token.IMOD, token.IQUO, token.IREM:
+				ast.SetRelPos(x.X, token.NoSpace)
+				c.Replace(&ast.CallExpr{
+					// Use the __foo version to prevent accidental shadowing.
+					Fun:  ast.NewIdent("__" + x.Op.String()),
+					Args: []ast.Expr{x.X, x.Y},
+				})
+			}
+		}
+		return true
+	}, nil).(*ast.File)
+
 	// Isolate bulk optional fields into a single struct.
 	ast.Walk(f, func(n ast.Node) bool {
 		var decls []ast.Decl
diff --git a/tools/fix/fix_test.go b/tools/fix/fix_test.go
index 06d2bd4..9ad093b 100644
--- a/tools/fix/fix_test.go
+++ b/tools/fix/fix_test.go
@@ -27,6 +27,22 @@
 		in   string
 		out  string
 	}{{
+		name: "rewrite integer division",
+		in: `package foo
+
+a: 1 div 2
+b: 3 mod 5
+c: 2 quo 9
+d: 1.0 rem 1.0 // pass on illegal values.
+`,
+		out: `package foo
+
+a: __div(1, 2)
+b: __mod(3, 5)
+c: __quo(2, 9)
+d: __rem(1.0, 1.0) // pass on illegal values.
+`,
+	}, {
 		name: "referenced quoted fields",
 		in: `package foo