diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..1bcb7740 Binary files /dev/null and b/.DS_Store differ diff --git a/builtins.go b/builtins.go index 47c918c0..add084d4 100644 --- a/builtins.go +++ b/builtins.go @@ -1907,6 +1907,42 @@ func builtinExtVar(i *interpreter, name value) (value, error) { return nil, i.Error("Undefined external variable: " + string(index)) } +func builtinMinArray(i *interpreter, arguments []value) (value, error) { + arrv := arguments[0] + keyFv := arguments[1] + + arr, err := i.getArray(arrv) + if err != nil { + return nil, err + } + keyF, err := i.getFunction(keyFv) + if err != nil { + return nil, err + } + num := arr.length() + if num == 0 { + return nil, i.Error("Expected at least one element in array. Got none") + } + minVal, err := keyF.call(i, args(arr.elements[0])) + if err != nil { + return nil, err + } + for index := 1; index < num; index++ { + current, err := keyF.call(i, args(arr.elements[index])) + if err != nil { + return nil, err + } + cmp, err := valueCmp(i, minVal, current) + if err != nil { + return nil, err + } + if cmp > 0 { + minVal = current + } + } + return minVal, nil +} + func builtinNative(i *interpreter, name value) (value, error) { str, err := i.getString(name) if err != nil { @@ -2264,6 +2300,7 @@ var funcBuiltins = buildBuiltinMap([]builtin{ &unaryBuiltin{name: "encodeUTF8", function: builtinEncodeUTF8, params: ast.Identifiers{"str"}}, &unaryBuiltin{name: "decodeUTF8", function: builtinDecodeUTF8, params: ast.Identifiers{"arr"}}, &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}}}, &unaryBuiltin{name: "native", function: builtinNative, params: ast.Identifiers{"x"}}, &unaryBuiltin{name: "sum", function: builtinSum, params: ast.Identifiers{"arr"}}, &binaryBuiltin{name: "contains", function: builtinContains, params: ast.Identifiers{"arr", "elem"}}, diff --git a/linter/internal/types/stdlib.go b/linter/internal/types/stdlib.go index 264b1ec8..dee12b27 100644 --- a/linter/internal/types/stdlib.go +++ b/linter/internal/types/stdlib.go @@ -140,6 +140,7 @@ func prepareStdlib(g *typeGraph) { "sort": g.newFuncType(anyArrayType, []ast.Parameter{required("arr"), optional("keyF")}), "uniq": g.newFuncType(anyArrayType, []ast.Parameter{required("arr"), optional("keyF")}), "sum": g.newSimpleFuncType(numberType, "arr"), + "minArray": g.newSimpleFuncType(anyType, "arr"), "contains": g.newSimpleFuncType(boolType, "arr", "elem"), // Sets diff --git a/testdata/builtinMinArray.golden b/testdata/builtinMinArray.golden new file mode 100644 index 00000000..3a2e3f49 --- /dev/null +++ b/testdata/builtinMinArray.golden @@ -0,0 +1 @@ +-1 diff --git a/testdata/builtinMinArray.jsonnet b/testdata/builtinMinArray.jsonnet new file mode 100644 index 00000000..202b8d62 --- /dev/null +++ b/testdata/builtinMinArray.jsonnet @@ -0,0 +1 @@ +std.minArray([1,-1,0]) \ No newline at end of file diff --git a/testdata/builtinMinArray.linter.golden b/testdata/builtinMinArray.linter.golden new file mode 100644 index 00000000..e69de29b