Example #1
0
// Conversion type-checks the conversion T(x).
// The result is in x.
func (check *Checker) conversion(x *operand, T Type) {
	constArg := x.mode == constant

	var ok bool
	switch {
	case constArg && isConstType(T):
		// constant conversion
		switch t := T.Underlying().(*Basic); {
		case representableConst(x.val, check.conf, t.kind, &x.val):
			ok = true
		case isInteger(x.typ) && isString(t):
			codepoint := int64(-1)
			if i, ok := exact.Int64Val(x.val); ok {
				codepoint = i
			}
			// If codepoint < 0 the absolute value is too large (or unknown) for
			// conversion. This is the same as converting any other out-of-range
			// value - let string(codepoint) do the work.
			x.val = exact.MakeString(string(codepoint))
			ok = true
		}
	case x.convertibleTo(check.conf, T):
		// non-constant conversion
		x.mode = value
		ok = true
	}

	if !ok {
		check.errorf(x.pos(), "cannot convert %s to %s", x, T)
		x.mode = invalid
		return
	}

	// The conversion argument types are final. For untyped values the
	// conversion provides the type, per the spec: "A constant may be
	// given a type explicitly by a constant declaration or conversion,...".
	final := x.typ
	if isUntyped(x.typ) {
		final = T
		// - For conversions to interfaces, use the argument's default type.
		// - For conversions of untyped constants to non-constant types, also
		//   use the default type (e.g., []byte("foo") should report string
		//   not []byte as type for the constant "foo").
		// - Keep untyped nil for untyped nil arguments.
		if IsInterface(T) || constArg && !isConstType(T) {
			final = defaultType(x.typ)
		}
		check.updateExprType(x.expr, final, true)
	}

	x.typ = T
}
Example #2
0
func (c *checker) InsertMetricValuesFromContext(m *metrics.MetricContext) error {
	for metricName, metric := range m.Gauges {
		name := strings.Replace(metricName, ".", "_", -1) + "_value"
		c.sc.Insert(types.NewConst(0, c.pkg, name,
			types.Typ[types.Float64], exact.MakeFloat64(metric.Get())))
		sname := name + "_string"
		c.sc.Insert(types.NewConst(0, c.pkg, sname,
			types.Typ[types.String], exact.MakeString(fmt.Sprintf("%0.2f", metric.Get()))))
	}
	for metricName, metric := range m.Counters {
		name := strings.Replace(metricName, ".", "_", -1) + "_current"
		c.sc.Insert(types.NewConst(0, c.pkg, name,
			types.Typ[types.Uint64], exact.MakeUint64(metric.Get())))
		sname := name + "_string"
		c.sc.Insert(types.NewConst(0, c.pkg, sname,
			types.Typ[types.String], exact.MakeString(fmt.Sprintf("%d", metric.Get()))))
		name = strings.Replace(metricName, ".", "_", -1) + "_rate"
		c.sc.Insert(types.NewConst(0, c.pkg, name,
			types.Typ[types.Float64], exact.MakeFloat64(metric.ComputeRate())))
	}
	return nil
}