code: func (a *expr) convertToInt(max int64, negErr string, errOp string) *expr {
  	switch a.t.lit().(type) {
  	case *idealIntType:
  		val := a.asIdealInt()()
  		if negErr != "" && val.Sign() < 0 {
  			a.diag("negative %s: %s", negErr, val)
  			return nil
  		}
  		bound := max
  		if negErr == "slice" {
  			bound++
  		}
  		if max != -1 && val.Cmp(big.NewInt(bound)) >= 0 {
  			a.diag("index %s exceeds length %d", val, max)
  			return nil
  		}
  		return a.convertTo(IntType)
  
  	case *uintType:
  		// Convert to int
  		na := a.newExpr(IntType, a.desc)
  		af := a.asUint()
  		na.eval = func(t *Thread) int64 { return int64(af(t)) }
  		return na
  
  	case *intType:
  		// Good as is
  		return a
  	}
  
  	a.diag("illegal operand type for %s\n\t%v", errOp, a.t)
  	return nil
  }
docs: // convertToInt converts this expression to an integer, if possible,
  // or produces an error if not.  This accepts ideal ints, uints, and
  // ints.  If max is not -1, produces an error if possible if the value
  // exceeds max.  If negErr is not "", produces an error if possible if
  // the value is negative.