diff --git a/ucl/ast.go b/ucl/ast.go index 54aaa64..3b567d9 100644 --- a/ucl/ast.go +++ b/ucl/ast.go @@ -148,7 +148,7 @@ var scanner = lexer.MustStateful(lexer.Rules{ {"NL", `[;\n][; \n\t]*`, nil}, {"PIPE", `\|`, nil}, {"EQ", `=`, nil}, - {"Ident", `[-!?]*[a-zA-Z_!?-][\w-!?]*`, nil}, + {"Ident", `[-]*[a-zA-Z_][\w-!?]*`, nil}, }, "String": { {"Escaped", `\\.`, nil}, diff --git a/ucl/builtins.go b/ucl/builtins.go index cc946b3..ddb065a 100644 --- a/ucl/builtins.go +++ b/ucl/builtins.go @@ -188,7 +188,7 @@ func eqBuiltin(ctx context.Context, args invocationArgs) (Object, error) { l := args.args[0] r := args.args[1] - return BoolObject(ObjectsEqual(l, r)), nil + return BoolObject(objectsEqual(l, r)), nil } func neBuiltin(ctx context.Context, args invocationArgs) (Object, error) { @@ -199,7 +199,7 @@ func neBuiltin(ctx context.Context, args invocationArgs) (Object, error) { l := args.args[0] r := args.args[1] - return BoolObject(!ObjectsEqual(l, r)), nil + return BoolObject(!objectsEqual(l, r)), nil } func ltBuiltin(ctx context.Context, args invocationArgs) (Object, error) { @@ -223,7 +223,7 @@ func leBuiltin(ctx context.Context, args invocationArgs) (Object, error) { if err != nil { return nil, err } - return BoolObject(isLess || ObjectsEqual(args.args[0], args.args[1])), nil + return BoolObject(isLess || objectsEqual(args.args[0], args.args[1])), nil } func gtBuiltin(ctx context.Context, args invocationArgs) (Object, error) { @@ -247,7 +247,7 @@ func geBuiltin(ctx context.Context, args invocationArgs) (Object, error) { if err != nil { return nil, err } - return BoolObject(isGreater || ObjectsEqual(args.args[0], args.args[1])), nil + return BoolObject(isGreater || objectsEqual(args.args[0], args.args[1])), nil } func andBuiltin(ctx context.Context, args invocationArgs) (Object, error) { @@ -286,7 +286,7 @@ func notBuiltin(ctx context.Context, args invocationArgs) (Object, error) { var errObjectsNotEqual = errors.New("objects not equal") -func ObjectsEqual(l, r Object) bool { +func objectsEqual(l, r Object) bool { if l == nil || r == nil { return l == nil && r == nil } @@ -314,7 +314,7 @@ func ObjectsEqual(l, r Object) bool { return false } for i := 0; i < lv.Len(); i++ { - if !ObjectsEqual(lv.Index(i), rv.Index(i)) { + if !objectsEqual(lv.Index(i), rv.Index(i)) { return false } } @@ -332,7 +332,7 @@ func ObjectsEqual(l, r Object) bool { rkv := rv.Value(k) if rkv == nil { return errObjectsNotEqual - } else if !ObjectsEqual(lkv, rkv) { + } else if !objectsEqual(lkv, rkv) { return errObjectsNotEqual } return nil @@ -370,18 +370,6 @@ func strBuiltin(ctx context.Context, args invocationArgs) (Object, error) { return StringObject(args.args[0].String()), nil } -func notNilBuiltin(ctx context.Context, args invocationArgs) (Object, error) { - if err := args.expectArgn(1); err != nil { - return nil, err - } - - if args.args[0] == nil { - return BoolObject(false), nil - } - - return BoolObject(true), nil -} - func intBuiltin(ctx context.Context, args invocationArgs) (Object, error) { if err := args.expectArgn(1); err != nil { return nil, err diff --git a/ucl/builtins/lists.go b/ucl/builtins/lists.go index 4e70095..f81f3e2 100644 --- a/ucl/builtins/lists.go +++ b/ucl/builtins/lists.go @@ -11,7 +11,6 @@ func Lists() ucl.Module { Name: "lists", Builtins: map[string]ucl.BuiltinHandler{ "first": listFirst, - "uniq": listUniq, }, } } @@ -59,69 +58,3 @@ func listFirst(ctx context.Context, args ucl.CallArgs) (any, error) { return newList, nil } - -func eachListOrIterItem(ctx context.Context, o ucl.Object, f func(int, ucl.Object) error) error { - switch t := o.(type) { - case ucl.Listable: - for i := 0; i < t.Len(); i++ { - if err := f(i, t.Index(i)); err != nil { - return err - } - } - return nil - case ucl.Iterable: - idx := 0 - for t.HasNext() { - v, err := t.Next(ctx) - if err != nil { - return err - } - if err := f(idx, v); err != nil { - return err - } - idx++ - } - } - return errors.New("expected listable") -} - -type uniqKey struct { - sVal string - iVal int -} - -func listUniq(ctx context.Context, args ucl.CallArgs) (any, error) { - var ( - what ucl.Object - ) - - if err := args.Bind(&what); err != nil { - return nil, err - } - - seen := make(map[uniqKey]bool) - found := ucl.NewListObject() - - if err := eachListOrIterItem(ctx, what, func(idx int, v ucl.Object) error { - var key uniqKey - switch v := v.(type) { - case ucl.StringObject: - key = uniqKey{sVal: string(v)} - case ucl.IntObject: - key = uniqKey{iVal: int(v)} - default: - return errors.New("expected string or int") - } - - if !seen[key] { - seen[key] = true - found.Append(v) - } - - return nil - }); err != nil { - return nil, err - } - - return found, nil -} diff --git a/ucl/builtins/lists_test.go b/ucl/builtins/lists_test.go index 72ccf65..526176e 100644 --- a/ucl/builtins/lists_test.go +++ b/ucl/builtins/lists_test.go @@ -45,37 +45,6 @@ func TestLists_First(t *testing.T) { } } -func TestLists_Uniq(t *testing.T) { - tests := []struct { - desc string - eval string - want any - wantErr bool - }{ - {desc: "uniq 1", eval: `lists:uniq [a a a a b b b c c c]`, want: []any{"a", "b", "c"}}, - {desc: "uniq 2", eval: `lists:uniq [1 2 1 3 2 4 2 5 3]`, want: []any{1, 2, 3, 4, 5}}, - {desc: "uniq 3", eval: `lists:uniq [1 a 2 b 3 b 2 a 1]5`, want: []any{1, "a", 2, "b", 3}}, - - {desc: "uniq err 1", eval: `lists:uniq [[1 2 3] [a:2] ()]`, wantErr: true}, - } - - for _, tt := range tests { - t.Run(tt.desc, func(t *testing.T) { - inst := ucl.New( - ucl.WithModule(builtins.Itrs()), - ucl.WithModule(builtins.Lists()), - ) - res, err := inst.EvalString(context.Background(), tt.eval) - if tt.wantErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - assert.Equal(t, tt.want, res) - } - }) - } -} - func uclListOf(args ...any) *ucl.ListObject { newList := ucl.NewListObject() for _, arg := range args { diff --git a/ucl/builtins/strs.go b/ucl/builtins/strs.go index 281dd4c..03801d0 100644 --- a/ucl/builtins/strs.go +++ b/ucl/builtins/strs.go @@ -103,7 +103,7 @@ func join(ctx context.Context, args ucl.CallArgs) (any, error) { if i > 0 { sb.WriteString(tok) } - sb.WriteString(ucl.ObjectToString(t.Index(i))) + sb.WriteString(t.Index(i).String()) } return sb.String(), nil case ucl.Iterable: @@ -120,7 +120,7 @@ func join(ctx context.Context, args ucl.CallArgs) (any, error) { } else { first = false } - sb.WriteString(ucl.ObjectToString(v)) + sb.WriteString(v.String()) } return sb.String(), nil diff --git a/ucl/builtins/strs_test.go b/ucl/builtins/strs_test.go index 6dc5436..c38065b 100644 --- a/ucl/builtins/strs_test.go +++ b/ucl/builtins/strs_test.go @@ -183,7 +183,6 @@ func TestStrs_Join(t *testing.T) { {desc: "join 3", eval: `strs:join [a b c] ""`, want: "abc"}, {desc: "join 4", eval: `strs:join [a b c]`, want: "abc"}, {desc: "join 5", eval: `strs:join (itrs:from [a b c]) ","`, want: "a,b,c"}, - {desc: "join 6", eval: `strs:join [a () c () e]`, want: "ace"}, } for _, tt := range tests { diff --git a/ucl/inst.go b/ucl/inst.go index de58436..074433e 100644 --- a/ucl/inst.go +++ b/ucl/inst.go @@ -81,8 +81,6 @@ func New(opts ...InstOption) *Inst { rootEC.addCmd("str", invokableFunc(strBuiltin)) rootEC.addCmd("int", invokableFunc(intBuiltin)) - rootEC.addCmd("!nil", invokableFunc(notNilBuiltin)) - rootEC.addCmd("add", invokableFunc(addBuiltin)) rootEC.addCmd("sub", invokableFunc(subBuiltin)) rootEC.addCmd("mup", invokableFunc(mupBuiltin)) diff --git a/ucl/inst_test.go b/ucl/inst_test.go index e2dbf60..7a9149a 100644 --- a/ucl/inst_test.go +++ b/ucl/inst_test.go @@ -21,7 +21,7 @@ func TestInst_Eval(t *testing.T) { {desc: "simple string", expr: `firstarg "hello"`, want: "hello"}, {desc: "simple int 1", expr: `firstarg 123`, want: 123}, {desc: "simple int 2", expr: `firstarg -234`, want: -234}, - {desc: "simple ident 1", expr: `firstarg a-test`, want: "a-test"}, + {desc: "simple ident", expr: `firstarg a-test`, want: "a-test"}, // String interpolation {desc: "interpolate string 1", expr: `$what = "world" ; firstarg "hello $what"`, want: "hello world"}, diff --git a/ucl/objs.go b/ucl/objs.go index 981f7ab..816bbaf 100644 --- a/ucl/objs.go +++ b/ucl/objs.go @@ -680,10 +680,3 @@ func isBreakErr(err error) bool { return errors.As(err, &errBreak{}) || errors.As(err, &errReturn{}) || errors.Is(err, ErrHalt) } - -func ObjectToString(obj Object) string { - if obj == nil { - return "" - } - return obj.String() -} diff --git a/ucl/builtins_test.go b/ucl/testbuiltins_test.go similarity index 97% rename from ucl/builtins_test.go rename to ucl/testbuiltins_test.go index 9361ae4..9ac1d61 100644 --- a/ucl/builtins_test.go +++ b/ucl/testbuiltins_test.go @@ -1749,44 +1749,6 @@ func TestBuiltins_Cat(t *testing.T) { } } -func TestBuiltins_NotNil(t *testing.T) { - tests := []struct { - desc string - expr string - want any - }{ - {desc: "not nil 1", expr: `!nil "hello"`, want: true}, - {desc: "not nil 2", expr: `!nil ""`, want: true}, - {desc: "not nil 3", expr: `!nil 4`, want: true}, - {desc: "not nil 4", expr: `!nil 0`, want: true}, - {desc: "not nil 5", expr: `!nil $true`, want: true}, - {desc: "not nil 6", expr: `!nil $false`, want: true}, - {desc: "not nil 7", expr: `!nil [1 2 3]`, want: true}, - {desc: "not nil 8", expr: `!nil []`, want: true}, - {desc: "not nil 9", expr: `!nil [a:1 b:21]`, want: true}, - {desc: "not nil 10", expr: `!nil [:]`, want: true}, - - {desc: "not nil 11", expr: `!nil ()`, want: false}, - - {desc: "not nil 12", expr: `[1 () 2 () 3] | filter !nil | reduce "" { |x a| "$a $x" }`, want: " 1 2 3"}, - } - - for _, tt := range tests { - t.Run(tt.desc, func(t *testing.T) { - ctx := context.Background() - outW := bytes.NewBuffer(nil) - - inst := New(WithOut(outW), WithTestBuiltin()) - inst.SetVar("true", true) - inst.SetVar("false", false) - - eqRes, err := inst.EvalString(ctx, tt.expr) - assert.NoError(t, err) - assert.Equal(t, tt.want, eqRes) - }) - } -} - func evalAndDisplay(ctx context.Context, inst *Inst, expr string) error { res, err := inst.eval(ctx, strings.NewReader(expr), evalOptions{}) if err != nil {