Skip to content

Commit

Permalink
internal/core/export: export floats as float literals
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Paul Jolly <[email protected]>
  • Loading branch information
mpvl committed Apr 11, 2021
1 parent f063a61 commit c8b7fe0
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 32 deletions.
2 changes: 1 addition & 1 deletion encoding/openapi/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ var cueToOpenAPI = map[string]string{

">=-2147483648 & <=2147483647 & int": "int32",
">=-9223372036854775808 & <=9223372036854775807 & int": "int64",
">=-340282346638528859811704183484516925440 & <=340282346638528859811704183484516925440": "float",
">=-340282346638528859811704183484516925440.0 & <=340282346638528859811704183484516925440.0": "float",
">=-1.797693134862315708145274237317043567981e+308 & <=1.797693134862315708145274237317043567981e+308": "double",
}

Expand Down
2 changes: 1 addition & 1 deletion internal/core/adt/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ func labelFromValue(c *OpContext, src Expr, v Value) Feature {
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 {
Expand Down
62 changes: 34 additions & 28 deletions internal/core/convert/go_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,51 +42,53 @@ func TestConvert(t *testing.T) {
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 }
Expand Down Expand Up @@ -123,9 +125,9 @@ func TestConvert(t *testing.T) {
}
}`,
}, {
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 }
Expand Down Expand Up @@ -177,9 +179,9 @@ func TestConvert(t *testing.T) {
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" }`,
}, {
Expand All @@ -203,7 +205,11 @@ func TestConvert(t *testing.T) {
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))
}
Expand Down
86 changes: 86 additions & 0 deletions internal/core/export/testdata/num.txtar
Original file line number Diff line number Diff line change
@@ -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
}
}
8 changes: 6 additions & 2 deletions internal/core/export/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package export

import (
"fmt"
"strings"

"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/ast/astutil"
Expand Down Expand Up @@ -245,8 +246,11 @@ func (e *exporter) num(n *adt.Num, orig []adt.Conjunct) *ast.BasicLit {
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 {
Expand Down

0 comments on commit c8b7fe0

Please sign in to comment.