Made Hashable public and bindable
All checks were successful
Build / build (push) Successful in 2m34s
All checks were successful
Build / build (push) Successful in 2m34s
This commit is contained in:
parent
27b6cc0b92
commit
109be33d14
|
@ -354,8 +354,8 @@ func objectsEqual(l, r Object) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
case hashable:
|
case Hashable:
|
||||||
rv, ok := r.(hashable)
|
rv, ok := r.(Hashable)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -469,7 +469,7 @@ func lenBuiltin(ctx context.Context, args invocationArgs) (Object, error) {
|
||||||
return IntObject(len(string(v))), nil
|
return IntObject(len(string(v))), nil
|
||||||
case Listable:
|
case Listable:
|
||||||
return IntObject(v.Len()), nil
|
return IntObject(v.Len()), nil
|
||||||
case hashable:
|
case Hashable:
|
||||||
return IntObject(v.Len()), nil
|
return IntObject(v.Len()), nil
|
||||||
case Iterable:
|
case Iterable:
|
||||||
cnt := 0
|
cnt := 0
|
||||||
|
@ -497,10 +497,10 @@ func indexLookup(ctx context.Context, obj, elem Object) (Object, error) {
|
||||||
return v.Index(int(intIdx)), nil
|
return v.Index(int(intIdx)), nil
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
case hashable:
|
case Hashable:
|
||||||
strIdx, ok := elem.(StringObject)
|
strIdx, ok := elem.(StringObject)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("expected string for hashable")
|
return nil, errors.New("expected string for Hashable")
|
||||||
}
|
}
|
||||||
return v.Value(string(strIdx)), nil
|
return v.Value(string(strIdx)), nil
|
||||||
}
|
}
|
||||||
|
@ -531,7 +531,7 @@ func keysBuiltin(ctx context.Context, args invocationArgs) (Object, error) {
|
||||||
|
|
||||||
val := args.args[0]
|
val := args.args[0]
|
||||||
switch v := val.(type) {
|
switch v := val.(type) {
|
||||||
case hashable:
|
case Hashable:
|
||||||
keys := make(ListObject, 0, v.Len())
|
keys := make(ListObject, 0, v.Len())
|
||||||
if err := v.Each(func(k string, _ Object) error {
|
if err := v.Each(func(k string, _ Object) error {
|
||||||
keys = append(keys, StringObject(k))
|
keys = append(keys, StringObject(k))
|
||||||
|
@ -676,7 +676,7 @@ func filterBuiltin(ctx context.Context, args invocationArgs) (Object, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &newList, nil
|
return &newList, nil
|
||||||
case hashable:
|
case Hashable:
|
||||||
newHash := hashObject{}
|
newHash := hashObject{}
|
||||||
if err := t.Each(func(k string, v Object) error {
|
if err := t.Each(func(k string, v Object) error {
|
||||||
if m, err := inv.invoke(ctx, args.fork([]Object{StringObject(k), v})); err != nil {
|
if m, err := inv.invoke(ctx, args.fork([]Object{StringObject(k), v})); err != nil {
|
||||||
|
@ -741,7 +741,7 @@ func reduceBuiltin(ctx context.Context, args invocationArgs) (Object, error) {
|
||||||
accum = newAccum
|
accum = newAccum
|
||||||
}
|
}
|
||||||
return accum, nil
|
return accum, nil
|
||||||
case hashable:
|
case Hashable:
|
||||||
// TODO: should raise error?
|
// TODO: should raise error?
|
||||||
if err := t.Each(func(k string, v Object) error {
|
if err := t.Each(func(k string, v Object) error {
|
||||||
newAccum, err := block.invoke(ctx, args.fork([]Object{StringObject(k), v, accum}))
|
newAccum, err := block.invoke(ctx, args.fork([]Object{StringObject(k), v, accum}))
|
||||||
|
@ -942,7 +942,7 @@ func foreachBuiltin(ctx context.Context, args macroArgs) (Object, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case hashable:
|
case Hashable:
|
||||||
err := t.Each(func(k string, v Object) error {
|
err := t.Each(func(k string, v Object) error {
|
||||||
last, err = args.evalBlock(ctx, blockIdx, []Object{StringObject(k), v}, false)
|
last, err = args.evalBlock(ctx, blockIdx, []Object{StringObject(k), v}, false)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -40,7 +40,7 @@ type ModListable interface {
|
||||||
Insert(idx int, obj Object) error
|
Insert(idx int, obj Object) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type hashable interface {
|
type Hashable interface {
|
||||||
Len() int
|
Len() int
|
||||||
Value(k string) Object
|
Value(k string) Object
|
||||||
Each(func(k string, v Object) error) error
|
Each(func(k string, v Object) error) error
|
||||||
|
|
|
@ -127,6 +127,13 @@ func (ca CallArgs) bindArg(v interface{}, arg Object) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.New("exepected listable")
|
return errors.New("exepected listable")
|
||||||
|
case *Hashable:
|
||||||
|
i, ok := arg.(Hashable)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("exepected hashable")
|
||||||
|
}
|
||||||
|
*t = i
|
||||||
|
return nil
|
||||||
case *Iterable:
|
case *Iterable:
|
||||||
if i, ok := arg.(Iterable); ok {
|
if i, ok := arg.(Iterable); ok {
|
||||||
*t = i
|
*t = i
|
||||||
|
|
|
@ -301,6 +301,49 @@ func TestCallArgs_CanBind(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Run("can bind Hashable", func(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
descr string
|
||||||
|
eval string
|
||||||
|
want any
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{descr: "return key 1", eval: `keyval [a:"hello" b:"world"] "a"`, want: "hello"},
|
||||||
|
{descr: "return key 2", eval: `keyval [a:"hello" b:"world"] "b"`, want: "world"},
|
||||||
|
{descr: "return key 3", eval: `keyval (keyval [a:"hello" b:[c:"fla"]] "b") c`, want: "fla"},
|
||||||
|
|
||||||
|
{descr: "err 1", eval: `keyval not-a-hashable "b"`, wantErr: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.descr, func(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
inst := ucl.New()
|
||||||
|
inst.SetBuiltin("keyval", func(ctx context.Context, args ucl.CallArgs) (any, error) {
|
||||||
|
var (
|
||||||
|
h ucl.Hashable
|
||||||
|
k string
|
||||||
|
)
|
||||||
|
if err := args.Bind(&h, &k); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.Value(k), nil
|
||||||
|
})
|
||||||
|
|
||||||
|
res, err := inst.Eval(ctx, tt.eval)
|
||||||
|
if tt.wantErr {
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Nil(t, res)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.want, res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("can bind invokable", func(t *testing.T) {
|
t.Run("can bind invokable", func(t *testing.T) {
|
||||||
inst := ucl.New()
|
inst := ucl.New()
|
||||||
inst.SetBuiltin("toUpper", func(ctx context.Context, args ucl.CallArgs) (any, error) {
|
inst.SetBuiltin("toUpper", func(ctx context.Context, args ucl.CallArgs) (any, error) {
|
||||||
|
|
Loading…
Reference in a new issue