rego-cpp 1.4.0
A C++ implementation of the Rego language and runtime
Loading...
Searching...
No Matches
rego.hh
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#pragma once
5
6#include "rego_c.h"
7#include "trieste/logging.h"
8#include "trieste/token.h"
9
10#include <initializer_list>
11#include <trieste/trieste.h>
12
17namespace rego
18{
19 using namespace trieste;
20 using namespace wf::ops;
21
23 inline const auto Module =
24 TokenDef("rego-module", flag::lookup | flag::symtab);
25 inline const auto Package = TokenDef("rego-package");
26 inline const auto Policy = TokenDef("rego-policy");
27 inline const auto Rule = TokenDef(
28 "rego-rule",
29 flag::lookup | flag::lookdown | flag::symtab | flag::defbeforeuse);
30 inline const auto RuleHead = TokenDef("rego-rulehead");
31 inline const auto RuleHeadComp = TokenDef("rego-ruleheadcomp");
32 inline const auto RuleHeadFunc = TokenDef("rego-ruleheadfunc");
33 inline const auto RuleHeadSet = TokenDef("rego-ruleheadset");
34 inline const auto RuleHeadObj = TokenDef("rego-ruleheadobj");
35 inline const auto RuleArgs = TokenDef("rego-ruleargs");
36 inline const auto Query = TokenDef("rego-query");
37 inline const auto Literal = TokenDef("rego-literal");
38 inline const auto Expr = TokenDef("rego-expr");
39 inline const auto ExprInfix = TokenDef("rego-exprinfix");
40 inline const auto ExprCall = TokenDef("rego-exprcall");
41 inline const auto ExprEvery = TokenDef("rego-exprevery", flag::symtab);
42 inline const auto ExprParens = TokenDef("rego-exprparens");
43 inline const auto UnaryExpr = TokenDef("rego-unaryexpr");
44 inline const auto NotExpr = TokenDef("rego-not-expr");
45 inline const auto Term = TokenDef("rego-term");
46 inline const auto InfixOperator = TokenDef("rego-infixoperator");
47 inline const auto BoolOperator = TokenDef("rego-booloperator");
48 inline const auto ArithOperator = TokenDef("rego-arithoperator");
49 inline const auto AssignOperator = TokenDef("rego-assignoperator");
50 inline const auto BinOperator = TokenDef("rego-binoperator");
51 inline const auto Ref = TokenDef("rego-ref");
52 inline const auto RefArgBrack = TokenDef("rego-refargbrack");
53 inline const auto RefArgDot = TokenDef("rego-refargdot");
54 inline const auto Var = TokenDef("rego-var", flag::print);
55 inline const auto Scalar = TokenDef("rego-scalar");
56 inline const auto String = TokenDef("rego-string");
57 inline const auto Array = TokenDef("rego-array");
58 inline const auto Object = TokenDef("rego-object");
59 inline const auto Set = TokenDef("rego-set");
60 inline const auto ObjectItem = TokenDef("rego-objectitem");
61 inline const auto RawString = TokenDef("rego-rawstring", flag::print);
62 inline const auto JSONString = TokenDef("rego-STRING", flag::print);
63 inline const auto TemplateString = TokenDef("rego-templatestring");
64 inline const auto TemplateLiteral =
65 TokenDef("rego-templateliteral", flag::print);
66 inline const auto Int = TokenDef("rego-INT", flag::print);
67 inline const auto Float = TokenDef("rego-FLOAT", flag::print);
68 inline const auto True = TokenDef("rego-true");
69 inline const auto False = TokenDef("rego-false");
70 inline const auto Null = TokenDef("rego-null");
71 inline const auto Equals = TokenDef("rego-equals");
72 inline const auto NotEquals = TokenDef("rego-notequals");
73 inline const auto LessThan = TokenDef("rego-lessthan");
74 inline const auto GreaterThan = TokenDef("rego-greaterthan");
75 inline const auto LessThanOrEquals = TokenDef("rego-lessthanorequals");
76 inline const auto GreaterThanOrEquals = TokenDef("rego-greaterthanorequals");
77 inline const auto Add = TokenDef("rego-add");
78 inline const auto Subtract = TokenDef("rego-subtract");
79 inline const auto Multiply = TokenDef("rego-multiply");
80 inline const auto Divide = TokenDef("rego-divide");
81 inline const auto Modulo = TokenDef("rego-modulo");
82 inline const auto And = TokenDef("rego-and");
83 inline const auto Or = TokenDef("rego-or");
84 inline const auto Assign = TokenDef("rego-assign");
85 inline const auto Unify = TokenDef("rego-unify");
86 inline const auto Default = TokenDef("rego-default");
87 inline const auto Some = TokenDef("rego-some");
88 inline const auto SomeDecl = TokenDef("rego-somedecl");
89 inline const auto If = TokenDef("rego-if");
90 inline const auto IsIn = TokenDef("rego-in");
91 inline const auto Contains = TokenDef("rego-contains");
92 inline const auto Else = TokenDef("rego-else");
93 inline const auto As = TokenDef("rego-as");
94 inline const auto With = TokenDef("rego-with");
95 inline const auto Every = TokenDef("rego-every");
96 inline const auto ArrayCompr = TokenDef("rego-arraycompr", flag::symtab);
97 inline const auto ObjectCompr = TokenDef("rego-objectcompr", flag::symtab);
98 inline const auto SetCompr = TokenDef("rego-setcompr", flag::symtab);
99 inline const auto Membership = TokenDef("rego-membership");
100 inline const auto Not = TokenDef("rego-not");
101 inline const auto Import =
102 TokenDef("rego-import", flag::lookdown | flag::lookup | flag::shadowing);
103 inline const auto Placeholder = TokenDef("rego-placeholder");
104 inline const auto Version = TokenDef("rego-version", flag::print);
105
106 // intermediate tokens
107 inline const auto RuleBodySeq = TokenDef("rego-rulebodyseq");
108 inline const auto ImportSeq = TokenDef("rego-importseq");
109 inline const auto RuleRef = TokenDef("rego-ruleref");
110 inline const auto RuleHeadType = TokenDef("rego-ruleheadtype");
111 inline const auto WithSeq = TokenDef("rego-withseq");
112 inline const auto TermSeq = TokenDef("rego-termseq");
113 inline const auto ExprSeq = TokenDef("rego-exprseq");
114 inline const auto VarSeq = TokenDef("rego-varseq");
115 inline const auto RefHead = TokenDef("rego-refhead");
116 inline const auto RefArgSeq = TokenDef("rego-refargseq");
117 inline const auto Key = TokenDef("rego-key", flag::print);
118 inline const auto Val = TokenDef("rego-value");
119 inline const auto Undefined = TokenDef("rego-undefined");
120 inline const auto Name = TokenDef("rego-name");
121 inline const auto Return = TokenDef("rego-return");
122 inline const auto Target = TokenDef("rego-target");
123 inline const auto Lhs = TokenDef("rego-lhs");
124 inline const auto Rhs = TokenDef("rego-rhs");
125 inline const auto Src = TokenDef("rego-src");
126 inline const auto Args = TokenDef("rego-args");
127 inline const auto Idx = TokenDef("rego-idx");
128 inline const auto Row = TokenDef("rego-row");
129 inline const auto Col = TokenDef("rego-col");
130
131 // other tokens
132 inline const auto Results = TokenDef("rego-results", flag::symtab);
133 inline const auto Result = TokenDef("rego-result", flag::symtab);
134 inline const auto Bindings = TokenDef("rego-bindings");
135 inline const auto Terms = TokenDef("rego-terms");
136 inline const auto Binding = TokenDef("rego-binding", flag::lookdown);
137 inline const auto ErrorCode = TokenDef("rego-errorcode");
138 inline const auto ErrorSeq = TokenDef("rego-errorseq");
139 inline const auto Line = TokenDef("rego-line", flag::print);
140
141 inline const auto wf_assign_op = Assign | Unify;
142 inline const auto wf_arith_op = Add | Subtract | Multiply | Divide | Modulo;
143 inline const auto wf_bin_op = And | Or | Subtract;
144 inline const auto wf_bool_op = Equals | NotEquals | LessThan |
145 LessThanOrEquals | GreaterThan | GreaterThanOrEquals | Not;
146 inline const auto wf_exprs =
147 Term | ExprCall | ExprInfix | ExprEvery | ExprParens | UnaryExpr;
148
149 // clang-format off
150 inline const auto wf =
151 (Top <<= Query | Module)
152 | (Module <<= Package * Version * ImportSeq * Policy)
153 | (ImportSeq <<= Import++)
154 | (Import <<= Ref * Var)
155 | (Package <<= Ref)
156 | (Policy <<= Rule++)
157 | (Rule <<= (Default >>= True | False) * RuleHead * RuleBodySeq)
158 | (RuleHead <<= RuleRef * (RuleHeadType >>= (RuleHeadSet | RuleHeadObj | RuleHeadFunc | RuleHeadComp)))
159 | (RuleRef <<= Var | Ref)
160 | (RuleHeadComp <<= Expr)
161 | (RuleHeadObj <<= Expr * Expr)
162 | (RuleHeadFunc <<= RuleArgs * Expr)
163 | (RuleHeadSet <<= Expr)
164 | (RuleArgs <<= Term++)
165 | (RuleBodySeq <<= (Else | Query)++)
166 | (Else <<= Expr * Query)
167 | (Query <<= Literal++)
168 | (Literal <<= (Expr >>= SomeDecl | Expr | NotExpr) * WithSeq)
169 | (WithSeq <<= With++)
170 | (With <<= Term * Expr)
171 | (SomeDecl <<= ExprSeq * (IsIn >>= Expr | Undefined))
172 | (NotExpr <<= Expr)
173 | (Expr <<= (Term | ExprCall | ExprInfix | ExprEvery | ExprParens | UnaryExpr))
174 | (ExprCall <<= Ref * ExprSeq)
175 | (ExprSeq <<= Expr++)
176 | (ExprInfix <<= Expr * InfixOperator * Expr)
177 | (ExprEvery <<= VarSeq * (IsIn >>= Term | ExprCall | ExprInfix) * Query)
178 | (VarSeq <<= Var++[1])
179 | (ExprParens <<= Expr)
180 | (UnaryExpr <<= Expr)
181 | (Membership <<= ExprSeq * Expr)
182 | (Term <<= Ref | Var | Scalar | Array | Object | Set | Membership | ArrayCompr | ObjectCompr | SetCompr)
183 | (TemplateString <<= Literal++)
184 | (ArrayCompr <<= Expr * Query)
185 | (SetCompr <<= Expr * Query)
186 | (ObjectCompr <<= Expr * Expr * Query)
187 | (InfixOperator <<= AssignOperator | BoolOperator | ArithOperator | BinOperator)
188 | (BoolOperator <<= Equals | NotEquals | LessThan | GreaterThan | LessThanOrEquals | GreaterThanOrEquals)
189 | (ArithOperator <<= Add | Subtract | Multiply | Divide | Modulo)
190 | (BinOperator <<= And | Or)
191 | (AssignOperator <<= Assign | Unify)
192 | (Ref <<= RefHead * RefArgSeq)
193 | (RefHead <<= Var | Array | Object | Set | ArrayCompr | ObjectCompr | SetCompr | ExprCall)
194 | (RefArgSeq <<= (RefArgDot | RefArgBrack)++)
195 | (RefArgBrack <<= Expr | Placeholder)
196 | (RefArgDot <<= Var)
197 | (Scalar <<= String | Int | Float | True | False | Null)
198 | (String <<= JSONString | RawString | TemplateString)
199 | (Array <<= Expr++)
200 | (Object <<= ObjectItem++)
201 | (ObjectItem <<= (Key >>= Expr) * (Val >>= Expr))
202 | (Set <<= Expr++)
203 ;
204 // clang-format on
205
206 // clang-format off
207 inline const auto wf_result =
208 (Top <<= Results | Undefined)
209 | (Results <<= Result++[1])
210 | (Result <<= Terms * Bindings)
211 | (Terms <<= Term++)
212 | (Bindings <<= Binding++)
213 | (Binding <<= (Key >>= Var) * (Val >>= Term))[Key]
214 | (Term <<= Scalar | Array | Object | Set)
215 | (Array <<= Term++)
216 | (Set <<= Term++)
217 | (Object <<= ObjectItem++)
218 | (ObjectItem <<= (Key >>= Term) * (Val >>= Term))
219 | (Scalar <<= JSONString | Int | Float | True | False | Null)
220 | (Error <<= ErrorMsg * ErrorAst * ErrorCode)
221 ;
222 // clang-format on
223
225
226 struct BuiltInDef;
227
229 using BuiltIn = std::shared_ptr<BuiltInDef>;
230
232 using BuiltInBehavior = std::function<Node(const Nodes&)>;
233
236 // This is a basic, non-optimized implementation of a big integer
243 class BigInt
244 {
245 public:
251 BigInt(const Location& value);
254 BigInt(std::int64_t value);
255
258 const Location& loc() const;
262 std::optional<std::int64_t> to_int() const;
266 std::optional<std::size_t> to_size() const;
267
270 bool is_negative() const;
271
274 bool is_zero() const;
275
284 BigInt abs() const;
287 BigInt negate() const;
288
293 static bool is_int(const Location& loc);
294
299 friend BigInt operator+(const BigInt& lhs, const BigInt& rhs);
300
305 friend BigInt operator-(const BigInt& lhs, const BigInt& rhs);
306
311 friend BigInt operator*(const BigInt& lhs, const BigInt& rhs);
312
317 friend BigInt operator/(const BigInt& lhs, const BigInt& rhs);
318
323 friend BigInt operator%(const BigInt& lhs, const BigInt& rhs);
324
329 friend bool operator>(const BigInt& lhs, const BigInt& rhs);
330
335 friend bool operator<(const BigInt& lhs, const BigInt& rhs);
336
341 friend bool operator<=(const BigInt& lhs, const BigInt& rhs);
342
347 friend bool operator>=(const BigInt& lhs, const BigInt& rhs);
348
353 friend bool operator==(const BigInt& lhs, const BigInt& rhs);
354
359 friend bool operator!=(const BigInt& lhs, const BigInt& rhs);
360
365 friend std::ostream& operator<<(std::ostream& os, const BigInt& value);
366
367 private:
368 struct DivideResult
369 {
370 std::string quotient;
371 std::string remainder;
372 };
373
374 static bool less_than(
375 const std::string_view& lhs, const std::string_view& rhs);
376 static bool greater_than(
377 const std::string_view& lhs, const std::string_view& rhs);
378 static bool equal(const std::string_view& lhs, const std::string_view& rhs);
379 static std::string add(
380 const std::string_view& lhs, const std::string_view& rhs, bool negative);
381 static std::string subtract(
382 const std::string_view& lhs, const std::string_view& rhs, bool negative);
383 static DivideResult divide(
384 const std::string_view& lhs, const std::string_view& rhs);
385 static std::string multiply(
386 const std::string_view& lhs, const std::string_view& rhs);
387 std::string_view digits() const;
388 Location m_loc;
389 static Location Zero;
390 static Location One;
391 };
392
395 {
397 Node node;
398
401 };
402
420 {
421 public:
425 UnwrapOpt(std::size_t index);
426
429 bool exclude_got() const;
430
436
439 bool specify_number() const;
440
447
450 const std::string& code() const;
451
455 UnwrapOpt& code(const std::string& value);
456
460 const std::string& pre() const;
461
465 UnwrapOpt& pre(const std::string& value);
466
470 const std::string& message() const;
471
477 UnwrapOpt& message(const std::string& value);
478
482 const std::string& func() const;
483
487 UnwrapOpt& func(const std::string& value);
488
493 const std::vector<Token>& types() const;
494
500 UnwrapOpt& types(const std::vector<Token>& value);
501
504 const Token& type() const;
505
510 UnwrapOpt& type(const Token& value);
511
515 Node unwrap(const Nodes& args) const;
516
517 private:
518 bool m_exclude_got;
519 bool m_specify_number;
520 std::string m_code;
521 std::string m_prefix;
522 std::string m_message;
523 std::string m_func;
524 std::vector<Token> m_types;
525 Token m_type;
526 std::size_t m_index;
527 };
528
533 Node unwrap_arg(const Nodes& args, const UnwrapOpt& options);
534
539 UnwrapResult unwrap(const Node& term, const Token& type);
540
545 UnwrapResult unwrap(const Node& term, const std::set<Token>& types);
546
550 BigInt get_int(const Node& node);
551
557 std::optional<BigInt> try_get_int(const Node& node);
558
562 double get_double(const Node& node);
563
568 std::optional<double> try_get_double(const Node& node);
569
574 std::string get_string(const Node& node);
575
580 std::optional<std::string> try_get_string(const Node& node);
581
585 bool get_bool(const Node& node);
586
590 std::optional<bool> try_get_bool(const Node& node);
591
596 std::optional<Node> try_get_item(
597 const Node& node, const std::string_view& key);
598
604 std::string_view get_raw_string(const Node& node);
605
611
616 Node scalar(double value);
617
622 Node scalar(bool value);
623
628 Node scalar(const char* value);
629
634 Node scalar(const std::string& value);
635
640
644 Node number(double value);
645
649 Node boolean(bool value);
650
654 Node string(const char* value);
655
659 Node string(const std::string& value);
660
664
670
674 Node object(const std::initializer_list<Node>& object_items);
675
679 Node array(const std::initializer_list<Node>& array_members);
680
684 Node set(const std::initializer_list<Node>& set_members);
685
686 namespace builtins
687 {
689 const std::size_t AnyArity = std::numeric_limits<std::size_t>::max();
690
691 inline const auto Decl = TokenDef("rego-builtin-decl");
692 inline const auto Arg = TokenDef("rego-builtin-arg");
693 inline const auto Args = TokenDef("rego-builtin-args");
694 inline const auto VarArgs = TokenDef("rego-builtin-varargs");
695 inline const auto Result = TokenDef("rego-builtin-result");
696 inline const auto Void = TokenDef("rego-builtin-void");
697 inline const auto Return = TokenDef("rego-builtins-return");
698 inline const auto Name = TokenDef("rego-builtin-name", flag::print);
699 inline const auto Description =
700 TokenDef("rego-builtin-description", flag::print);
701 inline const auto Type = TokenDef("rego-builtin-type");
702 inline const auto ArgSeq = TokenDef("rego-builtin-argseq");
703 inline const auto MemberType = TokenDef("rego-builtin-membertype");
704 inline const auto TypeSeq = TokenDef("rego-builtin-typeseq");
705 inline const auto DynamicArray = TokenDef("rego-builtin-dynamicarray");
706 inline const auto StaticArray = TokenDef("rego-builtin-staticarray");
707 inline const auto Set = TokenDef("rego-builtin-set");
708 inline const auto DynamicObject = TokenDef("rego-builtin-dynamicobject");
709 inline const auto StaticObject = TokenDef("rego-builtin-staticobject");
710 inline const auto HybridObject = TokenDef("rego-builtin-hybridobject");
711 inline const auto ObjectItem = TokenDef("rego-builtin-objectitem");
712 inline const auto Any = TokenDef("rego-builtin-any");
713 inline const auto String = TokenDef("rego-builtin-string");
714 inline const auto Number = TokenDef("rego-builtin-number");
715 inline const auto Boolean = TokenDef("rego-builtin-boolean");
716 inline const auto Null = TokenDef("rego-builtin-null");
717
718 // clang-format off
719 inline const auto wf_decl =
720 (Decl <<= (Args >>= ArgSeq | VarArgs) * (Return >>= Result | Void))
721 | (ArgSeq <<= Arg++)
722 | (Arg <<= Name * Description * Type)
724 | (TypeSeq <<= Type++)
725 | (DynamicArray <<= Type)
726 | (StaticArray <<= Type++)
727 | (Set <<= Type)
728 | (DynamicObject <<= (Key >>= Type) * (Val >>= Type))
729 | (StaticObject <<= ObjectItem++)
731 | (ObjectItem <<= Name * Type)
732 | (Result <<= Name * Description * Type)
733 ;
734 // clang-format on
736 }
737
793 {
797
801
805 std::size_t arity;
806
809
812
816
817 virtual ~BuiltInDef() = default;
818
820 virtual void clear();
821
833
845 const Location& name, size_t arity, BuiltInBehavior behavior);
846
859 const Location& name, Node decl, const std::string& message);
860 };
861
862 typedef BuiltIn (*BuiltInFactory)();
863
874 {
875 public:
878
883
889
897
904
906 void clear();
907
912
917
923
929
935 {
936 for (auto& built_in : built_ins)
937 {
939 }
940
941 return *this;
942 }
943
948
954 template <typename T>
955 BuiltInsDef& whitelist(const std::initializer_list<T>& allowed)
956 {
957 m_lookup_behavior = BuiltInsDef::LookupBehavior::Whitelist;
958 m_list.clear();
959 m_list.insert(allowed.begin(), allowed.end());
960 m_builtins.clear();
961 return *this;
962 }
963
971 template <typename T>
973 {
974 m_lookup_behavior = BuiltInsDef::LookupBehavior::Whitelist;
975 m_list.clear();
976 m_list.insert(begin, end);
977 m_builtins.clear();
978 return *this;
979 }
980
987 template <typename T>
988 BuiltInsDef& blacklist(const std::initializer_list<T>& forbidden)
989 {
990 m_lookup_behavior = BuiltInsDef::LookupBehavior::Blacklist;
991 m_list.clear();
992 m_list.insert(forbidden.begin(), forbidden.end());
993 m_builtins.clear();
994 return *this;
995 }
996
1005 template <typename T>
1007 {
1008 m_lookup_behavior = BuiltInsDef::LookupBehavior::Blacklist;
1009 m_list.clear();
1010 m_list.insert(begin, end);
1011 m_builtins.clear();
1012 return *this;
1013 }
1014
1018
1021 static std::shared_ptr<BuiltInsDef> create();
1022
1023 private:
1024 static BuiltIn lookup(const Location& name);
1025
1026 enum class LookupBehavior
1027 {
1028 AllowAll,
1029 Whitelist,
1030 Blacklist
1031 };
1032
1033 LookupBehavior m_lookup_behavior;
1034 std::set<Location> m_list;
1035 std::map<Location, BuiltIn> m_builtins;
1036 bool m_strict_errors;
1037 };
1038
1040 using BuiltIns = std::shared_ptr<BuiltInsDef>;
1041
1042 const std::string UnknownError = "unknown_error";
1043 const std::string EvalTypeError = "eval_type_error";
1044 const std::string EvalBuiltInError = "eval_builtin_error";
1045 const std::string RegoTypeError = "rego_type_error";
1046 const std::string RegoParseError = "rego_parse_error";
1047 const std::string RegoCompileError = "rego_compile_error";
1048 const std::string EvalConflictError = "eval_conflict_error";
1049 const std::string WellFormedError = "wellformed_error";
1050 const std::string RuntimeError = "runtime_error";
1051 const std::string RecursionError = "rego_recursion_error";
1052 const std::string TimeoutError = "timeout_error";
1053 const std::string DefaultVersion = "v1";
1055
1062 NodeRange& r,
1063 const std::string& msg,
1064 const std::string& code = UnknownError);
1065
1072 Node node, const std::string& msg, const std::string& code = UnknownError);
1073
1083
1085 enum class SetFormat
1086 {
1088 Angle,
1090 Square,
1092 Rego,
1093 };
1094
1102 std::string to_key(
1103 const trieste::Node& node,
1105 bool sort_arrays = false,
1106 const char* list_delim = ",");
1107
1109 enum class LogLevel : regoEnum
1110 {
1111 None = REGO_LOG_LEVEL_NONE,
1112 Error = REGO_LOG_LEVEL_ERROR,
1114 Warn = REGO_LOG_LEVEL_WARN,
1115 Info = REGO_LOG_LEVEL_INFO,
1116 Debug = REGO_LOG_LEVEL_DEBUG,
1117 Trace = REGO_LOG_LEVEL_TRACE
1118 };
1119
1122 namespace bundle
1123 {
1125 enum class OperandType
1126 {
1127 None,
1128 Local = 1,
1129 String = 2,
1130 True = 3,
1131 False = 4,
1132 Index,
1133 Value
1134 };
1135
1145 struct Operand
1146 {
1149 union
1150 {
1152 std::int64_t value;
1154 size_t index;
1155 };
1156
1159
1164 static Operand from_op(const Node& n);
1165
1171 static Operand from_index(const Node& n);
1172
1178 static Operand from_value(const Node& n);
1179
1184 friend std::ostream& operator<<(std::ostream& stream, const Operand& op);
1185 };
1186
1191 enum class StatementType
1192 {
1193 Nop = 0,
1194 ArrayAppend = 1,
1195 AssignInt = 2,
1196 AssignVarOnce = 3,
1197 AssignVar = 4,
1198 Block = 5,
1199 Break = 6,
1200 CallDynamic = 7,
1201 Call = 8,
1202 Dot = 9,
1203 Equal = 10,
1204 IsArray = 11,
1205 IsDefined = 12,
1206 IsObject = 13,
1207 IsSet = 14,
1208 IsUndefined = 15,
1209 Len = 16,
1210 MakeArray = 17,
1211 MakeNull = 18,
1212 MakeNumberInt = 19,
1213 MakeNumberRef = 20,
1214 MakeObject = 21,
1215 MakeSet = 22,
1216 NotEqual = 23,
1217 Not = 24,
1218 ObjectInsert = 25,
1219 ObjectInsertOnce = 26,
1220 ObjectMerge = 27,
1221 ResetLocal = 28,
1222 ResultSetAdd = 29,
1223 ReturnLocal = 30,
1224 Scan = 31,
1225 SetAdd = 32,
1226 With = 33
1227 };
1228
1229 struct Statement;
1230
1232 typedef std::vector<Statement> Block;
1233
1235 struct CallExt
1236 {
1240 std::vector<Operand> ops;
1241 };
1242
1245 {
1247 std::vector<Operand> path;
1249 std::vector<Operand> ops;
1250 };
1251
1253 struct WithExt
1254 {
1256 std::vector<size_t> path;
1259 };
1260
1264 {
1266 std::variant<CallExt, CallDynamicExt, WithExt, std::vector<Block>, Block>
1268
1271 const CallExt& call() const;
1277 const WithExt& with() const;
1280 const std::vector<Block>& blocks() const;
1283 const Block& block() const;
1284
1292 StatementExt(std::vector<Block>&& blocks);
1295 };
1296
1306 {
1311
1314
1317
1319 std::int32_t target;
1320
1322 std::shared_ptr<const StatementExt> ext;
1323
1326
1331 friend std::ostream& operator<<(
1332 std::ostream& stream, const Statement& stmt);
1333 };
1334
1336 struct Plan
1337 {
1341 std::vector<Block> blocks;
1342 };
1343
1346 {
1350 size_t arity;
1352 std::vector<Location> path;
1354 std::vector<size_t> parameters;
1356 size_t result;
1358 std::vector<Block> blocks;
1361 };
1362 }
1363
1364 struct BundleDef;
1365
1367 typedef std::shared_ptr<BundleDef> Bundle;
1368
1371 {
1375 std::map<Location, Node> builtin_functions;
1377 std::map<Location, size_t> name_to_func;
1379 std::map<Location, size_t> name_to_plan;
1381 std::vector<bundle::Plan> plans;
1383 std::vector<bundle::Function> functions;
1385 std::vector<Location> strings;
1387 std::vector<Source> files;
1391 std::optional<size_t> query_plan;
1392
1395
1399 std::optional<size_t> find_plan(const Location& name) const;
1400
1404 std::optional<size_t> find_function(const Location& name) const;
1405
1409 bool is_function(const Location& name) const;
1410
1416 void save(std::ostream& stream) const;
1417
1423 void save(const std::filesystem::path& path) const;
1424
1432 static Bundle from_node(Node bundle);
1433
1440 static Bundle load(std::istream& stream);
1441
1448 static Bundle load(const std::filesystem::path& path);
1449 };
1450
1457 {
1458 public:
1460
1470
1478
1483
1487
1492
1495
1498 size_t stmt_limit() const;
1499
1505
1506 private:
1507 typedef std::vector<Node> Frame;
1508
1509 enum class Code
1510 {
1511 Break,
1512 Continue,
1513 Undefined,
1514 MultipleOutputs,
1515 Return,
1516 Timeout,
1517 Error
1518 };
1519
1520 class State
1521 {
1522 public:
1523 State(Node input, Node data, size_t num_locals);
1524 Node read_local(size_t index) const;
1525 void write_local(size_t index, Node value);
1526 bool is_defined(size_t key) const;
1527 void reset_local(size_t key);
1528 void add_result(Node node);
1529 const Nodes& result_set() const;
1530 bool is_in_call_stack(const Location& func_name) const;
1531 std::string_view root_function_name() const;
1532 void push_function(const Location& func_name, size_t num_args);
1533 void pop_function(const Location& func_name);
1534 const Nodes& errors() const;
1535 void add_error(Node error);
1536 void add_error_multiple_output(Node inst);
1537 void add_error_object_insert(Node inst);
1538 void put_function_result(const Location& func_name, Node result);
1539 Node get_function_result(const Location& func_name) const;
1540 bool in_with() const;
1541 void push_with();
1542 void pop_with();
1543 bool in_break() const;
1544 void push_break(size_t levels);
1545 void pop_break();
1546 size_t stmt_count() const;
1547 size_t inc_stmts();
1548
1549 private:
1550 Frame m_frame;
1551 Nodes m_errors;
1552 BuiltIns m_builtins;
1553 std::vector<Location> m_call_stack;
1554 std::vector<size_t> m_num_args;
1555 std::map<Location, Node> m_function_cache;
1556 Nodes m_result_set;
1557 size_t m_with_count;
1558 size_t m_break_count;
1559 size_t m_stmt_count;
1560 };
1561
1562 void run_plan(const bundle::Plan& plan, State& state) const;
1563 Code run_block(State& state, const bundle::Block& block) const;
1564 Code run_stmt(
1565 State& state, size_t index, const bundle::Statement& stmt) const;
1566 Code run_scan(State& state, const bundle::Statement& stmt) const;
1567 Code run_with(State& state, const bundle::Statement& stmt) const;
1568 Code run_call(
1569 State& state,
1570 const Location& func,
1571 const std::vector<bundle::Operand>& args,
1572 size_t target) const;
1573 Node dot(const Node& source, const Node& key) const;
1574 Node merge_objects(const Node& a, const Node& b) const;
1575 Node merge_sets(const Node& a, const Node& b) const;
1576 bool insert_into_object(
1577 const Node& a, const Node& key, const Node& value, bool once) const;
1578 Node to_term(const Node& value) const;
1579 Node unpack_operand(
1580 const State& state, const bundle::Operand& operand) const;
1581 Node write_and_swap(
1582 State& state,
1583 size_t key,
1584 const std::vector<size_t>& path,
1585 Node value) const;
1586
1587 Bundle m_bundle;
1588 BuiltIns m_builtins;
1589 TRegex m_int_regex;
1590 size_t m_stmt_limit;
1591 };
1592
1628 {
1629 Node m_node;
1630 std::string m_json;
1631
1632 public:
1636
1640 bool ok() const;
1641
1644 Node node() const;
1645
1649 size_t size() const;
1650
1654 Node expressions_at(size_t index) const;
1655
1659
1665 Node binding_at(size_t index, const std::string& name) const;
1666
1670 Node binding(const std::string& name) const;
1671
1674 const std::string& json() const;
1675
1681 std::vector<std::string> errors() const;
1682 };
1683
1697 {
1698 public:
1701
1708 Node add_module_file(const std::filesystem::path& path);
1709
1717 Node add_module(const std::string& name, const std::string& contents);
1718
1725 Node add_data_json_file(const std::filesystem::path& path);
1726
1733 Node add_data_json(const std::string& json);
1734
1740 Node add_data(const Node& node);
1741
1749 Node set_input_json_file(const std::filesystem::path& path);
1750
1758 Node set_input_json(const std::string& json);
1759
1765 Node set_input_term(const std::string& term);
1766
1773 Node set_input(const Node& node);
1774
1781 Node set_query(const std::string& query);
1782
1787 const std::initializer_list<std::string>& entrypoints);
1788
1792 Interpreter& entrypoints(const std::vector<std::string>& entrypoints);
1793
1796 const std::vector<std::string>& entrypoints() const;
1797
1800 std::vector<std::string>& entrypoints();
1801
1807 std::string query();
1808
1815 std::string query(const std::string& query_expr);
1816
1824 Node query_node(const std::string& query_expr);
1825
1833
1839 Output query_output(const std::string& query_expr);
1840
1847
1848 // clang-format off
1849
1877
1878 // clang-format on
1879
1891 Node save_bundle(const std::filesystem::path& dir, const Node& bundle);
1892
1901 Node load_bundle(const std::filesystem::path& dir);
1902
1912 Node query_bundle(const Bundle& bundle);
1913
1924 Node query_bundle(const Bundle& bundle, const std::string& endpoint);
1925
1931 Interpreter& debug_path(const std::filesystem::path& prefix);
1932
1935 const std::filesystem::path& debug_path() const;
1936
1944
1947 bool debug_enabled() const;
1948
1956
1959 bool wf_check_enabled() const;
1960
1967
1972 std::string output_to_string(const Node& output) const;
1973
1977
1982
1988 Interpreter& log_level(const std::string& level);
1989
1993 const std::string& c_error() const;
1994
1999 Interpreter& c_error(const std::string& error);
2000
2003 size_t stmt_limit() const;
2004
2010
2011 private:
2012 Reader& reader();
2013 Reader& json();
2014 Rewriter& data_from_json();
2015 Rewriter& input_from_json();
2016 Rewriter& to_input();
2017 Rewriter& bundle();
2018 Rewriter& write_bundle();
2019 Rewriter& read_bundle();
2020
2021 void merge(const Node& ast);
2022
2023 Node m_dataseq;
2024 Node m_moduleseq;
2025 Node m_input;
2026 Node m_query;
2027 std::vector<std::string> m_entrypoints;
2028 std::filesystem::path m_debug_path;
2029 bool m_debug_enabled;
2030 bool m_wf_check_enabled;
2031 LogLevel m_log_level;
2032
2033 BuiltIns m_builtins;
2034 std::unique_ptr<Reader> m_reader;
2035 std::unique_ptr<Reader> m_json;
2036 std::unique_ptr<Rewriter> m_data_from_json;
2037 std::unique_ptr<Rewriter> m_input_from_json;
2038 std::unique_ptr<Rewriter> m_to_input;
2039 std::unique_ptr<Rewriter> m_bundle;
2040 std::unique_ptr<Rewriter> m_write_bundle;
2041 std::unique_ptr<Rewriter> m_read_bundle;
2042 VirtualMachine m_vm;
2043 std::size_t m_data_count;
2044 std::map<std::string, Node> m_cache;
2045
2046 std::string m_c_error;
2047 };
2048
2052 LogLevel log_level_from_string(const std::string& value);
2053
2056 inline const auto RegoBundle = TokenDef("rego-bundle", flag::symtab);
2057 inline const auto Data = TokenDef("rego-data");
2058 inline const auto ModuleFile = TokenDef("rego-modulefile");
2059 inline const auto Static = TokenDef("rego-static");
2060 inline const auto BuiltInFunction = TokenDef("rego-builtinfunction");
2061 inline const auto Plan = TokenDef("rego-plan", flag::lookup | flag::symtab);
2062 inline const auto Block = TokenDef("rego-block");
2063 inline const auto Function =
2064 TokenDef("rego-function", flag::lookup | flag::symtab);
2065 inline const auto LocalIndex = TokenDef("rego-localindex", flag::print);
2066 inline const auto Operand = TokenDef("rego-operand");
2067 inline const auto Int32 = TokenDef("rego-int32", flag::print);
2068 inline const auto Int64 = TokenDef("rego-int64", flag::print);
2069 inline const auto UInt32 = TokenDef("rego-uint32", flag::print);
2070 inline const auto StringIndex = TokenDef("rego-stringindex", flag::print);
2071 inline const auto Boolean = TokenDef("rego-boolean", flag::print);
2072 inline const auto IRString = TokenDef("rego-irstring", flag::print);
2073 inline const auto IRQuery = TokenDef("rego-irquery");
2074 inline const auto IRPath = TokenDef("rego-irpath");
2075
2076 // sequences
2077 inline const auto BlockSeq = TokenDef("rego-blockseq");
2078 inline const auto ParameterSeq = TokenDef("rego-parameterseq");
2079 inline const auto PlanSeq = TokenDef("rego-planseq");
2080 inline const auto FunctionSeq = TokenDef("rego-functionseq");
2081 inline const auto BuiltInFunctionSeq = TokenDef("rego-builtinfunctionseq");
2082 inline const auto StringSeq = TokenDef("rego-stringseq");
2083 inline const auto PathSeq = TokenDef("rego-pathseq");
2084 inline const auto OperandSeq = TokenDef("rego-operandseq");
2085 inline const auto Int32Seq = TokenDef("rego-int32seq");
2086 inline const auto EntryPointSeq = TokenDef("rego-entrypointseq");
2087 inline const auto ModuleFileSeq = TokenDef("rego-modulefileseq");
2088
2089 // Statements
2090 inline const auto ArrayAppendStmt = TokenDef("rego-arrayappendstmt");
2091 inline const auto AssignIntStmt = TokenDef("rego-assignintstmt");
2092 inline const auto AssignVarOnceStmt = TokenDef("rego-assignvaroncestmt");
2093 inline const auto AssignVarStmt = TokenDef("rego-assignvarstmt");
2094 inline const auto BlockStmt = TokenDef("rego-blockstmt");
2095 inline const auto BreakStmt = TokenDef("rego-breakstmt");
2096 inline const auto CallDynamicStmt = TokenDef("rego-calldynamicstmt");
2097 inline const auto CallStmt = TokenDef("rego-callstmt");
2098 inline const auto DotStmt = TokenDef("rego-dotstmt");
2099 inline const auto EqualStmt = TokenDef("rego-equalstmt");
2100 inline const auto IsArrayStmt = TokenDef("rego-isarraystmt");
2101 inline const auto IsDefinedStmt = TokenDef("rego-isdefinedstmt");
2102 inline const auto IsObjectStmt = TokenDef("rego-isobjectstmt");
2103 inline const auto IsSetStmt = TokenDef("rego-issetstmt");
2104 inline const auto IsUndefinedStmt = TokenDef("rego-isundefinedstmt");
2105 inline const auto LenStmt = TokenDef("rego-lenstmt");
2106 inline const auto MakeArrayStmt = TokenDef("rego-makearraystmt");
2107 inline const auto MakeNullStmt = TokenDef("rego-makenullstmt");
2108 inline const auto MakeNumberIntStmt = TokenDef("rego-makenumberintstmt");
2109 inline const auto MakeNumberRefStmt = TokenDef("rego-makenumberrefstmt");
2110 inline const auto MakeObjectStmt = TokenDef("rego-makeobjectstmt");
2111 inline const auto MakeSetStmt = TokenDef("rego-makesetstmt");
2112 inline const auto NotEqualStmt = TokenDef("rego-notequalstmt");
2113 inline const auto NotStmt = TokenDef("rego-notstmt");
2114 inline const auto ObjectInsertOnceStmt =
2115 TokenDef("rego-objectinsertoncestmt");
2116 inline const auto ObjectInsertStmt = TokenDef("rego-objectinsertstmt");
2117 inline const auto ObjectMergeStmt = TokenDef("rego-objectmergestmt");
2118 inline const auto ResetLocalStmt = TokenDef("rego-resetlocalstmt");
2119 inline const auto ResultSetAddStmt = TokenDef("rego-resultsetaddstmt");
2120 inline const auto ReturnLocalStmt = TokenDef("rego-returnlocalstmt");
2121 inline const auto ScanStmt = TokenDef("rego-scanstmt");
2122 inline const auto SetAddStmt = TokenDef("rego-setaddstmt");
2123 inline const auto WithStmt = TokenDef("rego-withstmt");
2124
2125 // other tokens
2126 inline const auto Blocks = TokenDef("rego-blocks");
2127 inline const auto Func = TokenDef("rego-func");
2128 inline const auto Capacity = TokenDef("rego-capacity");
2129 inline const auto Stmt = TokenDef("rego-stmt");
2130
2131 inline const auto wf_ir_statements = ArrayAppendStmt | AssignIntStmt |
2139
2140 // clang-format off
2141 inline const auto wf_bundle =
2142 builtins::wf_decl
2143 | wf_result
2144 | (Top <<= RegoBundle)
2146 | (ModuleFileSeq <<= ModuleFile++)
2147 | (ModuleFile <<= (Name >>= IRString) * (Contents >>= IRString))
2148 | (Data <<= rego::Object)
2150 | (IRQuery <<= (IRString|Undefined))
2152 | (StringSeq <<= IRString++)
2154 | (BuiltInFunction <<= (Name >>= IRString) * builtins::Decl)
2155 | (PathSeq <<= IRString++)
2156 | (PlanSeq <<= Plan++[1])
2157 | (Plan <<= (Name >>= IRString) * BlockSeq)
2158 | (BlockSeq <<= Block++)
2159 | (Block <<= wf_ir_statements++)
2160 | (FunctionSeq <<= Function++)
2161 | (Function <<= (Name >>= IRString) * IRPath * ParameterSeq * (Return >>= LocalIndex) * BlockSeq)[Name]
2162 | (IRPath <<= IRString++[1])
2163 | (ParameterSeq <<= LocalIndex++)
2164 | (ArrayAppendStmt <<= (Array >>= LocalIndex) * (Val >>= Operand))
2165 | (AssignIntStmt <<= (Val >>= Int64) * (Target >>= LocalIndex))
2166 | (AssignVarOnceStmt <<= (Src >>= Operand) * (Target >>= LocalIndex))
2167 | (AssignVarStmt <<= (Src >>= Operand) * (Target >>= LocalIndex))
2168 | (BlockStmt <<= (Blocks >>= BlockSeq))
2169 | (BreakStmt <<= (Idx >>= UInt32))
2170 | (CallDynamicStmt <<= (Func >>= OperandSeq) * (Args >>= OperandSeq) * (Result >>= LocalIndex))
2171 | (CallStmt <<= (Func >>= IRString) * (Args >>= OperandSeq) * (Result >>= LocalIndex))
2172 | (DotStmt <<= (Src >>= Operand) * (Key >>= Operand) * (Target >>= LocalIndex))
2173 | (EqualStmt <<= (Lhs >>= Operand) * (Rhs >>= Operand))
2174 | (IsArrayStmt <<= (Src >>= Operand))
2175 | (IsDefinedStmt <<= (Src >>= LocalIndex))
2176 | (IsObjectStmt <<= (Src >>= Operand))
2177 | (IsSetStmt <<= (Src >>= Operand))
2178 | (IsUndefinedStmt <<= (Src >>= LocalIndex))
2179 | (LenStmt <<= (Src >>= Operand) * (Target >>= LocalIndex))
2180 | (MakeArrayStmt <<= (Capacity >>= Int32) * (Target >>= LocalIndex))
2181 | (MakeNullStmt <<= (Target >>= LocalIndex))
2182 | (MakeNumberIntStmt <<= (Val >>= Int64) * (Target >>= LocalIndex))
2183 | (MakeNumberRefStmt <<= (Idx >>= Int32) * (Target >>= LocalIndex))
2184 | (MakeObjectStmt <<= (Target >>= LocalIndex))
2185 | (MakeSetStmt <<= (Target >>= LocalIndex))
2186 | (NotEqualStmt <<= (Lhs >>= Operand) * (Rhs >>= Operand))
2187 | (NotStmt <<= Block)
2188 | (ObjectInsertOnceStmt <<= (Key >>= Operand) * (Val >>= Operand) * (Object >>= LocalIndex))
2189 | (ObjectInsertStmt <<= (Key >>= Operand) * (Val >>= Operand) * (Object >>= LocalIndex))
2190 | (ObjectMergeStmt <<= (Lhs >>= LocalIndex) * (Rhs >>= LocalIndex) * (Target >>= LocalIndex))
2191 | (ResetLocalStmt <<= (Target >>= LocalIndex))
2192 | (ResultSetAddStmt <<= (Val >>= LocalIndex))
2193 | (ReturnLocalStmt <<= (Src >>= LocalIndex))
2194 | (ScanStmt <<= (Src >>= LocalIndex) * (Key >>= LocalIndex) * (Val >>= LocalIndex) * Block)
2195 | (SetAddStmt <<= (Val >>= Operand) * (Set >>= LocalIndex))
2196 | (WithStmt <<= LocalIndex * (Path >>= Int32Seq) * (Val >>= Operand) * Block)
2197 | (Operand <<= LocalIndex | Boolean | StringIndex)
2198 | (OperandSeq <<= Operand++)
2199 | (Int32Seq <<= Int32++)
2200 ;
2201 // clang-format on
2203
2206
2209
2212
2215
2218
2221
2224
2227}
Big Integer implemention based on strings.
Definition rego.hh:244
friend BigInt operator+(const BigInt &lhs, const BigInt &rhs)
Adds two BigInts.
std::optional< std::size_t > to_size() const
Attempts to convert the BigInt to a size_t integer.
friend BigInt operator*(const BigInt &lhs, const BigInt &rhs)
Multiplies two BigInts.
friend bool operator<(const BigInt &lhs, const BigInt &rhs)
Compares two BigInts for less-than.
friend bool operator>(const BigInt &lhs, const BigInt &rhs)
Compares two BigInts for greater-than.
std::optional< std::int64_t > to_int() const
Attempts to convert the BigInt to a 64-bit integer.
friend BigInt operator-(const BigInt &lhs, const BigInt &rhs)
Subtracts two BigInts.
BigInt negate() const
Negates the BigInt.
friend bool operator!=(const BigInt &lhs, const BigInt &rhs)
Compares two BigInts for inequality.
bool is_negative() const
Checks if the BigInt is negative.
friend bool operator<=(const BigInt &lhs, const BigInt &rhs)
Compares two BigInts for less-than-or-equal.
static bool is_int(const Location &loc)
Checks if a Location represents a valid integer string.
friend BigInt operator%(const BigInt &lhs, const BigInt &rhs)
Computes the remainder of dividing two BigInts.
bool is_zero() const
Checks if the BigInt is zero.
friend bool operator==(const BigInt &lhs, const BigInt &rhs)
Compares two BigInts for equality.
BigInt increment() const
Increments the BigInt by one.
BigInt(std::int64_t value)
Constructs a BigInt from a 64-bit integer.
BigInt()
Default constructor, initializes to zero.
BigInt(const Location &value)
Constructs a BigInt from a Location representing a arbitrary precision integer string.
const Location & loc() const
Gets the Location representing the integer string.
friend BigInt operator/(const BigInt &lhs, const BigInt &rhs)
Divides two BigInts.
BigInt decrement() const
Decrements the BigInt by one.
friend std::ostream & operator<<(std::ostream &os, const BigInt &value)
Outputs a BigInt to a stream.
BigInt abs() const
Gets the absolute value of the BigInt.
friend bool operator>=(const BigInt &lhs, const BigInt &rhs)
Compares two BigInts for greater-than-or-equal.
Manages the set of builtins used by an interpreter to resolve built-in calls.
Definition rego.hh:874
static std::shared_ptr< BuiltInsDef > create()
Creates the standard builtin set.
bool is_builtin(const Location &name)
Determines whether the provided name refers to a built-in.
bool is_deprecated(const Location &version, const Location &name) const
Determines whether the provided builtin name is deprecated in the provided version.
bool strict_errors() const
Whether to throw built-in errors.
Node call(const Location &name, const Location &version, const Nodes &args)
Calls the built-in with the provided name and arguments.
BuiltInsDef & blacklist(const std::initializer_list< T > &forbidden)
Sets a blacklist of built-in names that are forbidden from being loaded.
Definition rego.hh:988
void clear()
Called to clear any persistent state or caching.
BuiltInsDef & allow_all()
Allow all built-ins to be loaded from the standard library.
BuiltInsDef & register_builtins(const T &built_ins)
Registers a set of built-ins.
Definition rego.hh:934
BuiltInsDef & register_standard_builtins()
This method no longer needs to be called.
BuiltInsDef & whitelist(T begin, T end)
Sets a whitelist of built-in names that are allowed to be loaded.
Definition rego.hh:972
BuiltInsDef & blacklist(T begin, T end)
Sets a blacklist of built-in names that are forbidden from being loaded.
Definition rego.hh:1006
BuiltInsDef & whitelist(const std::initializer_list< T > &allowed)
Sets a whitelist of built-in names that are allowed to be loaded.
Definition rego.hh:955
BuiltIn at(const Location &name)
Gets the built-in with the provided name.
BuiltInsDef() noexcept
Constructor.
BuiltInsDef & register_builtin(const BuiltIn &built_in)
Registers a built-in.
Node decl(const Location &name)
Gets the declaration node for the specified built-in.
This class forms the main interface to the Rego library.
Definition rego.hh:1697
Node query_bundle(const Bundle &bundle)
Performs a query against a bundle.
Interpreter & debug_path(const std::filesystem::path &prefix)
The path to the debug directory.
std::string query(const std::string &query_expr)
Executes a query against the interpreter.
Node add_module(const std::string &name, const std::string &contents)
Adds a module (i.e. virtual document) to the interpreter.
const std::filesystem::path & debug_path() const
Gets the debug path.
Node set_input_term(const std::string &term)
Sets the input term of the interpreter.
std::string query()
Executes the documents against the interpreter.
Node add_data_json_file(const std::filesystem::path &path)
Adds a base document to the interpreter.
Interpreter & stmt_limit(size_t stmt_limit)
Sets the maximum number of statements that will execute before a timeout.
Node set_input_json_file(const std::filesystem::path &path)
Sets the input document to the interpreter.
Interpreter & entrypoints(const std::initializer_list< std::string > &entrypoints)
Sets the entrypoints to include when building a bundle.
Node save_bundle(const std::filesystem::path &dir, const Node &bundle)
Saves a bundle to a directory in JSON format.
Node query_bundle(const Bundle &bundle, const std::string &endpoint)
Performs a query against a bundle.
LogLevel log_level() const
Returns the current log level of this interpreter.
Node set_input_json(const std::string &json)
Sets the input document to the interpreter.
bool wf_check_enabled() const
Checks if well-formedness checks are enabled.
Interpreter & log_level(LogLevel level)
Sets the log level of the interpreter.
Output query_output(const std::string &query_expr)
Executes a query against the interpreter.
Node set_input(const Node &node)
Sets the input document to the interpreter.
BuiltIns builtins() const
The built-ins used by the interpreter.
std::vector< std::string > & entrypoints()
Gets the entrypoints to include when building a bundle.
std::string output_to_string(const Node &output) const
Converts an output node into a human-readable string.
Interpreter & c_error(const std::string &error)
Sets the most recent error message.
Node add_data_json(const std::string &json)
Adds a base document to the interpreter.
Interpreter()
Constructor.
Output query_output()
Executes a query against the interpreter.
Node query_node()
Executes a query against the interpreter.
Interpreter & log_level(const std::string &level)
Sets the logging level for the interpreter from a string.
const std::vector< std::string > & entrypoints() const
Gets the entrypoints to include when building a bundle.
Node query_node(const std::string &query_expr)
Executes a query against the interpreter.
Interpreter & wf_check_enabled(bool enabled)
Sets whether well-formedness checks are enabled.
Node load_bundle(const std::filesystem::path &dir)
Loads a bundle in JSON format from a direction.
Interpreter & entrypoints(const std::vector< std::string > &entrypoints)
Sets the entrypoints to include when building a bundle.
Node build()
Builds a bundle from the current state of the interpreter.
size_t stmt_limit() const
Gets the maximum number of statements that will execute before a timeout.
bool debug_enabled() const
Checks if debug mode is enabled.
Node add_data(const Node &node)
Adds a base document to the interpreter.
Interpreter & debug_enabled(bool enabled)
Sets whether debug mode is enabled.
const std::string & c_error() const
Returns a string representing the most recent error message.
Node add_module_file(const std::filesystem::path &path)
Adds a module (i.e. virtual document) file to the interpreter.
Node set_query(const std::string &query)
Sets the query expression of the interpreter.
Encapsulates the output of a Rego query.
Definition rego.hh:1628
Node binding_at(size_t index, const std::string &name) const
Gets the binding for the specified name at the specified result index.
const std::string & json() const
Gets the JSON representation of the output.
std::vector< std::string > errors() const
Gets the errors in the output.
size_t size() const
Gets the number of results.
Node expressions_at(size_t index) const
Gets the expressions for the result at the specified index.
Node binding(const std::string &name) const
Gets the binding for the specified name at the first result.
Node node() const
Gets the underlying node.
Node expressions() const
Gets the expressions for the first result.
Output(Node node)
Constructor.
bool ok() const
Whether the Output is OK (i.e., has not resulted in one or more errors)
Options for unwrapping an argument.
Definition rego.hh:420
bool exclude_got() const
Whether the statement indicating what was received instead of the expected type should be excluded.
const std::string & func() const
The name of the function. If provide, will be a prefix on the message as "<func-name>:".
const Token & type() const
The singular type to match against.
UnwrapOpt & type(const Token &value)
Sets the singular type to match against.
UnwrapOpt & pre(const std::string &value)
Sets the error preamble.
UnwrapOpt & exclude_got(bool exclude_got)
Sets whether to exclude the "got" statement in the error message.
UnwrapOpt & specify_number(bool specify_number)
Sets whether to specify in the error message which kind of number was received.
UnwrapOpt(std::size_t index)
Construct an UnwrapOpt.
bool specify_number() const
Whether to specify in the error message which kind of number was received (i.e. integer or floating p...
UnwrapOpt & code(const std::string &value)
Sets the error code for the error message.
const std::string & pre() const
The error preamble. If omitted, a default preamble will be constructed from the operation metadata in...
const std::string & code() const
The error code for the error message. Default value if omitted is EvalTypeError.
const std::string & message() const
The full error message. If this is set, no message will be generated and instead this will be returne...
Node unwrap(const Nodes &args) const
Unwraps an argument from the provided vector of nodes.
UnwrapOpt & message(const std::string &value)
Sets the full error message. If this is set, no message will be generated and instead this will be re...
UnwrapOpt & func(const std::string &value)
Sets the name of the function.
UnwrapOpt & types(const std::vector< Token > &value)
Sets the types to match against.
const std::vector< Token > & types() const
The types to match against. The operand must be one of the provided types or else an error node will ...
This class implements a virtual machine that can execute compiled Rego bundles.
Definition rego.hh:1457
BuiltIns builtins() const
Gets the built-in functions used during execution.
VirtualMachine & stmt_limit(size_t stmt_limit)
Sets the maximum number of statements that will execute before a timeout.
VirtualMachine & bundle(Bundle bundle)
Sets the bundle to use during execution.
Node run_query(Node input) const
Executes the query plan in the bundle with the provided input.
Bundle bundle() const
Gets the bundle used during execution.
VirtualMachine & builtins(BuiltIns builtins)
Sets the built-in functions to use during execution.
size_t stmt_limit() const
Gets the maximum number of statements that will execute before a timeout.
Node run_entrypoint(const Location &entrypoint, Node input) const
Executes the entrypoint plan in the bundle with the provided input.
OperandType
The type of an operand.
Definition rego.hh:1126
StatementType
The type of an IR statement.
Definition rego.hh:1192
std::vector< Statement > Block
A block of statements.
Definition rego.hh:1232
Definition rego.hh:18
SetFormat
Controls how sets are rendered by to_key().
Definition rego.hh:1086
@ Angle
Angle brackets: <1, 2, 3> (internal key representation).
@ Rego
Curly braces / set(): {1, 2, 3} or set() (OPA Rego display format).
@ Square
Square brackets: [1, 2, 3] (JSON-compatible array format).
bool get_bool(const Node &node)
Extracts the value of a node as a boolean.
std::optional< Node > try_get_item(const Node &node, const std::string_view &key)
Tries to get an item within an object using its key.
Node scalar()
Creates a null scalar.
std::optional< bool > try_get_bool(const Node &node)
Attempts to extract the value of a node as a boolean.
std::optional< double > try_get_double(const Node &node)
Attempts to extract the value of a node as an 64-bit floating point number.
Node null()
Creates a null scalar.
std::shared_ptr< BuiltInDef > BuiltIn
A pointer to a BuiltInDef.
Definition rego.hh:229
Node object_item(const Node &key_term, const Node &val_term)
Converts the key and val terms to an object item.
Node array(const std::initializer_list< Node > &array_members)
Converts the value to an array node.
BigInt get_int(const Node &node)
Extracts the value of a node as an integer.
double get_double(const Node &node)
Extracts the value of a node as an double.
Node unwrap_arg(const Nodes &args, const UnwrapOpt &options)
Unwraps an argument from the provided vector of nodes.
Rewriter json_to_bundle()
Rewrites an OPA bundle JSON to a Bundle AST.
Node err(NodeRange &r, const std::string &msg, const std::string &code=UnknownError)
Generates an error node.
std::optional< BigInt > try_get_int(const Node &node)
Attempts to extract the value of a node as an integer. In the case that the node is a double,...
std::function< Node(const Nodes &)> BuiltInBehavior
The function pointer to the behavior of the built-in.
Definition rego.hh:232
Reader file_to_rego()
Parses Rego queries and virtual documents.
Rewriter bundle_to_json()
Rewrites a Bundle AST to a JSON AST in OPA bundle JSON format.
std::optional< std::string > try_get_string(const Node &node)
Attempts to extract the value of a node as a string.
Rewriter rego_to_bundle(BuiltIns builtins=BuiltInsDef::create())
Rewrites a Rego AST to a Bundle AST.
std::shared_ptr< BundleDef > Bundle
A pointer to a BundleDef.
Definition rego.hh:1367
std::string_view get_raw_string(const Node &node)
Returns the raw location of the node from the source.
Node version()
Returns a node representing the version of the library.
UnwrapResult unwrap(const Node &term, const Token &type)
Attempts to unwrap a node to a specified type.
LogLevel log_level_from_string(const std::string &value)
Converts a string to a log level (case insensitive).
Node number(double value)
Converts the value to a scalar node.
Node string(const char *value)
Converts the value to a scalar node.
LogLevel
The logging level.
Definition rego.hh:1110
Rewriter rego_to_input()
Rewrites a Query AST to an input term.
Node set(const std::initializer_list< Node > &set_members)
Converts the value to a set node.
Rewriter json_to_rego(bool as_term=false)
Rewrites a JSON AST to a Rego data input AST.
std::string get_string(const Node &node)
Extracts the value of a node as a string.
std::string to_key(const trieste::Node &node, SetFormat set_format=SetFormat::Angle, bool sort_arrays=false, const char *list_delim=",")
Converts a node to a unique key representation that can be used for comparison.
Rewriter rego_to_yaml()
Rewrites a Rego binding term to a YAML AST.
Rewriter rego_to_json()
Rewrites a Rego binding term to a JSON AST.
Node boolean(bool value)
Converts the value to a scalar node.
Node object(const std::initializer_list< Node > &object_items)
Converts the value to an object node.
uint_least32_t regoEnum
Enum type.
Definition rego_c.h:32
Struct which defines a built-in function.
Definition rego.hh:793
bool available
Whether the builtin is available.
Definition rego.hh:811
Node decl
The declaration node which adheres to the builtins::wf_decl well-formedness definition.
Definition rego.hh:800
static BuiltIn create(const Location &name, size_t arity, BuiltInBehavior behavior)
Creates a new built-in.
virtual void clear()
Called to clear any persistent state or caching.
static BuiltIn placeholder(const Location &name, Node decl, const std::string &message)
Creates a placeholder for a built-in which is not available on this platform.
BuiltInDef(Location name_, Node decl_, BuiltInBehavior behavior_, bool available_)
Constructor.
BuiltInBehavior behavior
The function which will be called when the built-in is evaluated.
Definition rego.hh:808
static BuiltIn create(const Location &name, Node decl, BuiltInBehavior behavior)
Creates a new built-in.
std::size_t arity
The number of expected arguments.
Definition rego.hh:805
Location name
The name used to match against expression calls in the rego program.
Definition rego.hh:796
Represents a compiled Rego bundle.
Definition rego.hh:1371
std::map< Location, size_t > name_to_plan
Map from function names to their indices.
Definition rego.hh:1379
std::vector< bundle::Function > functions
The functions in the bundle.
Definition rego.hh:1383
std::map< Location, size_t > name_to_func
Map from plan names to their indices.
Definition rego.hh:1377
static Bundle load(const std::filesystem::path &path)
Loads a bundle from a file.
std::vector< Location > strings
The string table for the bundle.
Definition rego.hh:1385
std::vector< Source > files
The module source files which were compiled into the bundle.
Definition rego.hh:1387
static Bundle from_node(Node bundle)
Constructs a bundle from an AST node.
std::vector< bundle::Plan > plans
The plans in the bundle.
Definition rego.hh:1381
void save(const std::filesystem::path &path) const
Saves the bundle to a file.
Source query
The query, if one was included.
Definition rego.hh:1394
Node data
The merged base data document.
Definition rego.hh:1373
std::optional< size_t > find_function(const Location &name) const
Finds a function by name.
std::optional< size_t > find_plan(const Location &name) const
Finds a plan by name.
std::map< Location, Node > builtin_functions
The built-in functions required by the bundle.
Definition rego.hh:1375
static Bundle load(std::istream &stream)
Loads a bundle from a stream.
size_t local_count
The number of local variables required by the bundle.
Definition rego.hh:1389
std::optional< size_t > query_plan
The index of the query plan, if one was included.
Definition rego.hh:1391
bool is_function(const Location &name) const
Determines whether the provided name refers to a function.
void save(std::ostream &stream) const
Saves the bundle to a stream.
Result of unwrapping a node.
Definition rego.hh:395
bool success
True if the argument was unwrapped successfully.
Definition rego.hh:400
Node node
The unwrapped argument or nullptr (if unsuccessful).
Definition rego.hh:397
Additional information for CallDynamic statements.
Definition rego.hh:1245
std::vector< Operand > ops
The arguments to the function.
Definition rego.hh:1249
std::vector< Operand > path
The path to the function being called.
Definition rego.hh:1247
Additional information for Call statements.
Definition rego.hh:1236
std::vector< Operand > ops
The arguments to the function.
Definition rego.hh:1240
Location func
The function being called.
Definition rego.hh:1238
Represents a function in the IR.
Definition rego.hh:1346
std::vector< size_t > parameters
The local indices of the function parameters.
Definition rego.hh:1354
std::vector< Block > blocks
The blocks which make up the function.
Definition rego.hh:1358
Location name
The name of the function.
Definition rego.hh:1348
size_t arity
The arity of the function.
Definition rego.hh:1350
size_t result
The index of the result local.
Definition rego.hh:1356
std::vector< Location > path
The path of the function (the name broken into segments)
Definition rego.hh:1352
bool cacheable
Whether the function result can be cached.
Definition rego.hh:1360
Represents an operand in the IR.
Definition rego.hh:1146
size_t index
A local index (if type is Local, String, or Index).
Definition rego.hh:1154
std::int64_t value
An integer value (if type is Value).
Definition rego.hh:1152
OperandType type
The type of the operand.
Definition rego.hh:1148
Operand()
Constructs an Operand with type None.
static Operand from_op(const Node &n)
Constructs an Operand from the specified node.
friend std::ostream & operator<<(std::ostream &stream, const Operand &op)
Writes the operand to a stream (used for debugging purposes).
static Operand from_index(const Node &n)
Constructs an Operand from the specified node. Will have a type of Index.
static Operand from_value(const Node &n)
Constructs an Operand from the specified node. Will have a type of Value.
Represents a plan in the IR.
Definition rego.hh:1337
Location name
The name of the plan.
Definition rego.hh:1339
std::vector< Block > blocks
The blocks which make up the plan.
Definition rego.hh:1341
Additional information for Call, CallDynamic, With, Block, Not, and Scan statements.
Definition rego.hh:1264
const WithExt & with() const
Returns this extension as a WithExt.
const CallDynamicExt & call_dynamic() const
Returns this extension as a CallDynamicExt.
std::variant< CallExt, CallDynamicExt, WithExt, std::vector< Block >, Block > contents
The contents of the extension.
Definition rego.hh:1267
StatementExt(CallExt &&ext)
Constructs a StatementExt from a CallExt.
const std::vector< Block > & blocks() const
Returns this extension as a vector of Blocks.
const Block & block() const
Returns this extension as a Block.
StatementExt(Block &&block)
Constructs a StatementExt from a Block.
const CallExt & call() const
Returns this extension as a CallExt.
StatementExt(WithExt &&ext)
Constructs a StatementExt from a WithExt.
StatementExt(std::vector< Block > &&blocks)
Constructs a StatementExt from a vector of Blocks.
StatementExt(CallDynamicExt &&ext)
Constructs a StatementExt from a CallDynamicExt.
Represents a single IR statement.
Definition rego.hh:1306
std::int32_t target
The target of the statement.
Definition rego.hh:1319
StatementType type
The type of statement.
Definition rego.hh:1308
std::shared_ptr< const StatementExt > ext
The (optional) extended information for the statement.
Definition rego.hh:1322
Location location
The location of the statement in the source document.
Definition rego.hh:1310
friend std::ostream & operator<<(std::ostream &stream, const Statement &stmt)
Writes the statement to a stream (used for debugging purposes)
Operand op1
The second operand of the statement.
Definition rego.hh:1316
Statement()
Default constructor.
Operand op0
The first operand of the statement.
Definition rego.hh:1313
Additional information for With statements.
Definition rego.hh:1254
std::vector< size_t > path
The path to the value being replaced.
Definition rego.hh:1256
Block block
The block to execute with the replacement.
Definition rego.hh:1258