Skip to content

Commit d6ddf08

Browse files
committed
Add keys() and values() builtins
1 parent 386ff5c commit d6ddf08

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

builtin/builtin.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,60 @@ var Functions = []*Function{
461461
return runtime.Fetch(args[0], args[1]), nil
462462
},
463463
},
464+
{
465+
Name: "keys",
466+
Func: func(args ...interface{}) (interface{}, error) {
467+
if len(args) != 1 {
468+
return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
469+
}
470+
v := reflect.ValueOf(args[0])
471+
if v.Kind() != reflect.Map {
472+
return nil, fmt.Errorf("cannot get keys from %s", v.Kind())
473+
}
474+
keys := v.MapKeys()
475+
out := make([]interface{}, len(keys))
476+
for i, key := range keys {
477+
out[i] = key.Interface()
478+
}
479+
return out, nil
480+
},
481+
Validate: func(args []reflect.Type) (reflect.Type, error) {
482+
if len(args) != 1 {
483+
return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
484+
}
485+
switch kind(args[0]) {
486+
case reflect.Map:
487+
return arrayType, nil
488+
}
489+
return anyType, fmt.Errorf("cannot get keys from %s", args[0])
490+
},
491+
},
492+
{
493+
Name: "values",
494+
Func: func(args ...interface{}) (interface{}, error) {
495+
if len(args) != 1 {
496+
return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
497+
}
498+
v := reflect.ValueOf(args[0])
499+
if v.Kind() != reflect.Map {
500+
return nil, fmt.Errorf("cannot get values from %s", v.Kind())
501+
}
502+
keys := v.MapKeys()
503+
out := make([]interface{}, len(keys))
504+
for i, key := range keys {
505+
out[i] = v.MapIndex(key).Interface()
506+
}
507+
return out, nil
508+
},
509+
Validate: func(args []reflect.Type) (reflect.Type, error) {
510+
if len(args) != 1 {
511+
return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
512+
}
513+
switch kind(args[0]) {
514+
case reflect.Map:
515+
return arrayType, nil
516+
}
517+
return anyType, fmt.Errorf("cannot get values from %s", args[0])
518+
},
519+
},
464520
}

builtin/builtin_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ func TestBuiltin(t *testing.T) {
8282
{`get(ArrayOfAny, 1)`, "2"},
8383
{`get({foo: 1, bar: 2}, "foo")`, 1},
8484
{`get({foo: 1, bar: 2}, "unknown")`, nil},
85+
{`"foo" in keys({foo: 1, bar: 2})`, true},
86+
{`1 in values({foo: 1, bar: 2})`, true},
8587
}
8688

8789
env := map[string]interface{}{

0 commit comments

Comments
 (0)