作者:samuelyao31
项目:myg
// 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()
}
作者:samuelyao31
项目:myg
// floatString returns the string representation for a
// numeric value v in normalized floating-point format.
func floatString(v exact.Value) string {
if exact.Sign(v) == 0 {
return "0.0"
}
// x != 0
// convert |v| into a big.Rat x
x := new(big.Rat).SetFrac(absInt(exact.Num(v)), absInt(exact.Denom(v)))
// normalize x and determine exponent e
// (This is not very efficient, but also not speed-critical.)
var e int
for x.Cmp(ten) >= 0 {
x.Quo(x, ten)
e++
}
for x.Cmp(one) < 0 {
x.Mul(x, ten)
e--
}
// TODO(gri) Values such as 1/2 are easier to read in form 0.5
// rather than 5.0e-1. Similarly, 1.0e1 is easier to read as
// 10.0. Fine-tune best exponent range for readability.
s := x.FloatString(100) // good-enough precision
// trim trailing 0's
i := len(s)
for i > 0 && s[i-1] == '0' {
i--
}
s = s[:i]
// add a 0 if the number ends in decimal point
if len(s) > 0 && s[len(s)-1] == '.' {
s += "0"
}
// add exponent and sign
if e != 0 {
s += fmt.Sprintf("e%+d", e)
}
if exact.Sign(v) < 0 {
s = "-" + s
}
// TODO(gri) If v is a "small" fraction (i.e., numerator and denominator
// are just a small number of decimal digits), add the exact fraction as
// a comment. For instance: 3.3333...e-1 /* = 1/3 */
return s
}
作者:hackrol
项目:daily-progra
func (p *exporter) float(x exact.Value) {
sign := exact.Sign(x)
p.int(sign)
if sign == 0 {
return
}
p.ufloat(x)
}
作者:hackrol
项目:daily-progra
func (p *exporter) fraction(x exact.Value) {
sign := exact.Sign(x)
p.int(sign)
if sign == 0 {
return
}
p.ufloat(exact.Num(x))
p.ufloat(exact.Denom(x))
}
作者:rjammal
项目:emg
func (cdd *CDD) Value(w *bytes.Buffer, ev exact.Value, t types.Type) {
k := t.Underlying().(*types.Basic).Kind()
// TODO: use t instead ev.Kind() in following switch
switch ev.Kind() {
case exact.Int:
writeInt(w, ev, k)
case exact.Float:
writeFloat(w, ev, k)
case exact.Complex:
switch k {
case types.Complex64:
k = types.Float32
case types.Complex128:
k = types.Float64
default:
k = types.UntypedFloat
}
writeFloat(w, exact.Real(ev), k)
im := exact.Imag(ev)
if exact.Sign(im) != -1 {
w.WriteByte('+')
}
writeFloat(w, im, k)
w.WriteByte('i')
case exact.String:
w.WriteString("EGSTR(")
w.WriteString(ev.String())
w.WriteByte(')')
default:
w.WriteString(ev.String())
}
}
作者:hackrol
项目:daily-progra
// index checks an index expression for validity.
// If max >= 0, it is the upper bound for index.
// If index is valid and the result i >= 0, then i is the constant value of index.
func (check *Checker) index(index ast.Expr, max int64) (i int64, valid bool) {
var x operand
check.expr(&x, index)
if x.mode == invalid {
return
}
// an untyped constant must be representable as Int
check.convertUntyped(&x, Typ[Int])
if x.mode == invalid {
return
}
// the index must be of integer type
if !isInteger(x.typ) {
check.invalidArg(x.pos(), "index %s must be integer", &x)
return
}
// a constant index i must be in bounds
if x.mode == constant {
if exact.Sign(x.val) < 0 {
check.invalidArg(x.pos(), "index %s must not be negative", &x)
return
}
i, valid = exact.Int64Val(x.val)
if !valid || max >= 0 && i >= max {
check.errorf(x.pos(), "index %s is out of bounds", &x)
return i, false
}
// 0 <= i [ && i < max ]
return i, true
}
return -1, true
}
作者:hackrol
项目:daily-progra
func (check *Checker) binary(x *operand, lhs, rhs ast.Expr, op token.Token) {
var y operand
check.expr(x, lhs)
check.expr(&y, rhs)
if x.mode == invalid {
return
}
if y.mode == invalid {
x.mode = invalid
x.expr = y.expr
return
}
if isShift(op) {
check.shift(x, &y, op)
return
}
check.convertUntyped(x, y.typ)
if x.mode == invalid {
return
}
check.convertUntyped(&y, x.typ)
if y.mode == invalid {
x.mode = invalid
return
}
if isComparison(op) {
check.comparison(x, &y, op)
return
}
if !Identical(x.typ, y.typ) {
// only report an error if we have valid types
// (otherwise we had an error reported elsewhere already)
if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] {
check.invalidOp(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
}
x.mode = invalid
return
}
if !check.op(binaryOpPredicates, x, op) {
x.mode = invalid
return
}
if (op == token.QUO || op == token.REM) && (x.mode == constant || isInteger(x.typ)) && y.mode == constant && exact.Sign(y.val) == 0 {
check.invalidOp(y.pos(), "division by zero")
x.mode = invalid
return
}
if x.mode == constant && y.mode == constant {
typ := x.typ.Underlying().(*Basic)
// force integer division of integer operands
if op == token.QUO && isInteger(typ) {
op = token.QUO_ASSIGN
}
x.val = exact.BinaryOp(x.val, op, y.val)
// Typed constants must be representable in
// their type after each constant operation.
if isTyped(typ) {
check.representable(x, typ)
}
return
}
x.mode = value
// x.typ is unchanged
}
作者:hackrol
项目:daily-progra
func (check *Checker) shift(x, y *operand, op token.Token) {
untypedx := isUntyped(x.typ)
// The lhs must be of integer type or be representable
// as an integer; otherwise the shift has no chance.
if !isInteger(x.typ) && (!untypedx || !representableConst(x.val, nil, UntypedInt, nil)) {
check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
x.mode = invalid
return
}
// spec: "The right operand in a shift expression must have unsigned
// integer type or be an untyped constant that can be converted to
// unsigned integer type."
switch {
case isInteger(y.typ) && isUnsigned(y.typ):
// nothing to do
case isUntyped(y.typ):
check.convertUntyped(y, Typ[UntypedInt])
if y.mode == invalid {
x.mode = invalid
return
}
default:
check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y)
x.mode = invalid
return
}
if x.mode == constant {
if y.mode == constant {
// rhs must be within reasonable bounds
const stupidShift = 1023 - 1 + 52 // so we can express smallestFloat64
s, ok := exact.Uint64Val(y.val)
if !ok || s > stupidShift {
check.invalidOp(y.pos(), "stupid shift count %s", y)
x.mode = invalid
return
}
// The lhs is representable as an integer but may not be an integer
// (e.g., 2.0, an untyped float) - this can only happen for untyped
// non-integer numeric constants. Correct the type so that the shift
// result is of integer type.
if !isInteger(x.typ) {
x.typ = Typ[UntypedInt]
}
x.val = exact.Shift(x.val, op, uint(s))
return
}
// non-constant shift with constant lhs
if untypedx {
// spec: "If the left operand of a non-constant shift
// expression is an untyped constant, the type of the
// constant is what it would be if the shift expression
// were replaced by its left operand alone.".
//
// Delay operand checking until we know the final type:
// The lhs expression must be in the untyped map, mark
// the entry as lhs shift operand.
info, found := check.untyped[x.expr]
assert(found)
info.isLhs = true
check.untyped[x.expr] = info
// keep x's type
x.mode = value
return
}
}
// constant rhs must be >= 0
if y.mode == constant && exact.Sign(y.val) < 0 {
check.invalidOp(y.pos(), "shift count %s must not be negative", y)
}
// non-constant shift - lhs must be an integer
if !isInteger(x.typ) {
check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
x.mode = invalid
return
}
x.mode = value
}
作者:hackrol
项目:daily-progra
// representableConst reports whether x can be represented as
// value of the given basic type kind and for the configuration
// provided (only needed for int/uint sizes).
//
// If rounded != nil, *rounded is set to the rounded value of x for
// representable floating-point values; it is left alone otherwise.
// It is ok to provide the addressof the first argument for rounded.
func representableConst(x exact.Value, conf *Config, as BasicKind, rounded *exact.Value) bool {
switch x.Kind() {
case exact.Unknown:
return true
case exact.Bool:
return as == Bool || as == UntypedBool
case exact.Int:
if x, ok := exact.Int64Val(x); ok {
switch as {
case Int:
var s = uint(conf.sizeof(Typ[as])) * 8
return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1
case Int8:
const s = 8
return -1<<(s-1) <= x && x <= 1<<(s-1)-1
case Int16:
const s = 16
return -1<<(s-1) <= x && x <= 1<<(s-1)-1
case Int32:
const s = 32
return -1<<(s-1) <= x && x <= 1<<(s-1)-1
case Int64:
return true
case Uint, Uintptr:
if s := uint(conf.sizeof(Typ[as])) * 8; s < 64 {
return 0 <= x && x <= int64(1)<<s-1
}
return 0 <= x
case Uint8:
const s = 8
return 0 <= x && x <= 1<<s-1
case Uint16:
const s = 16
return 0 <= x && x <= 1<<s-1
case Uint32:
const s = 32
return 0 <= x && x <= 1<<s-1
case Uint64:
return 0 <= x
case Float32, Float64, Complex64, Complex128,
UntypedInt, UntypedFloat, UntypedComplex:
return true
}
}
n := exact.BitLen(x)
switch as {
case Uint, Uintptr:
var s = uint(conf.sizeof(Typ[as])) * 8
return exact.Sign(x) >= 0 && n <= int(s)
case Uint64:
return exact.Sign(x) >= 0 && n <= 64
case Float32, Complex64:
if rounded == nil {
return fitsFloat32(x)
}
r := roundFloat32(x)
if r != nil {
*rounded = r
return true
}
case Float64, Complex128:
if rounded == nil {
return fitsFloat64(x)
}
r := roundFloat64(x)
if r != nil {
*rounded = r
return true
}
case UntypedInt, UntypedFloat, UntypedComplex:
return true
}
case exact.Float:
switch as {
case Float32, Complex64:
if rounded == nil {
return fitsFloat32(x)
}
r := roundFloat32(x)
if r != nil {
*rounded = r
return true
}
case Float64, Complex128:
if rounded == nil {
return fitsFloat64(x)
}
r := roundFloat64(x)
if r != nil {
//.........这里部分代码省略.........