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 {
|
||||
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) {
|
||||
case *valueNumber:
|
||||
right, err := e.evaluateNumber(yp)
|
||||
right, err := e.getNumber(y)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return makeValueNumber(left.value + right.value), nil
|
||||
case *valueString:
|
||||
right, err := e.evaluateString(yp)
|
||||
right, err := builtinToString(e, yp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return concatStrings(left, right), nil
|
||||
return concatStrings(left, right.(*valueString)), nil
|
||||
case valueObject:
|
||||
right, err := e.evaluateObject(yp)
|
||||
right, err := e.getObject(y)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return makeValueExtendedObject(left, right), nil
|
||||
case *valueArray:
|
||||
right, err := e.getArray(y)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return concatArrays(left, right), nil
|
||||
default:
|
||||
return nil, e.typeErrorGeneral(x)
|
||||
}
|
||||
@ -215,6 +234,10 @@ func builtinToString(e *evaluator, xp potentialValue) (value, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch x := x.(type) {
|
||||
case *valueString:
|
||||
return x, nil
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
err = e.i.manifestJSON(e.trace, x, false, "", &buf)
|
||||
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 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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hidden, err := e.evaluateBoolean(hiddenp)
|
||||
includeHidden, err := e.evaluateBoolean(includeHiddenP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fields := objectFields(obj, hidden.value)
|
||||
fields := objectFields(obj, !includeHidden.value)
|
||||
sort.Strings(fields)
|
||||
elems := []potentialValue{}
|
||||
for _, fieldname := range fields {
|
||||
@ -423,7 +446,7 @@ func builtinObjectFieldsEx(e *evaluator, objp potentialValue, hiddenp potentialV
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -432,11 +455,11 @@ func builtinObjectHasEx(e *evaluator, objp potentialValue, fnamep potentialValue
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hidden, err := e.evaluateBoolean(hiddenp)
|
||||
includeHidden, err := e.evaluateBoolean(includeHiddenP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, fieldname := range objectFields(obj, hidden.value) {
|
||||
for _, fieldname := range objectFields(obj, !includeHidden.value) {
|
||||
if fieldname == string(fname.value) {
|
||||
return makeValueBoolean(true), nil
|
||||
}
|
||||
|
@ -427,7 +427,7 @@ func desugar(astPtr *ast.Node, objLevel int) (err error) {
|
||||
if node.Step == nil {
|
||||
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)
|
||||
|
||||
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",
|
||||
"y",
|
||||
"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 {
|
||||
return "array"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user