Skip to content

Commit

Permalink
ext: add overloads for the individual comparable types
Browse files Browse the repository at this point in the history
  • Loading branch information
Cezar Guimaraes committed Sep 13, 2024
1 parent 5c148cd commit 2ff4703
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 8 deletions.
2 changes: 2 additions & 0 deletions ext/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -408,8 +408,10 @@ Examples:
### Sort

Sorts a list with comparable elements. If the element type is not comparable
or the element types are not the same, the function will produce an error.

<list(T)>.sort() -> <list(T)>
T in {int, uint, double, bool, duration, timestamp, string, bytes}

Examples:

Expand Down
35 changes: 29 additions & 6 deletions ext/lists.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ import (
// # Sort
//
// Sorts a list with comparable elements. If the element type is not comparable
// or the element types are not the same, the function will produce an error.
//
// <list(T)>.sort() -> <list(T)>
// T in {int, uint, double, bool, duration, timestamp, string, bytes}
//
// Examples:
//
Expand Down Expand Up @@ -108,6 +110,25 @@ func ListsVersion(version uint32) ListsOption {
}
}

var comparableTypes = []*cel.Type{
cel.IntType,
cel.UintType,
cel.DoubleType,
cel.BoolType,
cel.DurationType,
cel.TimestampType,
cel.StringType,
cel.BytesType,
}

func templatedOverloads(types []*cel.Type, template func(t *cel.Type) cel.FunctionOpt) []cel.FunctionOpt {
overloads := make([]cel.FunctionOpt, len(types))
for i, t := range types {
overloads[i] = template(t)
}
return overloads
}

// CompileOptions implements the Library interface method.
func (lib listsLib) CompileOptions() []cel.EnvOption {
listType := cel.ListType(cel.TypeParamType("T"))
Expand Down Expand Up @@ -175,10 +196,11 @@ func (lib listsLib) CompileOptions() []cel.EnvOption {
)
}
if lib.version >= 2 {
opts = append(opts,
cel.Function("sort",
cel.MemberOverload("list_sort",
[]*cel.Type{listType}, listType,
sortDecl := cel.Function("sort",
templatedOverloads(comparableTypes, func(t *cel.Type) cel.FunctionOpt {
return cel.MemberOverload(
fmt.Sprintf("list_%s_sort", t.TypeName()),
[]*cel.Type{cel.ListType(t)}, cel.ListType(t),
cel.UnaryBinding(func(arg ref.Val) ref.Val {
list, ok := arg.(traits.Lister)
if !ok {
Expand All @@ -191,9 +213,10 @@ func (lib listsLib) CompileOptions() []cel.EnvOption {

return sorted
}),
),
),
)
})...,
)
opts = append(opts, sortDecl)
}

return opts
Expand Down
2 changes: 0 additions & 2 deletions ext/lists_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ func TestLists(t *testing.T) {
{expr: `[4, 3, 2, 1].sort() == [1, 2, 3, 4]`},
{expr: `["d", "a", "b", "c"].sort() == ["a", "b", "c", "d"]`},
{expr: `["d", 3, 2, "c"].sort() == ["a", "b", "c", "d"]`, err: "list elements must have the same type"},
{expr: `[[1, 2, 3], [3, 2, 1]].sort()`, err: "list elements must be comparable"},
{expr: `[[1, 2, 3]].sort()`, err: "list elements must be comparable"},
}

env := testListsEnv(t)
Expand Down

0 comments on commit 2ff4703

Please sign in to comment.