func panicHandler(v *exact.Value) { switch p := recover().(type) { case nil: // nothing to do case string: *v = exact.MakeString(p) case error: *v = exact.MakeString(p.Error()) default: panic(p) } }
// zeroConst returns a new "zero" constant of the specified type, // which must not be an array or struct type: the zero values of // aggregates are well-defined but cannot be represented by Const. // func zeroConst(t types.Type) *Const { switch t := t.(type) { case *types.Basic: switch { case t.Info()&types.IsBoolean != 0: return NewConst(exact.MakeBool(false), t) case t.Info()&types.IsNumeric != 0: return NewConst(exact.MakeInt64(0), t) case t.Info()&types.IsString != 0: return NewConst(exact.MakeString(""), t) case t.Kind() == types.UnsafePointer: fallthrough case t.Kind() == types.UntypedNil: return nilConst(t) default: panic(fmt.Sprint("zeroConst for unexpected type:", t)) } case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature: return nilConst(t) case *types.Named: return NewConst(zeroConst(t.Underlying()).Value, t) case *types.Array, *types.Struct, *types.Tuple: panic(fmt.Sprint("zeroConst applied to aggregate:", t)) } panic(fmt.Sprint("zeroConst: unexpected ", t)) }
// 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 x.isInteger() && 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 }
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.New("float64"), exact.MakeFloat64(metric.Get()))) sname := name + "_string" c.sc.Insert(types.NewConst(0, c.pkg, sname, types.New("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.New("float64"), exact.MakeUint64(metric.Get()))) sname := name + "_string" c.sc.Insert(types.NewConst(0, c.pkg, sname, types.New("string"), exact.MakeString(fmt.Sprintf("%d", metric.Get())))) name = strings.Replace(metricName, ".", "_", -1) + "_rate" c.sc.Insert(types.NewConst(0, c.pkg, name, types.New("float64"), exact.MakeFloat64(metric.ComputeRate()))) } return nil }
// testMainSlice emits to fn code to construct a slice of type slice // (one of []testing.Internal{Test,Benchmark,Example}) for all // functions in this package whose name starts with prefix (one of // "Test", "Benchmark" or "Example") and whose type is appropriate. // It returns the slice value. // func testMainSlice(fn *Function, prefix string, slice types.Type) Value { tElem := slice.(*types.Slice).Elem() tFunc := tElem.Underlying().(*types.Struct).Field(1).Type() var testfuncs []*Function for name, mem := range fn.Pkg.Members { if fn, ok := mem.(*Function); ok && isTest(name, prefix) && types.IsIdentical(fn.Signature, tFunc) { testfuncs = append(testfuncs, fn) } } if testfuncs == nil { return nilConst(slice) } tString := types.Typ[types.String] tPtrString := types.NewPointer(tString) tPtrElem := types.NewPointer(tElem) tPtrFunc := types.NewPointer(tFunc) // Emit: array = new [n]testing.InternalTest tArray := types.NewArray(tElem, int64(len(testfuncs))) array := emitNew(fn, tArray, token.NoPos) array.Comment = "test main" for i, testfunc := range testfuncs { // Emit: pitem = &array[i] ia := &IndexAddr{X: array, Index: intConst(int64(i))} ia.setType(tPtrElem) pitem := fn.emit(ia) // Emit: pname = &pitem.Name fa := &FieldAddr{X: pitem, Field: 0} // .Name fa.setType(tPtrString) pname := fn.emit(fa) // Emit: *pname = "testfunc" emitStore(fn, pname, NewConst(exact.MakeString(testfunc.Name()), tString)) // Emit: pfunc = &pitem.F fa = &FieldAddr{X: pitem, Field: 1} // .F fa.setType(tPtrFunc) pfunc := fn.emit(fa) // Emit: *pfunc = testfunc emitStore(fn, pfunc, testfunc) } // Emit: slice array[:] sl := &Slice{X: array} sl.setType(slice) return fn.emit(sl) }
func (v *LLVMValue) mustConvertI2V(typ types.Type) Value { result, ok := v.convertI2V(typ) c, builder := v.compiler, v.compiler.builder end := llvm.InsertBasicBlock(builder.GetInsertBlock(), "end") end.MoveAfter(builder.GetInsertBlock()) failed := llvm.InsertBasicBlock(end, "failed") builder.CreateCondBr(ok.LLVMValue(), end, failed) builder.SetInsertPointAtEnd(failed) s := fmt.Sprintf("convertI2V(%s, %s) failed", v.typ, typ) c.visitPanic(c.NewConstValue(exact.MakeString(s), types.Typ[types.String])) builder.SetInsertPointAtEnd(end) return result }
func (p *importer) value() exact.Value { switch kind := exact.Kind(p.int()); kind { case falseTag: return exact.MakeBool(false) case trueTag: return exact.MakeBool(true) case int64Tag: return exact.MakeInt64(p.int64()) case floatTag: return p.float() case fractionTag: return p.fraction() case complexTag: re := p.fraction() im := p.fraction() return exact.BinaryOp(re, token.ADD, exact.MakeImag(im)) case stringTag: return exact.MakeString(p.string()) default: panic(fmt.Sprintf("unexpected value kind %d", kind)) } }
func (c *compiler) printf(format string, args ...interface{}) { s := exact.MakeString(fmt.Sprintf(format, args...)) c.printValues(true, c.NewConstValue(s, types.Typ[types.String])) }
// stringConst returns a 'string' constant that evaluates to s. func stringConst(s string) *Const { return NewConst(exact.MakeString(s), tString) }
// ConstValue = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) . // FloatOrComplex = float ["i" | ("+"|"-") float "i"] . func (p *parser) parseConstValue() (val exact.Value, typ types.Type) { switch p.tok { case scanner.String: str := p.parseString() val = exact.MakeString(str) typ = types.Typ[types.UntypedString] return case scanner.Ident: b := false switch p.lit { case "false": case "true": b = true default: p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit) } p.next() val = exact.MakeBool(b) typ = types.Typ[types.UntypedBool] return } sign := "" if p.tok == '-' { p.next() sign = "-" } switch p.tok { case scanner.Int: val = exact.MakeFromLiteral(sign+p.lit, token.INT) if val == nil { p.error("could not parse integer literal") } p.next() if p.tok == '\'' { p.next() typ = types.Typ[types.UntypedRune] } else { typ = types.Typ[types.UntypedInt] } case scanner.Float: re := sign + p.lit p.next() var im string switch p.tok { case '+': p.next() im = p.expect(scanner.Float) case '-': p.next() im = "-" + p.expect(scanner.Float) case scanner.Ident: // re is in fact the imaginary component. Expect "i" below. im = re re = "0" default: val = exact.MakeFromLiteral(re, token.FLOAT) if val == nil { p.error("could not parse float literal") } typ = types.Typ[types.UntypedFloat] return } p.expectKeyword("i") reval := exact.MakeFromLiteral(re, token.FLOAT) if reval == nil { p.error("could not parse real component of complex literal") } imval := exact.MakeFromLiteral(im+"i", token.IMAG) if imval == nil { p.error("could not parse imag component of complex literal") } val = exact.BinaryOp(reval, token.ADD, imval) typ = types.Typ[types.UntypedComplex] default: p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit) } return }