// valString returns the string representation for the value v. // Setting floatFmt forces an integer value to be formatted in // normalized floating-point format. // TODO(gri) Move this code into package exact. func valString(v exact.Value, floatFmt bool) string { switch v.Kind() { case exact.Int: if floatFmt { return floatString(v) } case exact.Float: return floatString(v) case exact.Complex: re := exact.Real(v) im := exact.Imag(v) var s string if exact.Sign(re) != 0 { s = floatString(re) if exact.Sign(im) >= 0 { s += " + " } else { s += " - " im = exact.UnaryOp(token.SUB, im, 0) // negate im } } // im != 0, otherwise v would be exact.Int or exact.Float return s + floatString(im) + "i" } return v.String() }
func (check *checker) unary(x *operand, op token.Token) { switch op { case token.AND: // spec: "As an exception to the addressability // requirement x may also be a composite literal." if _, ok := unparen(x.expr).(*ast.CompositeLit); ok { x.mode = variable } if x.mode != variable { check.invalidOp(x.pos(), "cannot take address of %s", x) x.mode = invalid return } x.typ = &Pointer{base: x.typ} return case token.ARROW: typ, ok := x.typ.Underlying().(*Chan) if !ok { check.invalidOp(x.pos(), "cannot receive from non-channel %s", x) x.mode = invalid return } if typ.dir&ast.RECV == 0 { check.invalidOp(x.pos(), "cannot receive from send-only channel %s", x) x.mode = invalid return } x.mode = commaok x.typ = typ.elem return } if !check.op(unaryOpPredicates, x, op) { x.mode = invalid return } if x.mode == constant { typ := x.typ.Underlying().(*Basic) size := -1 if isUnsigned(typ) { size = int(check.conf.sizeof(typ)) } x.val = exact.UnaryOp(op, x.val, size) // Typed constants must be representable in // their type after each constant operation. if isTyped(typ) { check.isRepresentableAs(x, typ) } return } x.mode = value // x.typ remains unchanged }
func (p *importer) fraction() exact.Value { sign := p.int() if sign == 0 { return exact.MakeInt64(0) } x := exact.BinaryOp(p.ufloat(), token.QUO, p.ufloat()) if sign < 0 { x = exact.UnaryOp(token.SUB, x, 0) } return x }
func doOp(x exact.Value, op token.Token, y exact.Value) (z exact.Value) { defer panicHandler(&z) if x == nil { return exact.UnaryOp(op, y, -1) } switch op { case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ: return exact.MakeBool(exact.Compare(x, op, y)) case token.SHL, token.SHR: s, _ := exact.Int64Val(y) return exact.Shift(x, op, uint(s)) default: return exact.BinaryOp(x, op, y) } }
func evalAction(n ast.Node) exact.Value { switch e := n.(type) { case *ast.BasicLit: return val(e.Value) case *ast.BinaryExpr: x := evalAction(e.X) if x == nil { return nil } y := evalAction(e.Y) if y == nil { return nil } switch e.Op { case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ: return exact.MakeBool(exact.Compare(x, e.Op, y)) case token.SHL, token.SHR: s, _ := exact.Int64Val(y) return exact.Shift(x, e.Op, uint(s)) default: return exact.BinaryOp(x, e.Op, y) } case *ast.UnaryExpr: return exact.UnaryOp(e.Op, evalAction(e.X), -1) case *ast.CallExpr: fmt.Printf("Can't handle call (%s) yet at pos %d\n", e.Fun, e.Pos()) return nil case *ast.Ident: fmt.Printf("Can't handle Ident %s here at pos %d\n", e.Name, e.Pos()) return nil case *ast.ParenExpr: return evalAction(e.X) default: fmt.Println("Can't handle") fmt.Printf("n: %s, e: %s\n", n, e) return nil } }