mirror of
https://github.com/google/go-jsonnet.git
synced 2025-09-28 17:01:02 +02:00
Even more builtins
Fix a bunch of bugs: - Reverse meaning of boolean argument to objectFieldsEx and objectHasEx - Slice desugaring using `std.slice` instead of `slice` as a field name. Support + on string and something else. Support + on arrays assertEqual should now work properly
This commit is contained in:
parent
6b040a9afe
commit
1e4797071f
43
builtins.go
43
builtins.go
@ -38,25 +38,44 @@ func builtinPlus(e *evaluator, xp, yp potentialValue) (value, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
y, err := e.evaluate(yp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
switch right := y.(type) {
|
||||||
|
case *valueString:
|
||||||
|
left, err := builtinToString(e, xp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return concatStrings(left.(*valueString), right), nil
|
||||||
|
|
||||||
|
}
|
||||||
switch left := x.(type) {
|
switch left := x.(type) {
|
||||||
case *valueNumber:
|
case *valueNumber:
|
||||||
right, err := e.evaluateNumber(yp)
|
right, err := e.getNumber(y)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return makeValueNumber(left.value + right.value), nil
|
return makeValueNumber(left.value + right.value), nil
|
||||||
case *valueString:
|
case *valueString:
|
||||||
right, err := e.evaluateString(yp)
|
right, err := builtinToString(e, yp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return concatStrings(left, right), nil
|
return concatStrings(left, right.(*valueString)), nil
|
||||||
case valueObject:
|
case valueObject:
|
||||||
right, err := e.evaluateObject(yp)
|
right, err := e.getObject(y)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return makeValueExtendedObject(left, right), nil
|
return makeValueExtendedObject(left, right), nil
|
||||||
|
case *valueArray:
|
||||||
|
right, err := e.getArray(y)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return concatArrays(left, right), nil
|
||||||
default:
|
default:
|
||||||
return nil, e.typeErrorGeneral(x)
|
return nil, e.typeErrorGeneral(x)
|
||||||
}
|
}
|
||||||
@ -215,6 +234,10 @@ func builtinToString(e *evaluator, xp potentialValue) (value, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
switch x := x.(type) {
|
||||||
|
case *valueString:
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
err = e.i.manifestJSON(e.trace, x, false, "", &buf)
|
err = e.i.manifestJSON(e.trace, x, false, "", &buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -405,16 +428,16 @@ var builtinBitwiseAnd = liftBitwise(func(x, y int64) int64 { return x & y })
|
|||||||
var builtinBitwiseOr = liftBitwise(func(x, y int64) int64 { return x | y })
|
var builtinBitwiseOr = liftBitwise(func(x, y int64) int64 { return x | y })
|
||||||
var builtinBitwiseXor = liftBitwise(func(x, y int64) int64 { return x ^ y })
|
var builtinBitwiseXor = liftBitwise(func(x, y int64) int64 { return x ^ y })
|
||||||
|
|
||||||
func builtinObjectFieldsEx(e *evaluator, objp potentialValue, hiddenp potentialValue) (value, error) {
|
func builtinObjectFieldsEx(e *evaluator, objp potentialValue, includeHiddenP potentialValue) (value, error) {
|
||||||
obj, err := e.evaluateObject(objp)
|
obj, err := e.evaluateObject(objp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hidden, err := e.evaluateBoolean(hiddenp)
|
includeHidden, err := e.evaluateBoolean(includeHiddenP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fields := objectFields(obj, hidden.value)
|
fields := objectFields(obj, !includeHidden.value)
|
||||||
sort.Strings(fields)
|
sort.Strings(fields)
|
||||||
elems := []potentialValue{}
|
elems := []potentialValue{}
|
||||||
for _, fieldname := range fields {
|
for _, fieldname := range fields {
|
||||||
@ -423,7 +446,7 @@ func builtinObjectFieldsEx(e *evaluator, objp potentialValue, hiddenp potentialV
|
|||||||
return makeValueArray(elems), nil
|
return makeValueArray(elems), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinObjectHasEx(e *evaluator, objp potentialValue, fnamep potentialValue, hiddenp potentialValue) (value, error) {
|
func builtinObjectHasEx(e *evaluator, objp potentialValue, fnamep potentialValue, includeHiddenP potentialValue) (value, error) {
|
||||||
obj, err := e.evaluateObject(objp)
|
obj, err := e.evaluateObject(objp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -432,11 +455,11 @@ func builtinObjectHasEx(e *evaluator, objp potentialValue, fnamep potentialValue
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hidden, err := e.evaluateBoolean(hiddenp)
|
includeHidden, err := e.evaluateBoolean(includeHiddenP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, fieldname := range objectFields(obj, hidden.value) {
|
for _, fieldname := range objectFields(obj, !includeHidden.value) {
|
||||||
if fieldname == string(fname.value) {
|
if fieldname == string(fname.value) {
|
||||||
return makeValueBoolean(true), nil
|
return makeValueBoolean(true), nil
|
||||||
}
|
}
|
||||||
|
@ -427,7 +427,7 @@ func desugar(astPtr *ast.Node, objLevel int) (err error) {
|
|||||||
if node.Step == nil {
|
if node.Step == nil {
|
||||||
node.Step = &ast.LiteralNull{}
|
node.Step = &ast.LiteralNull{}
|
||||||
}
|
}
|
||||||
*astPtr = buildStdCall("std.slice", node.Target, node.BeginIndex, node.EndIndex, node.Step)
|
*astPtr = buildStdCall("slice", node.Target, node.BeginIndex, node.EndIndex, node.Step)
|
||||||
desugar(astPtr, objLevel)
|
desugar(astPtr, objLevel)
|
||||||
|
|
||||||
case *ast.Local:
|
case *ast.Local:
|
||||||
|
1
testdata/assert_equal.golden
vendored
Normal file
1
testdata/assert_equal.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
true
|
1
testdata/assert_equal.input
vendored
Normal file
1
testdata/assert_equal.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.assertEqual([], [])
|
1
testdata/assert_equal2.golden
vendored
Normal file
1
testdata/assert_equal2.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
true
|
1
testdata/assert_equal2.input
vendored
Normal file
1
testdata/assert_equal2.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.assertEqual({}, {})
|
1
testdata/assert_equal3.golden
vendored
Normal file
1
testdata/assert_equal3.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
true
|
1
testdata/assert_equal3.input
vendored
Normal file
1
testdata/assert_equal3.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.assertEqual({x:: 42}, {})
|
1
testdata/assert_equal4.golden
vendored
Normal file
1
testdata/assert_equal4.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: Assertion failed. {"x": 1} != {"x": 2}
|
1
testdata/assert_equal4.input
vendored
Normal file
1
testdata/assert_equal4.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.assertEqual({x: 1}, {x: 2})
|
1
testdata/builtinObjectFieldsEx.golden
vendored
1
testdata/builtinObjectFieldsEx.golden
vendored
@ -1,5 +1,4 @@
|
|||||||
[
|
[
|
||||||
"x",
|
"x",
|
||||||
"y",
|
|
||||||
"z"
|
"z"
|
||||||
]
|
]
|
||||||
|
5
testdata/builtinObjectFieldsExWithHidden.golden
vendored
Normal file
5
testdata/builtinObjectFieldsExWithHidden.golden
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[
|
||||||
|
"x",
|
||||||
|
"y",
|
||||||
|
"z"
|
||||||
|
]
|
1
testdata/builtinObjectFieldsExWithHidden.input
vendored
Normal file
1
testdata/builtinObjectFieldsExWithHidden.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.objectFieldsEx({x: 1, y:: 1, z::: 2}, true)
|
1
testdata/plus.golden
vendored
Normal file
1
testdata/plus.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
3
|
1
testdata/plus.input
vendored
Normal file
1
testdata/plus.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
1 + 2
|
1
testdata/plus2.golden
vendored
Normal file
1
testdata/plus2.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"ab"
|
1
testdata/plus2.input
vendored
Normal file
1
testdata/plus2.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"a" + "b"
|
8
testdata/plus3.golden
vendored
Normal file
8
testdata/plus3.golden
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6
|
||||||
|
]
|
1
testdata/plus3.input
vendored
Normal file
1
testdata/plus3.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[1, 2, 3] + [4, 5, 6]
|
5
testdata/plus4.golden
vendored
Normal file
5
testdata/plus4.golden
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"a": 3,
|
||||||
|
"b": 2,
|
||||||
|
"c": 4
|
||||||
|
}
|
1
testdata/plus4.input
vendored
Normal file
1
testdata/plus4.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"a": 1, "b": 2} + {"a": 3, "c": 4}
|
1
testdata/plus5.golden
vendored
Normal file
1
testdata/plus5.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: Unexpected type function, expected number
|
1
testdata/plus5.input
vendored
Normal file
1
testdata/plus5.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
42 + function() 42
|
1
testdata/plus6.golden
vendored
Normal file
1
testdata/plus6.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"a42"
|
1
testdata/plus6.input
vendored
Normal file
1
testdata/plus6.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"a" + 42
|
1
testdata/plus7.golden
vendored
Normal file
1
testdata/plus7.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"42a"
|
1
testdata/plus7.input
vendored
Normal file
1
testdata/plus7.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
42 + "a"
|
1
testdata/plus8.golden
vendored
Normal file
1
testdata/plus8.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"{\"x\": 42}a"
|
1
testdata/plus8.input
vendored
Normal file
1
testdata/plus8.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"x": 42} + "a"
|
1
testdata/plus9.golden
vendored
Normal file
1
testdata/plus9.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"a[1, 2, 3]"
|
1
testdata/plus9.input
vendored
Normal file
1
testdata/plus9.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"a" + [1, 2, 3]
|
4
testdata/slice.golden
vendored
Normal file
4
testdata/slice.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
2,
|
||||||
|
4
|
||||||
|
]
|
1
testdata/slice.input
vendored
Normal file
1
testdata/slice.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[1,2,3,4][1:4:2]
|
3
testdata/slice2.golden
vendored
Normal file
3
testdata/slice2.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[
|
||||||
|
2
|
||||||
|
]
|
1
testdata/slice2.input
vendored
Normal file
1
testdata/slice2.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[1,2,3,4][1:3:2]
|
3
testdata/slice3.golden
vendored
Normal file
3
testdata/slice3.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[
|
||||||
|
2
|
||||||
|
]
|
1
testdata/slice3.input
vendored
Normal file
1
testdata/slice3.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[1,2,3,4][1:2]
|
5
testdata/slice4.golden
vendored
Normal file
5
testdata/slice4.golden
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
]
|
1
testdata/slice4.input
vendored
Normal file
1
testdata/slice4.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[1,2,3,4][:3:]
|
5
testdata/slice5.golden
vendored
Normal file
5
testdata/slice5.golden
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4
|
||||||
|
]
|
1
testdata/slice5.input
vendored
Normal file
1
testdata/slice5.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[1,2,3,4][1:]
|
5
testdata/slice6.golden
vendored
Normal file
5
testdata/slice6.golden
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4
|
||||||
|
]
|
1
testdata/slice6.input
vendored
Normal file
1
testdata/slice6.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[1,2,3,4][1::]
|
4
testdata/slice7.golden
vendored
Normal file
4
testdata/slice7.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
1,
|
||||||
|
3
|
||||||
|
]
|
1
testdata/slice7.input
vendored
Normal file
1
testdata/slice7.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[1,2,3,4][::2]
|
4
testdata/std.objectFields.golden
vendored
Normal file
4
testdata/std.objectFields.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
"x",
|
||||||
|
"z"
|
||||||
|
]
|
1
testdata/std.objectFields.input
vendored
Normal file
1
testdata/std.objectFields.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.objectFields({x: 1, y:: 2, z::: 3})
|
1
testdata/std.objectHasEx.golden
vendored
Normal file
1
testdata/std.objectHasEx.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
true
|
1
testdata/std.objectHasEx.input
vendored
Normal file
1
testdata/std.objectHasEx.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.objectHasEx({"x": null}, "x", false)
|
1
testdata/std.objectHasEx2.golden
vendored
Normal file
1
testdata/std.objectHasEx2.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
false
|
1
testdata/std.objectHasEx2.input
vendored
Normal file
1
testdata/std.objectHasEx2.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.objectHasEx({"x":: null}, "x", false)
|
1
testdata/std.objectHasEx3.golden
vendored
Normal file
1
testdata/std.objectHasEx3.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
true
|
1
testdata/std.objectHasEx3.input
vendored
Normal file
1
testdata/std.objectHasEx3.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.objectHasEx({"x": null}, "x", true)
|
1
testdata/std.objectHasEx4.golden
vendored
Normal file
1
testdata/std.objectHasEx4.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
true
|
1
testdata/std.objectHasEx4.input
vendored
Normal file
1
testdata/std.objectHasEx4.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.objectHasEx({"x":: null}, "x", true)
|
4
testdata/std.slice.golden
vendored
Normal file
4
testdata/std.slice.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
2,
|
||||||
|
4
|
||||||
|
]
|
1
testdata/std.slice.input
vendored
Normal file
1
testdata/std.slice.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.slice([1,2,3,4], 1, 4, 2)
|
2
testdata/std.toString.golden
vendored
2
testdata/std.toString.golden
vendored
@ -1 +1 @@
|
|||||||
"\"xxx\""
|
"xxx"
|
||||||
|
11
value.go
11
value.go
@ -206,6 +206,17 @@ func makeValueArray(elements []potentialValue) *valueArray {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func concatArrays(a, b *valueArray) *valueArray {
|
||||||
|
result := make([]potentialValue, 0, len(a.elements)+len(b.elements))
|
||||||
|
for _, r := range a.elements {
|
||||||
|
result = append(result, r)
|
||||||
|
}
|
||||||
|
for _, r := range b.elements {
|
||||||
|
result = append(result, r)
|
||||||
|
}
|
||||||
|
return &valueArray{elements: result}
|
||||||
|
}
|
||||||
|
|
||||||
func (*valueArray) typename() string {
|
func (*valueArray) typename() string {
|
||||||
return "array"
|
return "array"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user