mirror of
https://github.com/google/go-jsonnet.git
synced 2025-09-29 09:21:03 +02:00
feat: support onEmpty optional parameter on std.minArray,std.maxArray
This commit is contained in:
parent
6a15a2f3fc
commit
9a89560b0d
51
builtins.go
51
builtins.go
@ -2280,6 +2280,7 @@ func builtinExtVar(i *interpreter, name value) (value, error) {
|
|||||||
func builtinMinArray(i *interpreter, arguments []value) (value, error) {
|
func builtinMinArray(i *interpreter, arguments []value) (value, error) {
|
||||||
arrv := arguments[0]
|
arrv := arguments[0]
|
||||||
keyFv := arguments[1]
|
keyFv := arguments[1]
|
||||||
|
onEmpty := arguments[2]
|
||||||
|
|
||||||
arr, err := i.getArray(arrv)
|
arr, err := i.getArray(arrv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -2291,7 +2292,11 @@ func builtinMinArray(i *interpreter, arguments []value) (value, error) {
|
|||||||
}
|
}
|
||||||
num := arr.length()
|
num := arr.length()
|
||||||
if num == 0 {
|
if num == 0 {
|
||||||
|
if onEmpty == nil {
|
||||||
return nil, i.Error("Expected at least one element in array. Got none")
|
return nil, i.Error("Expected at least one element in array. Got none")
|
||||||
|
} else {
|
||||||
|
return onEmpty, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
minVal, err := arr.elements[0].getValue(i)
|
minVal, err := arr.elements[0].getValue(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -2325,6 +2330,7 @@ func builtinMinArray(i *interpreter, arguments []value) (value, error) {
|
|||||||
func builtinMaxArray(i *interpreter, arguments []value) (value, error) {
|
func builtinMaxArray(i *interpreter, arguments []value) (value, error) {
|
||||||
arrv := arguments[0]
|
arrv := arguments[0]
|
||||||
keyFv := arguments[1]
|
keyFv := arguments[1]
|
||||||
|
onEmpty := arguments[2]
|
||||||
|
|
||||||
arr, err := i.getArray(arrv)
|
arr, err := i.getArray(arrv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -2336,7 +2342,11 @@ func builtinMaxArray(i *interpreter, arguments []value) (value, error) {
|
|||||||
}
|
}
|
||||||
num := arr.length()
|
num := arr.length()
|
||||||
if num == 0 {
|
if num == 0 {
|
||||||
|
if onEmpty == nil {
|
||||||
return nil, i.Error("Expected at least one element in array. Got none")
|
return nil, i.Error("Expected at least one element in array. Got none")
|
||||||
|
} else {
|
||||||
|
return onEmpty, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
maxVal, err := arr.elements[0].getValue(i)
|
maxVal, err := arr.elements[0].getValue(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -2533,7 +2543,7 @@ func flattenArgs(args callArguments, params []namedParameter, defaults []value)
|
|||||||
}
|
}
|
||||||
// Bind defaults for unsatisfied named parameters
|
// Bind defaults for unsatisfied named parameters
|
||||||
for i := range params {
|
for i := range params {
|
||||||
if flatArgs[i] == nil {
|
if flatArgs[i] == nil && defaults[i] != nil {
|
||||||
flatArgs[i] = readyThunk(defaults[i])
|
flatArgs[i] = readyThunk(defaults[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2551,10 +2561,14 @@ type unaryBuiltin struct {
|
|||||||
func (b *unaryBuiltin) evalCall(args callArguments, i *interpreter) (value, error) {
|
func (b *unaryBuiltin) evalCall(args callArguments, i *interpreter) (value, error) {
|
||||||
flatArgs := flattenArgs(args, b.parameters(), []value{})
|
flatArgs := flattenArgs(args, b.parameters(), []value{})
|
||||||
|
|
||||||
x, err := flatArgs[0].getValue(i)
|
var x value
|
||||||
|
var err error
|
||||||
|
if flatArgs[0] != nil {
|
||||||
|
x, err = flatArgs[0].getValue(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return b.function(i, x)
|
return b.function(i, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2581,14 +2595,20 @@ type binaryBuiltin struct {
|
|||||||
func (b *binaryBuiltin) evalCall(args callArguments, i *interpreter) (value, error) {
|
func (b *binaryBuiltin) evalCall(args callArguments, i *interpreter) (value, error) {
|
||||||
flatArgs := flattenArgs(args, b.parameters(), []value{})
|
flatArgs := flattenArgs(args, b.parameters(), []value{})
|
||||||
|
|
||||||
x, err := flatArgs[0].getValue(i)
|
var err error
|
||||||
|
var x, y value
|
||||||
|
if flatArgs[0] != nil {
|
||||||
|
x, err = flatArgs[0].getValue(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
y, err := flatArgs[1].getValue(i)
|
}
|
||||||
|
if flatArgs[1] != nil {
|
||||||
|
y, err = flatArgs[1].getValue(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return b.function(i, x, y)
|
return b.function(i, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2615,18 +2635,26 @@ type ternaryBuiltin struct {
|
|||||||
func (b *ternaryBuiltin) evalCall(args callArguments, i *interpreter) (value, error) {
|
func (b *ternaryBuiltin) evalCall(args callArguments, i *interpreter) (value, error) {
|
||||||
flatArgs := flattenArgs(args, b.parameters(), []value{})
|
flatArgs := flattenArgs(args, b.parameters(), []value{})
|
||||||
|
|
||||||
x, err := flatArgs[0].getValue(i)
|
var err error
|
||||||
|
var x, y, z value
|
||||||
|
if flatArgs[0] != nil {
|
||||||
|
x, err = flatArgs[0].getValue(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
y, err := flatArgs[1].getValue(i)
|
}
|
||||||
|
if flatArgs[1] != nil {
|
||||||
|
y, err = flatArgs[1].getValue(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
z, err := flatArgs[2].getValue(i)
|
}
|
||||||
|
if flatArgs[2] != nil {
|
||||||
|
z, err = flatArgs[2].getValue(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return b.function(i, x, y, z)
|
return b.function(i, x, y, z)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2649,6 +2677,7 @@ type generalBuiltinParameter struct {
|
|||||||
// This spares us unnecessary evaluation.
|
// This spares us unnecessary evaluation.
|
||||||
defaultValue value
|
defaultValue value
|
||||||
name ast.Identifier
|
name ast.Identifier
|
||||||
|
nonValueDefault bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// generalBuiltin covers cases that other builtin structures do not,
|
// generalBuiltin covers cases that other builtin structures do not,
|
||||||
@ -2665,7 +2694,7 @@ func (b *generalBuiltin) parameters() []namedParameter {
|
|||||||
ret := make([]namedParameter, len(b.params))
|
ret := make([]namedParameter, len(b.params))
|
||||||
for i := range ret {
|
for i := range ret {
|
||||||
ret[i].name = b.params[i].name
|
ret[i].name = b.params[i].name
|
||||||
if b.params[i].defaultValue != nil {
|
if b.params[i].defaultValue != nil || b.params[i].nonValueDefault {
|
||||||
// This is not actually used because the defaultValue is used instead.
|
// This is not actually used because the defaultValue is used instead.
|
||||||
// The only reason we don't leave it nil is because the checkArguments
|
// The only reason we don't leave it nil is because the checkArguments
|
||||||
// function uses the non-nil status to indicate that the parameter
|
// function uses the non-nil status to indicate that the parameter
|
||||||
@ -2693,11 +2722,13 @@ func (b *generalBuiltin) evalCall(args callArguments, i *interpreter) (value, er
|
|||||||
values := make([]value, len(flatArgs))
|
values := make([]value, len(flatArgs))
|
||||||
for j := 0; j < len(values); j++ {
|
for j := 0; j < len(values); j++ {
|
||||||
var err error
|
var err error
|
||||||
|
if flatArgs[j] != nil {
|
||||||
values[j], err = flatArgs[j].getValue(i)
|
values[j], err = flatArgs[j].getValue(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return b.function(i, values)
|
return b.function(i, values)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2840,8 +2871,8 @@ var funcBuiltins = buildBuiltinMap([]builtin{
|
|||||||
&unaryBuiltin{name: "encodeUTF8", function: builtinEncodeUTF8, params: ast.Identifiers{"str"}},
|
&unaryBuiltin{name: "encodeUTF8", function: builtinEncodeUTF8, params: ast.Identifiers{"str"}},
|
||||||
&unaryBuiltin{name: "decodeUTF8", function: builtinDecodeUTF8, params: ast.Identifiers{"arr"}},
|
&unaryBuiltin{name: "decodeUTF8", function: builtinDecodeUTF8, params: ast.Identifiers{"arr"}},
|
||||||
&generalBuiltin{name: "sort", function: builtinSort, params: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}}},
|
&generalBuiltin{name: "sort", function: builtinSort, params: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}}},
|
||||||
&generalBuiltin{name: "minArray", function: builtinMinArray, params: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}}},
|
&generalBuiltin{name: "minArray", function: builtinMinArray, params: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}, {name: "onEmpty", nonValueDefault: true}}},
|
||||||
&generalBuiltin{name: "maxArray", function: builtinMaxArray, params: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}}},
|
&generalBuiltin{name: "maxArray", function: builtinMaxArray, params: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}, {name: "onEmpty", nonValueDefault: true}}},
|
||||||
&unaryBuiltin{name: "native", function: builtinNative, params: ast.Identifiers{"x"}},
|
&unaryBuiltin{name: "native", function: builtinNative, params: ast.Identifiers{"x"}},
|
||||||
&unaryBuiltin{name: "sum", function: builtinSum, params: ast.Identifiers{"arr"}},
|
&unaryBuiltin{name: "sum", function: builtinSum, params: ast.Identifiers{"arr"}},
|
||||||
&unaryBuiltin{name: "avg", function: builtinAvg, params: ast.Identifiers{"arr"}},
|
&unaryBuiltin{name: "avg", function: builtinAvg, params: ast.Identifiers{"arr"}},
|
||||||
|
@ -150,8 +150,8 @@ func prepareStdlib(g *typeGraph) {
|
|||||||
"sort": g.newFuncType(anyArrayType, []ast.Parameter{required("arr"), optional("keyF")}),
|
"sort": g.newFuncType(anyArrayType, []ast.Parameter{required("arr"), optional("keyF")}),
|
||||||
"uniq": g.newFuncType(anyArrayType, []ast.Parameter{required("arr"), optional("keyF")}),
|
"uniq": g.newFuncType(anyArrayType, []ast.Parameter{required("arr"), optional("keyF")}),
|
||||||
"sum": g.newSimpleFuncType(numberType, "arr"),
|
"sum": g.newSimpleFuncType(numberType, "arr"),
|
||||||
"minArray": g.newFuncType(anyArrayType, []ast.Parameter{required("arr"), optional("keyF")}),
|
"minArray": g.newFuncType(anyArrayType, []ast.Parameter{required("arr"), optional("keyF"), optional("onEmpty")}),
|
||||||
"maxArray": g.newFuncType(anyArrayType, []ast.Parameter{required("arr"), optional("keyF")}),
|
"maxArray": g.newFuncType(anyArrayType, []ast.Parameter{required("arr"), optional("keyF"), optional("onEmpty")}),
|
||||||
"contains": g.newSimpleFuncType(boolType, "arr", "elem"),
|
"contains": g.newSimpleFuncType(boolType, "arr", "elem"),
|
||||||
"avg": g.newSimpleFuncType(numberType, "arr"),
|
"avg": g.newSimpleFuncType(numberType, "arr"),
|
||||||
"all": g.newSimpleFuncType(boolArrayType, "arr"),
|
"all": g.newSimpleFuncType(boolArrayType, "arr"),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user