cue: fix number output
Ensure that numbers of type float have
a dot in them to retain their type.
Also:
- removes stripping of trailing zeros after
division.
- fixes a bug where the type of a resulting
number is determined using old semantics.
- fixes a blatant typing bug.
Fixes #233
Change-Id: I2cc524923f189bdf8cb25dd72a1667ee2f2097d0
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/4400
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/binop.go b/cue/binop.go
index 86dca45..38dcdb1 100644
--- a/cue/binop.go
+++ b/cue/binop.go
@@ -452,10 +452,16 @@
case diff == 1:
if k&floatKind == 0 {
if x.op == opGeq && y.op == opLss {
- return &numLit{numBase: a.numBase, v: lo}
+ n := *a
+ n.k = k & numKind
+ n.v.Set(&lo)
+ return &n
}
if x.op == opGtr && y.op == opLeq {
- return &numLit{numBase: b.numBase, v: hi}
+ n := *b
+ n.k = k & numKind
+ n.v.Set(&hi)
+ return &n
}
}
@@ -1047,7 +1053,6 @@
if cond.DivisionByZero() {
return ctx.mkErr(src, "division by zero")
}
- _, _, _ = ctx.Reduce(&n.v, &n.v)
n.k = floatKind
case opIDiv:
if y.v.IsZero() {
diff --git a/cue/debug.go b/cue/debug.go
index 17d8f2f..e525c17 100644
--- a/cue/debug.go
+++ b/cue/debug.go
@@ -432,11 +432,7 @@
str = str[1 : len(str)-1]
writef("'%s'", str)
case *numLit:
- if x.k&intKind != 0 {
- write(x.v.Text('f')) // also render info
- } else {
- write(x.v.Text('g')) // also render info
- }
+ write(x.String())
case *durationLit:
write(x.d.String())
case *bound:
diff --git a/cue/export.go b/cue/export.go
index 9990072..36fdc83 100644
--- a/cue/export.go
+++ b/cue/export.go
@@ -550,16 +550,11 @@
}
case *numLit:
+ kind := token.FLOAT
if x.k&intKind != 0 {
- return &ast.BasicLit{
- Kind: token.INT,
- Value: x.v.Text('f'),
- }
+ kind = token.INT
}
- return &ast.BasicLit{
- Kind: token.FLOAT,
- Value: x.v.Text('g'),
- }
+ return &ast.BasicLit{Kind: kind, Value: x.String()}
case *durationLit:
panic("unimplemented")
diff --git a/cue/go.go b/cue/go.go
index d2a2225..09c1ae6 100644
--- a/cue/go.go
+++ b/cue/go.go
@@ -452,7 +452,7 @@
}
func toUint(ctx *context, src source, x uint64) evaluated {
- n := newNum(src, floatKind)
+ n := newNum(src, intKind)
n.v.Coeff.SetUint64(x)
return n
}
diff --git a/cue/lit.go b/cue/lit.go
index 57ace1f..325f9e5 100644
--- a/cue/lit.go
+++ b/cue/lit.go
@@ -47,11 +47,6 @@
return numInfo{m, k}
}
-func unifyNuminfo(a, b numInfo) numInfo {
- k := unifyType(a.k, b.k)
- return numInfo{a.rep | b.rep, k}
-}
-
func (n numInfo) isValid() bool { return n.k != bottomKind }
func (n numInfo) multiplier() multiplier { return n.rep & (hasSeparators - 1) }
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index 26bde55..3733af9 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -137,9 +137,11 @@
sum: -1 + +2 // 1
div1: 2.0 / 3 * 6 // 4
div2: 2 / 3 * 6 // 4
+ div3: 1.00 / 1.00
divZero: 1.0 / 0
div00: 0 / 0
b: 1 != 4
+ add: div1 + 1.0
idiv00: 0 div 0
imod00: 0 mod 0
@@ -166,14 +168,16 @@
`sum: 1, ` +
`div1: 4.00000000000000000000000, ` +
`div2: 4.00000000000000000000000, ` +
+ `div3: 1., ` +
`divZero: _|_((1.0 / 0):division by zero), ` +
`div00: _|_((0 / 0):division undefined), ` +
`b: true, ` +
+ `add: 5.00000000000000000000000, ` +
`idiv00: _|_((0 div 0):division by zero), ` +
`imod00: _|_((0 mod 0):division by zero), ` +
`iquo00: _|_((0 quo 0):division by zero), ` +
`irem00: _|_((0 rem 0):division by zero), ` +
- `v1: 5e+11, ` +
+ `v1: 5.0000000000e+11, ` +
`v2: true, ` +
`v3: 0.666666666666666666666667, ` +
`v5: 0, ` +
@@ -611,9 +615,10 @@
v2: 2.0 == 2
n1: 1
v5: 2.0 / n1
+ v6: 1.0 / 1.0
e2: int & 4.0/2.0
`,
- out: `<0>{v1: 5e+11, v2: true, n1: 1, v5: 2, e2: _|_((int & (4.0 / 2.0)):conflicting values int and (4.0 / 2.0) (mismatched types int and float))}`,
+ out: `<0>{v1: 5.0000000000e+11, v2: true, n1: 1, v5: 2.0, v6: 1., e2: _|_((int & (4.0 / 2.0)):conflicting values int and (4.0 / 2.0) (mismatched types int and float))}`,
}, {
desc: "inequality",
in: `
@@ -768,6 +773,7 @@
}, {
desc: "bound conversions",
in: `
+ r0: int & >0.1 & <=1.9
r1: int & >0.1 & <1.9
r2: int & >=0.1 & <1.9
r3: int & >=-1.9 & <=-0.1
@@ -783,6 +789,7 @@
c4: 1.2 & (>=1 & <2 & int)
`,
out: `<0>{` +
+ `r0: 1, ` +
`r1: 1, ` +
`r2: 1, ` +
`r3: -1, ` +
diff --git a/cue/types.go b/cue/types.go
index 273fd24..c019e11 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -987,6 +987,7 @@
func makeInt(v Value, x int64) Value {
n := &numLit{numBase: numBase{baseValue: v.path.v.base()}}
n.v.SetInt64(x)
+ n.k = intKind
return remakeValue(v, n)
}
diff --git a/cue/types_test.go b/cue/types_test.go
index 7718475..c38ab79 100644
--- a/cue/types_test.go
+++ b/cue/types_test.go
@@ -1891,7 +1891,7 @@
}, {
// Issue #107
value: `a: 1.0/1`,
- json: `{"a":1}`,
+ json: `{"a":1.0}`,
}, {
// Issue #108
value: `
diff --git a/cue/value.go b/cue/value.go
index 3d1fbf8..59c0ef1 100644
--- a/cue/value.go
+++ b/cue/value.go
@@ -315,7 +315,7 @@
n := &numLit{
numBase: numBase{
baseValue: a.baseValue,
- numInfo: unifyNuminfo(a.numInfo, b.numInfo),
+ numInfo: numInfo{a.rep | b.rep, k},
},
}
return n
@@ -326,6 +326,17 @@
v apd.Decimal
}
+func (n *numLit) String() string {
+ if n.k&intKind != 0 {
+ return n.v.Text('f') // also render info
+ }
+ s := n.v.Text('g')
+ if len(s) == 1 {
+ s += "."
+ }
+ return s // also render info
+}
+
func parseInt(k kind, s string) *numLit {
n := &ast.BasicLit{
Kind: token.INT,