1// Copyright 2016 The OPA Authors.  All rights reserved.
2// Use of this source code is governed by an Apache2
3// license that can be found in the LICENSE file.
4
5package ast
6
7import (
8	"strings"
9
10	"github.com/open-policy-agent/opa/types"
11)
12
13// Builtins is the registry of built-in functions supported by OPA.
14// Call RegisterBuiltin to add a new built-in.
15var Builtins []*Builtin
16
17// RegisterBuiltin adds a new built-in function to the registry.
18func RegisterBuiltin(b *Builtin) {
19	Builtins = append(Builtins, b)
20	BuiltinMap[b.Name] = b
21	if len(b.Infix) > 0 {
22		BuiltinMap[b.Infix] = b
23	}
24}
25
26// DefaultBuiltins is the registry of built-in functions supported in OPA
27// by default. When adding a new built-in function to OPA, update this
28// list.
29var DefaultBuiltins = [...]*Builtin{
30
31	// Unification/equality ("=")
32	Equality,
33
34	// Assignment (":=")
35	Assign,
36
37	// Comparisons
38	GreaterThan,
39	GreaterThanEq,
40	LessThan,
41	LessThanEq,
42	NotEqual,
43	Equal,
44
45	// Arithmetic
46	Plus,
47	Minus,
48	Multiply,
49	Divide,
50	Round,
51	Abs,
52	Rem,
53
54	// Binary
55	And,
56	Or,
57
58	// Aggregates
59	Count,
60	Sum,
61	Product,
62	Max,
63	Min,
64
65	// Casting
66	ToNumber,
67
68	// Regular Expressions
69	RegexMatch,
70	GlobsMatch,
71
72	// Sets
73	SetDiff,
74	Intersection,
75	Union,
76
77	// Strings
78	Concat,
79	FormatInt,
80	IndexOf,
81	Substring,
82	Lower,
83	Upper,
84	Contains,
85	StartsWith,
86	EndsWith,
87	Split,
88	Replace,
89	Trim,
90	Sprintf,
91
92	// Encoding
93	JSONMarshal,
94	JSONUnmarshal,
95	Base64Encode,
96	Base64Decode,
97	Base64UrlEncode,
98	Base64UrlDecode,
99	URLQueryDecode,
100	URLQueryEncode,
101	URLQueryEncodeObject,
102	YAMLMarshal,
103	YAMLUnmarshal,
104
105	// Tokens
106	JWTDecode,
107	JWTVerifyRS256,
108	JWTVerifyHS256,
109
110	// Time
111	NowNanos,
112	ParseNanos,
113	ParseRFC3339Nanos,
114	ParseDurationNanos,
115	Date,
116	Clock,
117
118	// Crypto
119	CryptoX509ParseCertificates,
120
121	// Graphs
122	WalkBuiltin,
123
124	// Sort
125	Sort,
126
127	// Types
128	IsNumber,
129	IsString,
130	IsBoolean,
131	IsArray,
132	IsSet,
133	IsObject,
134	IsNull,
135	TypeNameBuiltin,
136
137	// HTTP
138	HTTPSend,
139
140	// Tracing
141	Trace,
142}
143
144// BuiltinMap provides a convenient mapping of built-in names to
145// built-in definitions.
146var BuiltinMap map[string]*Builtin
147
148// IgnoreDuringPartialEval is a set of built-in functions that should not be
149// evaluated during partial evaluation. These functions are not partially
150// evaluated because they are not pure.
151var IgnoreDuringPartialEval = []*Builtin{
152	NowNanos,
153	HTTPSend,
154}
155
156/**
157 * Unification
158 */
159
160// Equality represents the "=" operator.
161var Equality = &Builtin{
162	Name:  "eq",
163	Infix: "=",
164	Decl: types.NewFunction(
165		types.Args(types.A, types.A),
166		types.B,
167	),
168}
169
170/**
171 * Assignment
172 */
173
174// Assign represents the assignment (":=") operator.
175var Assign = &Builtin{
176	Name:  "assign",
177	Infix: ":=",
178	Decl: types.NewFunction(
179		types.Args(types.A, types.A),
180		types.B,
181	),
182}
183
184/**
185 * Comparisons
186 */
187
188// GreaterThan represents the ">" comparison operator.
189var GreaterThan = &Builtin{
190	Name:  "gt",
191	Infix: ">",
192	Decl: types.NewFunction(
193		types.Args(types.A, types.A),
194		types.B,
195	),
196}
197
198// GreaterThanEq represents the ">=" comparison operator.
199var GreaterThanEq = &Builtin{
200	Name:  "gte",
201	Infix: ">=",
202	Decl: types.NewFunction(
203		types.Args(types.A, types.A),
204		types.B,
205	),
206}
207
208// LessThan represents the "<" comparison operator.
209var LessThan = &Builtin{
210	Name:  "lt",
211	Infix: "<",
212	Decl: types.NewFunction(
213		types.Args(types.A, types.A),
214		types.B,
215	),
216}
217
218// LessThanEq represents the "<=" comparison operator.
219var LessThanEq = &Builtin{
220	Name:  "lte",
221	Infix: "<=",
222	Decl: types.NewFunction(
223		types.Args(types.A, types.A),
224		types.B,
225	),
226}
227
228// NotEqual represents the "!=" comparison operator.
229var NotEqual = &Builtin{
230	Name:  "neq",
231	Infix: "!=",
232	Decl: types.NewFunction(
233		types.Args(types.A, types.A),
234		types.B,
235	),
236}
237
238// Equal represents the "==" comparison operator.
239var Equal = &Builtin{
240	Name:  "equal",
241	Infix: "==",
242	Decl: types.NewFunction(
243		types.Args(types.A, types.A),
244		types.B,
245	),
246}
247
248/**
249 * Arithmetic
250 */
251
252// Plus adds two numbers together.
253var Plus = &Builtin{
254	Name:  "plus",
255	Infix: "+",
256	Decl: types.NewFunction(
257		types.Args(types.N, types.N),
258		types.N,
259	),
260}
261
262// Minus subtracts the second number from the first number or computes the diff
263// between two sets.
264var Minus = &Builtin{
265	Name:  "minus",
266	Infix: "-",
267	Decl: types.NewFunction(
268		types.Args(
269			types.NewAny(types.N, types.NewSet(types.A)),
270			types.NewAny(types.N, types.NewSet(types.A)),
271		),
272		types.NewAny(types.N, types.NewSet(types.A)),
273	),
274}
275
276// Multiply multiplies two numbers together.
277var Multiply = &Builtin{
278	Name:  "mul",
279	Infix: "*",
280	Decl: types.NewFunction(
281		types.Args(types.N, types.N),
282		types.N,
283	),
284}
285
286// Divide divides the first number by the second number.
287var Divide = &Builtin{
288	Name:  "div",
289	Infix: "/",
290	Decl: types.NewFunction(
291		types.Args(types.N, types.N),
292		types.N,
293	),
294}
295
296// Round rounds the number up to the nearest integer.
297var Round = &Builtin{
298	Name: "round",
299	Decl: types.NewFunction(
300		types.Args(types.N),
301		types.N,
302	),
303}
304
305// Abs returns the number without its sign.
306var Abs = &Builtin{
307	Name: "abs",
308	Decl: types.NewFunction(
309		types.Args(types.N),
310		types.N,
311	),
312}
313
314// Rem returns the remainder for x%y for y != 0.
315var Rem = &Builtin{
316	Name:  "rem",
317	Infix: "%",
318	Decl: types.NewFunction(
319		types.Args(types.N, types.N),
320		types.N,
321	),
322}
323
324/**
325 * Binary
326 */
327
328// TODO(tsandall): update binary operators to support integers.
329
330// And performs an intersection operation on sets.
331var And = &Builtin{
332	Name:  "and",
333	Infix: "&",
334	Decl: types.NewFunction(
335		types.Args(
336			types.NewSet(types.A),
337			types.NewSet(types.A),
338		),
339		types.NewSet(types.A),
340	),
341}
342
343// Or performs a union operation on sets.
344var Or = &Builtin{
345	Name:  "or",
346	Infix: "|",
347	Decl: types.NewFunction(
348		types.Args(
349			types.NewSet(types.A),
350			types.NewSet(types.A),
351		),
352		types.NewSet(types.A),
353	),
354}
355
356/**
357 * Aggregates
358 */
359
360// Count takes a collection or string and counts the number of elements in it.
361var Count = &Builtin{
362	Name: "count",
363	Decl: types.NewFunction(
364		types.Args(
365			types.NewAny(
366				types.NewSet(types.A),
367				types.NewArray(nil, types.A),
368				types.NewObject(nil, types.NewDynamicProperty(types.A, types.A)),
369				types.S,
370			),
371		),
372		types.N,
373	),
374}
375
376// Sum takes an array or set of numbers and sums them.
377var Sum = &Builtin{
378	Name: "sum",
379	Decl: types.NewFunction(
380		types.Args(
381			types.NewAny(
382				types.NewSet(types.N),
383				types.NewArray(nil, types.N),
384			),
385		),
386		types.N,
387	),
388}
389
390// Product takes an array or set of numbers and multiplies them.
391var Product = &Builtin{
392	Name: "product",
393	Decl: types.NewFunction(
394		types.Args(
395			types.NewAny(
396				types.NewSet(types.N),
397				types.NewArray(nil, types.N),
398			),
399		),
400		types.N,
401	),
402}
403
404// Max returns the maximum value in a collection.
405var Max = &Builtin{
406	Name: "max",
407	Decl: types.NewFunction(
408		types.Args(
409			types.NewAny(
410				types.NewSet(types.A),
411				types.NewArray(nil, types.A),
412			),
413		),
414		types.A,
415	),
416}
417
418// Min returns the minimum value in a collection.
419var Min = &Builtin{
420	Name: "min",
421	Decl: types.NewFunction(
422		types.Args(
423			types.NewAny(
424				types.NewSet(types.A),
425				types.NewArray(nil, types.A),
426			),
427		),
428		types.A,
429	),
430}
431
432/**
433 * Casting
434 */
435
436// ToNumber takes a string, bool, or number value and converts it to a number.
437// Strings are converted to numbers using strconv.Atoi.
438// Boolean false is converted to 0 and boolean true is converted to 1.
439var ToNumber = &Builtin{
440	Name: "to_number",
441	Decl: types.NewFunction(
442		types.Args(
443			types.NewAny(
444				types.N,
445				types.S,
446				types.B,
447				types.NewNull(),
448			),
449		),
450		types.N,
451	),
452}
453
454/**
455 * Regular Expressions
456 */
457
458// RegexMatch takes two strings and evaluates to true if the string in the second
459// position matches the pattern in the first position.
460var RegexMatch = &Builtin{
461	Name: "re_match",
462	Decl: types.NewFunction(
463		types.Args(
464			types.S,
465			types.S,
466		),
467		types.B,
468	),
469}
470
471// GlobsMatch takes two strings regexp-style strings and evaluates to true if their
472// intersection matches a non-empty set of non-empty strings.
473// Examples:
474//  - "a.a." and ".b.b" -> true.
475//  - "[a-z]*" and [0-9]+" -> not true.
476var GlobsMatch = &Builtin{
477	Name: "regex.globs_match",
478	Decl: types.NewFunction(
479		types.Args(
480			types.S,
481			types.S,
482		),
483		types.B,
484	),
485}
486
487/**
488 * Strings
489 */
490
491// Concat joins an array of strings with an input string.
492var Concat = &Builtin{
493	Name: "concat",
494	Decl: types.NewFunction(
495		types.Args(
496			types.S,
497			types.NewAny(
498				types.NewSet(types.S),
499				types.NewArray(nil, types.S),
500			),
501		),
502		types.S,
503	),
504}
505
506// FormatInt returns the string representation of the number in the given base after converting it to an integer value.
507var FormatInt = &Builtin{
508	Name: "format_int",
509	Decl: types.NewFunction(
510		types.Args(
511			types.N,
512			types.N,
513		),
514		types.S,
515	),
516}
517
518// IndexOf returns the index of a substring contained inside a string
519var IndexOf = &Builtin{
520	Name: "indexof",
521	Decl: types.NewFunction(
522		types.Args(
523			types.S,
524			types.S,
525		),
526		types.N,
527	),
528}
529
530// Substring returns the portion of a string for a given start index and a length.
531//   If the length is less than zero, then substring returns the remainder of the string.
532var Substring = &Builtin{
533	Name: "substring",
534	Decl: types.NewFunction(
535		types.Args(
536			types.S,
537			types.N,
538			types.N,
539		),
540		types.S,
541	),
542}
543
544// Contains returns true if the search string is included in the base string
545var Contains = &Builtin{
546	Name: "contains",
547	Decl: types.NewFunction(
548		types.Args(
549			types.S,
550			types.S,
551		),
552		types.B,
553	),
554}
555
556// StartsWith returns true if the search string begins with the base string
557var StartsWith = &Builtin{
558	Name: "startswith",
559	Decl: types.NewFunction(
560		types.Args(
561			types.S,
562			types.S,
563		),
564		types.B,
565	),
566}
567
568// EndsWith returns true if the search string begins with the base string
569var EndsWith = &Builtin{
570	Name: "endswith",
571	Decl: types.NewFunction(
572		types.Args(
573			types.S,
574			types.S,
575		),
576		types.B,
577	),
578}
579
580// Lower returns the input string but with all characters in lower-case
581var Lower = &Builtin{
582	Name: "lower",
583	Decl: types.NewFunction(
584		types.Args(types.S),
585		types.S,
586	),
587}
588
589// Upper returns the input string but with all characters in upper-case
590var Upper = &Builtin{
591	Name: "upper",
592	Decl: types.NewFunction(
593		types.Args(types.S),
594		types.S,
595	),
596}
597
598// Split returns an array containing elements of the input string split on a delimiter.
599var Split = &Builtin{
600	Name: "split",
601	Decl: types.NewFunction(
602		types.Args(
603			types.S,
604			types.S,
605		),
606		types.NewArray(nil, types.S),
607	),
608}
609
610// Replace returns the given string with all instances of the second argument replaced
611// by the third.
612var Replace = &Builtin{
613	Name: "replace",
614	Decl: types.NewFunction(
615		types.Args(
616			types.S,
617			types.S,
618			types.S,
619		),
620		types.S,
621	),
622}
623
624// Trim returns the given string will all leading or trailing instances of the second
625// argument removed.
626var Trim = &Builtin{
627	Name: "trim",
628	Decl: types.NewFunction(
629		types.Args(
630			types.S,
631			types.S,
632		),
633		types.S,
634	),
635}
636
637// Sprintf returns the given string, formatted.
638var Sprintf = &Builtin{
639	Name: "sprintf",
640	Decl: types.NewFunction(
641		types.Args(
642			types.S,
643			types.NewArray(nil, types.A),
644		),
645		types.S,
646	),
647}
648
649/**
650 * JSON
651 */
652
653// JSONMarshal serializes the input term.
654var JSONMarshal = &Builtin{
655	Name: "json.marshal",
656	Decl: types.NewFunction(
657		types.Args(types.A),
658		types.S,
659	),
660}
661
662// JSONUnmarshal deserializes the input string.
663var JSONUnmarshal = &Builtin{
664	Name: "json.unmarshal",
665	Decl: types.NewFunction(
666		types.Args(types.S),
667		types.A,
668	),
669}
670
671// Base64Encode serializes the input string into base64 encoding.
672var Base64Encode = &Builtin{
673	Name: "base64.encode",
674	Decl: types.NewFunction(
675		types.Args(types.S),
676		types.S,
677	),
678}
679
680// Base64Decode deserializes the base64 encoded input string.
681var Base64Decode = &Builtin{
682	Name: "base64.decode",
683	Decl: types.NewFunction(
684		types.Args(types.S),
685		types.S,
686	),
687}
688
689// Base64UrlEncode serializes the input string into base64url encoding.
690var Base64UrlEncode = &Builtin{
691	Name: "base64url.encode",
692	Decl: types.NewFunction(
693		types.Args(types.S),
694		types.S,
695	),
696}
697
698// Base64UrlDecode deserializes the base64url encoded input string.
699var Base64UrlDecode = &Builtin{
700	Name: "base64url.decode",
701	Decl: types.NewFunction(
702		types.Args(types.S),
703		types.S,
704	),
705}
706
707// URLQueryDecode decodes a URL encoded input string.
708var URLQueryDecode = &Builtin{
709	Name: "urlquery.decode",
710	Decl: types.NewFunction(
711		types.Args(types.S),
712		types.S,
713	),
714}
715
716// URLQueryEncode encodes the input string into a URL encoded string.
717var URLQueryEncode = &Builtin{
718	Name: "urlquery.encode",
719	Decl: types.NewFunction(
720		types.Args(types.S),
721		types.S,
722	),
723}
724
725// URLQueryEncodeObject encodes the given JSON into a URL encoded query string.
726var URLQueryEncodeObject = &Builtin{
727	Name: "urlquery.encode_object",
728	Decl: types.NewFunction(
729		types.Args(
730			types.NewObject(
731				nil,
732				types.NewDynamicProperty(
733					types.S,
734					types.NewAny(
735						types.S,
736						types.NewArray(nil, types.S),
737						types.NewSet(types.S))))),
738		types.S,
739	),
740}
741
742// YAMLMarshal serializes the input term.
743var YAMLMarshal = &Builtin{
744	Name: "yaml.marshal",
745	Decl: types.NewFunction(
746		types.Args(types.A),
747		types.S,
748	),
749}
750
751// YAMLUnmarshal deserializes the input string.
752var YAMLUnmarshal = &Builtin{
753	Name: "yaml.unmarshal",
754	Decl: types.NewFunction(
755		types.Args(types.S),
756		types.A,
757	),
758}
759
760/**
761 * Tokens
762 */
763
764// JWTDecode decodes a JSON Web Token and outputs it as an Object.
765var JWTDecode = &Builtin{
766	Name: "io.jwt.decode",
767	Decl: types.NewFunction(
768		types.Args(types.S),
769		types.NewArray([]types.Type{
770			types.NewObject(nil, types.NewDynamicProperty(types.A, types.A)),
771			types.NewObject(nil, types.NewDynamicProperty(types.A, types.A)),
772			types.S,
773		}, nil),
774	),
775}
776
777// JWTVerifyRS256 verifies if a RS256 JWT signature is valid or not.
778var JWTVerifyRS256 = &Builtin{
779	Name: "io.jwt.verify_rs256",
780	Decl: types.NewFunction(
781		types.Args(
782			types.S,
783			types.S,
784		),
785		types.B,
786	),
787}
788
789// JWTVerifyHS256 verifies if a HS256 (secret) JWT signature is valid or not.
790var JWTVerifyHS256 = &Builtin{
791	Name: "io.jwt.verify_hs256",
792	Decl: types.NewFunction(
793		types.Args(
794			types.S,
795			types.S,
796		),
797		types.B,
798	),
799}
800
801/**
802 * Time
803 */
804
805// NowNanos returns the current time since epoch in nanoseconds.
806var NowNanos = &Builtin{
807	Name: "time.now_ns",
808	Decl: types.NewFunction(
809		nil,
810		types.N,
811	),
812}
813
814// ParseNanos returns the time in nanoseconds parsed from the string in the given format.
815var ParseNanos = &Builtin{
816	Name: "time.parse_ns",
817	Decl: types.NewFunction(
818		types.Args(
819			types.S,
820			types.S,
821		),
822		types.N,
823	),
824}
825
826// ParseRFC3339Nanos returns the time in nanoseconds parsed from the string in RFC3339 format.
827var ParseRFC3339Nanos = &Builtin{
828	Name: "time.parse_rfc3339_ns",
829	Decl: types.NewFunction(
830		types.Args(types.S),
831		types.N,
832	),
833}
834
835// ParseDurationNanos returns the duration in nanoseconds represented by a duration string.
836// Duration string is similar to the Go time.ParseDuration string
837var ParseDurationNanos = &Builtin{
838	Name: "time.parse_duration_ns",
839	Decl: types.NewFunction(
840		types.Args(types.S),
841		types.N,
842	),
843}
844
845// Date returns the [year, month, day] for the nanoseconds since epoch.
846var Date = &Builtin{
847	Name: "time.date",
848	Decl: types.NewFunction(
849		types.Args(types.N),
850		types.NewArray([]types.Type{types.N, types.N, types.N}, nil),
851	),
852}
853
854// Clock returns the [hour, minute, second] of the day for the nanoseconds since epoch.
855var Clock = &Builtin{
856	Name: "time.clock",
857	Decl: types.NewFunction(
858		types.Args(types.N),
859		types.NewArray([]types.Type{types.N, types.N, types.N}, nil),
860	),
861}
862
863/**
864 * Crypto.
865 */
866
867// CryptoX509ParseCertificates returns one or more certificates from the given
868// base64 encoded string containing DER encoded certificates that have been
869// concatenated.
870var CryptoX509ParseCertificates = &Builtin{
871	Name: "crypto.x509.parse_certificates",
872	Decl: types.NewFunction(
873		types.Args(types.S),
874		types.NewArray(nil, types.NewObject(nil, types.NewDynamicProperty(types.S, types.A))),
875	),
876}
877
878/**
879 * Graphs.
880 */
881
882// WalkBuiltin generates [path, value] tuples for all nested documents
883// (recursively).
884var WalkBuiltin = &Builtin{
885	Name:     "walk",
886	Relation: true,
887	Decl: types.NewFunction(
888		types.Args(types.A),
889		types.NewArray(
890			[]types.Type{
891				types.NewArray(nil, types.A),
892				types.A,
893			},
894			nil,
895		),
896	),
897}
898
899/**
900 * Sorting
901 */
902
903// Sort returns a sorted array.
904var Sort = &Builtin{
905	Name: "sort",
906	Decl: types.NewFunction(
907		types.Args(
908			types.NewAny(
909				types.NewArray(nil, types.A),
910				types.NewSet(types.A),
911			),
912		),
913		types.NewArray(nil, types.A),
914	),
915}
916
917/**
918 * Type
919 */
920
921// IsNumber returns true if the input value is a number
922var IsNumber = &Builtin{
923	Name: "is_number",
924	Decl: types.NewFunction(
925		types.Args(
926			types.A,
927		),
928		types.B,
929	),
930}
931
932// IsString returns true if the input value is a string.
933var IsString = &Builtin{
934	Name: "is_string",
935	Decl: types.NewFunction(
936		types.Args(
937			types.A,
938		),
939		types.B,
940	),
941}
942
943// IsBoolean returns true if the input value is a boolean.
944var IsBoolean = &Builtin{
945	Name: "is_boolean",
946	Decl: types.NewFunction(
947		types.Args(
948			types.A,
949		),
950		types.B,
951	),
952}
953
954// IsArray returns true if the input value is an array.
955var IsArray = &Builtin{
956	Name: "is_array",
957	Decl: types.NewFunction(
958		types.Args(
959			types.A,
960		),
961		types.B,
962	),
963}
964
965// IsSet returns true if the input value is a set.
966var IsSet = &Builtin{
967	Name: "is_set",
968	Decl: types.NewFunction(
969		types.Args(
970			types.A,
971		),
972		types.B,
973	),
974}
975
976// IsObject returns true if the input value is an object.
977var IsObject = &Builtin{
978	Name: "is_object",
979	Decl: types.NewFunction(
980		types.Args(
981			types.A,
982		),
983		types.B,
984	),
985}
986
987// IsNull returns true if the input value is null.
988var IsNull = &Builtin{
989	Name: "is_null",
990	Decl: types.NewFunction(
991		types.Args(
992			types.A,
993		),
994		types.B,
995	),
996}
997
998/**
999 * Type Name
1000 */
1001
1002// TypeNameBuiltin returns the type of the input.
1003var TypeNameBuiltin = &Builtin{
1004	Name: "type_name",
1005	Decl: types.NewFunction(
1006		types.Args(
1007			types.NewAny(
1008				types.A,
1009			),
1010		),
1011		types.S,
1012	),
1013}
1014
1015/**
1016 * HTTP Request
1017 */
1018
1019// HTTPSend returns a HTTP response to the given HTTP request.
1020var HTTPSend = &Builtin{
1021	Name: "http.send",
1022	Decl: types.NewFunction(
1023		types.Args(
1024			types.NewObject(nil, types.NewDynamicProperty(types.S, types.A)),
1025		),
1026		types.NewObject(nil, types.NewDynamicProperty(types.A, types.A)),
1027	),
1028}
1029
1030/**
1031 * Trace
1032 */
1033
1034// Trace prints a note that is included in the query explanation.
1035var Trace = &Builtin{
1036	Name: "trace",
1037	Decl: types.NewFunction(
1038		types.Args(
1039			types.S,
1040		),
1041		types.B,
1042	),
1043}
1044
1045/**
1046 * Set
1047 */
1048
1049// Intersection returns the intersection of the given input sets
1050var Intersection = &Builtin{
1051	Name: "intersection",
1052	Decl: types.NewFunction(
1053		types.Args(
1054			types.NewSet(types.NewSet(types.A)),
1055		),
1056		types.NewSet(types.A),
1057	),
1058}
1059
1060// Union returns the union of the given input sets
1061var Union = &Builtin{
1062	Name: "union",
1063	Decl: types.NewFunction(
1064		types.Args(
1065			types.NewSet(types.NewSet(types.A)),
1066		),
1067		types.NewSet(types.A),
1068	),
1069}
1070
1071/**
1072 * Deprecated built-ins.
1073 */
1074
1075// SetDiff has been replaced by the minus built-in.
1076var SetDiff = &Builtin{
1077	Name: "set_diff",
1078	Decl: types.NewFunction(
1079		types.Args(
1080			types.NewSet(types.A),
1081			types.NewSet(types.A),
1082		),
1083		types.NewSet(types.A),
1084	),
1085}
1086
1087// Builtin represents a built-in function supported by OPA. Every built-in
1088// function is uniquely identified by a name.
1089type Builtin struct {
1090	Name     string          // Unique name of built-in function, e.g., <name>(arg1,arg2,...,argN)
1091	Infix    string          // Unique name of infix operator. Default should be unset.
1092	Decl     *types.Function // Built-in function type declaration.
1093	Relation bool            // Indicates if the built-in acts as a relation.
1094}
1095
1096// Expr creates a new expression for the built-in with the given operands.
1097func (b *Builtin) Expr(operands ...*Term) *Expr {
1098	ts := make([]*Term, len(operands)+1)
1099	ts[0] = NewTerm(b.Ref())
1100	for i := range operands {
1101		ts[i+1] = operands[i]
1102	}
1103	return &Expr{
1104		Terms: ts,
1105	}
1106}
1107
1108// Call creates a new term for the built-in with the given operands.
1109func (b *Builtin) Call(operands ...*Term) *Term {
1110	call := make(Call, len(operands)+1)
1111	call[0] = NewTerm(b.Ref())
1112	for i := range operands {
1113		call[i+1] = operands[i]
1114	}
1115	return NewTerm(call)
1116}
1117
1118// Ref returns a Ref that refers to the built-in function.
1119func (b *Builtin) Ref() Ref {
1120	parts := strings.Split(b.Name, ".")
1121	ref := make(Ref, len(parts))
1122	ref[0] = VarTerm(parts[0])
1123	for i := 1; i < len(parts); i++ {
1124		ref[i] = StringTerm(parts[i])
1125	}
1126	return ref
1127}
1128
1129// IsTargetPos returns true if a variable in the i-th position will be bound by
1130// evaluating the call expression.
1131func (b *Builtin) IsTargetPos(i int) bool {
1132	return len(b.Decl.Args()) == i
1133}
1134
1135func init() {
1136	BuiltinMap = map[string]*Builtin{}
1137	for _, b := range DefaultBuiltins {
1138		RegisterBuiltin(b)
1139	}
1140}
1141