internal/core/export: export floats as float literals
This avoids round-tripping problems when floats can
be represented as integers.
Fixes #896
The real solution is probably to make integer a direct
subclass of float. This, however, is a far more substantial
change. See #253.
Change-Id: I1fa532677a4ba2dcbe85446fcd7134f5bc3a542d
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9381
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/encoding/openapi/types.go b/encoding/openapi/types.go
index 7306660..50a962e 100644
--- a/encoding/openapi/types.go
+++ b/encoding/openapi/types.go
@@ -48,7 +48,7 @@
">=-2147483648 & <=2147483647 & int": "int32",
">=-9223372036854775808 & <=9223372036854775807 & int": "int64",
- ">=-340282346638528859811704183484516925440 & <=340282346638528859811704183484516925440": "float",
+ ">=-340282346638528859811704183484516925440.0 & <=340282346638528859811704183484516925440.0": "float",
">=-1.797693134862315708145274237317043567981e+308 & <=1.797693134862315708145274237317043567981e+308": "double",
}
diff --git a/internal/core/adt/feature.go b/internal/core/adt/feature.go
index d6f44b2..29585c5 100644
--- a/internal/core/adt/feature.go
+++ b/internal/core/adt/feature.go
@@ -196,7 +196,7 @@
if src == nil {
src = v
}
- c.AddErrf("invalid index %v: %v", src, err)
+ c.AddErrf("invalid index %v: %v", c.Str(src), err)
return InvalidLabel
}
if i < 0 {
diff --git a/internal/core/convert/go_test.go b/internal/core/convert/go_test.go
index 6b49f13..1a034c7 100644
--- a/internal/core/convert/go_test.go
+++ b/internal/core/convert/go_test.go
@@ -42,51 +42,53 @@
goVal interface{}
want string
}{{
- nil, "_",
+ nil, "(_){ _ }",
}, {
- true, "true",
+ true, "(bool){ true }",
}, {
- false, "false",
+ false, "(bool){ false }",
}, {
- errors.New("oh noes"), "_|_(oh noes)",
+ errors.New("oh noes"), "(_|_){\n // [eval] oh noes\n}",
}, {
- "foo", `"foo"`,
+ "foo", `(string){ "foo" }`,
}, {
- "\x80", `_|_(cannot convert result to string: invalid UTF-8)`,
+ "\x80", "(_|_){\n // [eval] cannot convert result to string: invalid UTF-8\n}",
}, {
- 3, "3",
+ 3, "(int){ 3 }",
}, {
- uint(3), "3",
+ uint(3), "(int){ 3 }",
}, {
- uint8(3), "3",
+ uint8(3), "(int){ 3 }",
}, {
- uint16(3), "3",
+ uint16(3), "(int){ 3 }",
}, {
- uint32(3), "3",
+ uint32(3), "(int){ 3 }",
}, {
- uint64(3), "3",
+ uint64(3), "(int){ 3 }",
}, {
- int8(-3), "-3",
+ int8(-3), "(int){ -3 }",
}, {
- int16(-3), "-3",
+ int16(-3), "(int){ -3 }",
}, {
- int32(-3), "-3",
+ int32(-3), "(int){ -3 }",
}, {
- int64(-3), "-3",
+ int64(-3), "(int){ -3 }",
}, {
- float64(3.1), "3.1",
+ float64(3), "(float){ 3 }",
}, {
- float32(3.1), "3.1",
+ float64(3.1), "(float){ 3.1 }",
}, {
- uintptr(3), "3",
+ float32(3.1), "(float){ 3.1 }",
}, {
- &i34, "34",
+ uintptr(3), "(int){ 3 }",
}, {
- &f37, "37",
+ &i34, "(int){ 34 }",
}, {
- &d35, "35",
+ &f37, "(float){ 37 }",
}, {
- &n36, "-36",
+ &d35, "(int){ 35 }",
+ }, {
+ &n36, "(int){ -36 }",
}, {
[]int{1, 2, 3, 4}, `(#list){
0: (int){ 1 }
@@ -123,9 +125,9 @@
}
}`,
}, {
- map[bool]int{}, "_|_(unsupported Go type for map key (bool))",
+ map[bool]int{}, "(_|_){\n // [eval] unsupported Go type for map key (bool)\n}",
}, {
- map[struct{}]int{{}: 2}, "_|_(unsupported Go type for map key (struct {}))",
+ map[struct{}]int{{}: 2}, "(_|_){\n // [eval] unsupported Go type for map key (struct {})\n}",
}, {
map[int]int{1: 2}, `(struct){
"1": (int){ 2 }
@@ -177,9 +179,9 @@
A: (int){ 3 }
}`,
}, {
- (*struct{ A int })(nil), "_",
+ (*struct{ A int })(nil), "(_){ _ }",
}, {
- reflect.ValueOf(3), "3",
+ reflect.ValueOf(3), "(int){ 3 }",
}, {
time.Date(2019, 4, 1, 0, 0, 0, 0, time.UTC), `(string){ "2019-04-01T00:00:00Z" }`,
}, {
@@ -203,7 +205,11 @@
ctx := adt.NewContext(r, &adt.Vertex{})
t.Run("", func(t *testing.T) {
v := convert.GoValueToValue(ctx, tc.goVal, true)
- got := debug.NodeString(ctx, v, nil)
+ n, ok := v.(*adt.Vertex)
+ if !ok {
+ n = &adt.Vertex{BaseValue: v}
+ }
+ got := debug.NodeString(ctx, n, nil)
if got != tc.want {
t.Error(cmp.Diff(got, tc.want))
}
diff --git a/internal/core/export/testdata/num.txtar b/internal/core/export/testdata/num.txtar
new file mode 100644
index 0000000..07ebd2d
--- /dev/null
+++ b/internal/core/export/testdata/num.txtar
@@ -0,0 +1,86 @@
+-- in.cue --
+import "strings"
+
+floats: {
+ a: 3.
+ b: float & 3.
+}
+numbers: {
+ a: number
+ a: 3
+ b: number
+ b: 3.
+}
+-- out/definition --
+floats: {
+ a: 3.0
+ b: 3.0
+}
+numbers: {
+ a: 3
+ b: 3.0
+}
+-- out/doc --
+[]
+[floats]
+[floats a]
+[floats b]
+[numbers]
+[numbers a]
+[numbers b]
+-- out/value --
+== Simplified
+{
+ floats: {
+ a: 3.0
+ b: 3.0
+ }
+ numbers: {
+ a: 3
+ b: 3.0
+ }
+}
+== Raw
+{
+ floats: {
+ a: 3.0
+ b: 3.0
+ }
+ numbers: {
+ a: 3
+ b: 3.0
+ }
+}
+== Final
+{
+ floats: {
+ a: 3.0
+ b: 3.0
+ }
+ numbers: {
+ a: 3
+ b: 3.0
+ }
+}
+== All
+{
+ floats: {
+ a: 3.0
+ b: 3.0
+ }
+ numbers: {
+ a: 3
+ b: 3.0
+ }
+}
+== Eval
+{
+ floats: {
+ a: 3.0
+ b: 3.0
+ }
+ numbers: {
+ a: 3
+ b: 3.0
+ }
+}
diff --git a/internal/core/export/value.go b/internal/core/export/value.go
index 720c3d7..1508581 100644
--- a/internal/core/export/value.go
+++ b/internal/core/export/value.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "strings"
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/ast/astutil"
@@ -245,8 +246,11 @@
if n.K&adt.IntKind != 0 {
kind = token.INT
}
- return &ast.BasicLit{Kind: kind, Value: n.X.String()}
-
+ s := n.X.String()
+ if kind == token.FLOAT && !strings.ContainsAny(s, "eE.") {
+ s += "."
+ }
+ return &ast.BasicLit{Kind: kind, Value: s}
}
func (e *exporter) string(n *adt.String, orig []adt.Conjunct) *ast.BasicLit {