@@ -9,7 +9,7 @@ extension BuiltinFuncs {
99
1010 guard let len = args [ 0 ] . count else {
1111 throw BuiltinError . argumentTypeMismatch (
12- arg: " collection " , got: args [ 0 ] . typeName, want: " string| array| object| set" )
12+ arg: " collection " , got: args [ 0 ] . typeName, want: " any< array, object, set, string> " )
1313 }
1414
1515 return . number( NSNumber ( value: len) )
@@ -27,7 +27,7 @@ extension BuiltinFuncs {
2727 return s. max ( ) ?? . undefined
2828 default :
2929 throw BuiltinError . argumentTypeMismatch (
30- arg: " collection " , got: args [ 0 ] . typeName, want: " array| set " )
30+ arg: " collection " , got: args [ 0 ] . typeName, want: " any< array[any], set[any]> " )
3131 }
3232 }
3333
@@ -43,7 +43,74 @@ extension BuiltinFuncs {
4343 return s. min ( ) ?? . undefined
4444 default :
4545 throw BuiltinError . argumentTypeMismatch (
46- arg: " collection " , got: args [ 0 ] . typeName, want: " array|set " )
46+ arg: " collection " , got: args [ 0 ] . typeName, want: " any<array[any], set[any]> " )
47+ }
48+ }
49+
50+ static func sort( ctx: BuiltinContext , args: [ AST . RegoValue ] ) async throws -> AST . RegoValue {
51+ guard args. count == 1 else {
52+ throw BuiltinError . argumentCountMismatch ( got: args. count, want: 1 )
53+ }
54+
55+ switch args [ 0 ] {
56+ case . array( let a) :
57+ return . array( a. sorted ( ) )
58+ case . set( let s) :
59+ return . array( s. sorted ( ) )
60+ default :
61+ throw BuiltinError . argumentTypeMismatch (
62+ arg: " collection " , got: args [ 0 ] . typeName, want: " any<array[any], set[any]> " )
63+ }
64+ }
65+
66+ static func sum( ctx: BuiltinContext , args: [ AST . RegoValue ] ) async throws -> AST . RegoValue {
67+ return try doReduce ( args: args, initialValue: . number( 0 ) , op: BuiltinFuncs . doPlus)
68+ }
69+
70+ static func product( ctx: BuiltinContext , args: [ AST . RegoValue ] ) async throws -> AST . RegoValue {
71+ return try doReduce ( args: args, initialValue: . number( 1 ) , op: BuiltinFuncs . doMul)
72+ }
73+
74+ /// Returns reduction over an array or set of RegoValues with a given async Builtin being used as an reducer operation.
75+ /// Returns the normalized metric unit symbol for a given symbol.
76+ /// - Parameters:
77+ /// - ctx: The builtin context.
78+ /// - args: The arguments to reduce.
79+ /// - initialValue: The initial value to start with.
80+ /// - op: The Arithmetic builtin operation to be applied to the partial result an the next value in the sequence to produce the next result.
81+ private static func doReduce(
82+ args: [ AST . RegoValue ] ,
83+ initialValue: AST . RegoValue ,
84+ op: ( [ AST . RegoValue ] ) throws -> AST . RegoValue
85+ ) throws -> AST . RegoValue {
86+ guard args. count == 1 else {
87+ throw BuiltinError . argumentCountMismatch ( got: args. count, want: 1 )
88+ }
89+
90+ // We will iterate over this sequence
91+ var sequence : any Sequence < RegoValue >
92+ switch args [ 0 ] {
93+ case . array( let a) :
94+ sequence = a
95+ case . set( let s) :
96+ sequence = s
97+ default :
98+ throw BuiltinError . argumentTypeMismatch (
99+ arg: " collection " , got: args [ 0 ] . typeName, want: " any<array[number], set[number]> " )
100+ }
101+
102+ do {
103+ let result = try sequence. reduce (
104+ initialValue,
105+ { x, y in
106+ try op ( [ x, y] )
107+ } )
108+ return result
109+ } catch is RegoError {
110+ let receivedTypes = Set ( sequence. map ( { $0. typeName } ) ) . sorted ( ) . joined ( separator: " , " )
111+ throw BuiltinError . argumentTypeMismatch (
112+ arg: " collection " , got: " \( args [ 0 ] . typeName) [any< \( receivedTypes) >] " ,
113+ want: " any<array[number], set[number]> " )
47114 }
48115 }
49116}
0 commit comments