rego-cpp 1.2.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 Int = TokenDef("rego-INT", flag::print);
64 inline const auto Float = TokenDef("rego-FLOAT", flag::print);
65 inline const auto True = TokenDef("rego-true");
66 inline const auto False = TokenDef("rego-false");
67 inline const auto Null = TokenDef("rego-null");
68 inline const auto Equals = TokenDef("rego-equals");
69 inline const auto NotEquals = TokenDef("rego-notequals");
70 inline const auto LessThan = TokenDef("rego-lessthan");
71 inline const auto GreaterThan = TokenDef("rego-greaterthan");
72 inline const auto LessThanOrEquals = TokenDef("rego-lessthanorequals");
73 inline const auto GreaterThanOrEquals = TokenDef("rego-greaterthanorequals");
74 inline const auto Add = TokenDef("rego-add");
75 inline const auto Subtract = TokenDef("rego-subtract");
76 inline const auto Multiply = TokenDef("rego-multiply");
77 inline const auto Divide = TokenDef("rego-divide");
78 inline const auto Modulo = TokenDef("rego-modulo");
79 inline const auto And = TokenDef("rego-and");
80 inline const auto Or = TokenDef("rego-or");
81 inline const auto Assign = TokenDef("rego-assign");
82 inline const auto Unify = TokenDef("rego-unify");
83 inline const auto Default = TokenDef("rego-default");
84 inline const auto Some = TokenDef("rego-some");
85 inline const auto SomeDecl = TokenDef("rego-somedecl");
86 inline const auto If = TokenDef("rego-if");
87 inline const auto IsIn = TokenDef("rego-in");
88 inline const auto Contains = TokenDef("rego-contains");
89 inline const auto Else = TokenDef("rego-else");
90 inline const auto As = TokenDef("rego-as");
91 inline const auto With = TokenDef("rego-with");
92 inline const auto Every = TokenDef("rego-every");
93 inline const auto ArrayCompr = TokenDef("rego-arraycompr", flag::symtab);
94 inline const auto ObjectCompr = TokenDef("rego-objectcompr", flag::symtab);
95 inline const auto SetCompr = TokenDef("rego-setcompr", flag::symtab);
96 inline const auto Membership = TokenDef("rego-membership");
97 inline const auto Not = TokenDef("rego-not");
98 inline const auto Import =
99 TokenDef("rego-import", flag::lookdown | flag::lookup | flag::shadowing);
100 inline const auto Placeholder = TokenDef("rego-placeholder");
101 inline const auto Version = TokenDef("rego-version", flag::print);
102
103 // intermediate tokens
104 inline const auto RuleBodySeq = TokenDef("rego-rulebodyseq");
105 inline const auto ImportSeq = TokenDef("rego-importseq");
106 inline const auto RuleRef = TokenDef("rego-ruleref");
107 inline const auto RuleHeadType = TokenDef("rego-ruleheadtype");
108 inline const auto WithSeq = TokenDef("rego-withseq");
109 inline const auto TermSeq = TokenDef("rego-termseq");
110 inline const auto ExprSeq = TokenDef("rego-exprseq");
111 inline const auto VarSeq = TokenDef("rego-varseq");
112 inline const auto RefHead = TokenDef("rego-refhead");
113 inline const auto RefArgSeq = TokenDef("rego-refargseq");
114 inline const auto Key = TokenDef("rego-key", flag::print);
115 inline const auto Val = TokenDef("rego-value");
116 inline const auto Undefined = TokenDef("rego-undefined");
117 inline const auto Name = TokenDef("rego-name");
118 inline const auto Return = TokenDef("rego-return");
119 inline const auto Target = TokenDef("rego-target");
120 inline const auto Lhs = TokenDef("rego-lhs");
121 inline const auto Rhs = TokenDef("rego-rhs");
122 inline const auto Src = TokenDef("rego-src");
123 inline const auto Args = TokenDef("rego-args");
124 inline const auto Idx = TokenDef("rego-idx");
125 inline const auto Row = TokenDef("rego-row");
126 inline const auto Col = TokenDef("rego-col");
127
128 // other tokens
129 inline const auto Results = TokenDef("rego-results", flag::symtab);
130 inline const auto Result = TokenDef("rego-result", flag::symtab);
131 inline const auto Bindings = TokenDef("rego-bindings");
132 inline const auto Terms = TokenDef("rego-terms");
133 inline const auto Binding = TokenDef("rego-binding", flag::lookdown);
134 inline const auto ErrorCode = TokenDef("rego-errorcode");
135 inline const auto ErrorSeq = TokenDef("rego-errorseq");
136 inline const auto Line = TokenDef("rego-line", flag::print);
137
138 inline const auto wf_assign_op = Assign | Unify;
139 inline const auto wf_arith_op = Add | Subtract | Multiply | Divide | Modulo;
140 inline const auto wf_bin_op = And | Or | Subtract;
141 inline const auto wf_bool_op = Equals | NotEquals | LessThan |
142 LessThanOrEquals | GreaterThan | GreaterThanOrEquals | Not;
143 inline const auto wf_exprs =
144 Term | ExprCall | ExprInfix | ExprEvery | ExprParens | UnaryExpr;
145
146 // clang-format off
147 inline const auto wf =
148 (Top <<= Query | Module)
149 | (Module <<= Package * Version * ImportSeq * Policy)
150 | (ImportSeq <<= Import++)
151 | (Import <<= Ref * Var)
152 | (Package <<= Ref)
153 | (Policy <<= Rule++)
154 | (Rule <<= (Default >>= True | False) * RuleHead * RuleBodySeq)
155 | (RuleHead <<= RuleRef * (RuleHeadType >>= (RuleHeadSet | RuleHeadObj | RuleHeadFunc | RuleHeadComp)))
156 | (RuleRef <<= Var | Ref)
157 | (RuleHeadComp <<= Expr)
158 | (RuleHeadObj <<= Expr * Expr)
159 | (RuleHeadFunc <<= RuleArgs * Expr)
160 | (RuleHeadSet <<= Expr)
161 | (RuleArgs <<= Term++)
162 | (RuleBodySeq <<= (Else | Query)++)
163 | (Else <<= Expr * Query)
164 | (Query <<= Literal++)
165 | (Literal <<= (Expr >>= SomeDecl | Expr | NotExpr) * WithSeq)
166 | (WithSeq <<= With++)
167 | (With <<= Term * Expr)
168 | (SomeDecl <<= ExprSeq * (IsIn >>= Expr | Undefined))
169 | (NotExpr <<= Expr)
170 | (Expr <<= (Term | ExprCall | ExprInfix | ExprEvery | ExprParens | UnaryExpr))
171 | (ExprCall <<= Ref * ExprSeq)
172 | (ExprSeq <<= Expr++)
173 | (ExprInfix <<= Expr * InfixOperator * Expr)
174 | (ExprEvery <<= VarSeq * (IsIn >>= Term | ExprCall | ExprInfix) * Query)
175 | (VarSeq <<= Var++[1])
176 | (ExprParens <<= Expr)
177 | (UnaryExpr <<= Expr)
178 | (Membership <<= ExprSeq * Expr)
179 | (Term <<= Ref | Var | Scalar | Array | Object | Set | Membership | ArrayCompr | ObjectCompr | SetCompr)
180 | (ArrayCompr <<= Expr * Query)
181 | (SetCompr <<= Expr * Query)
182 | (ObjectCompr <<= Expr * Expr * Query)
183 | (InfixOperator <<= AssignOperator | BoolOperator | ArithOperator | BinOperator)
184 | (BoolOperator <<= Equals | NotEquals | LessThan | GreaterThan | LessThanOrEquals | GreaterThanOrEquals)
185 | (ArithOperator <<= Add | Subtract | Multiply | Divide | Modulo)
186 | (BinOperator <<= And | Or)
187 | (AssignOperator <<= Assign | Unify)
188 | (Ref <<= RefHead * RefArgSeq)
189 | (RefHead <<= Var | Array | Object | Set | ArrayCompr | ObjectCompr | SetCompr | ExprCall)
190 | (RefArgSeq <<= (RefArgDot | RefArgBrack)++)
191 | (RefArgBrack <<= Expr | Placeholder)
192 | (RefArgDot <<= Var)
193 | (Scalar <<= String | Int | Float | True | False | Null)
194 | (String <<= JSONString | RawString)
195 | (Array <<= Expr++)
196 | (Object <<= ObjectItem++)
197 | (ObjectItem <<= (Key >>= Expr) * (Val >>= Expr))
198 | (Set <<= Expr++)
199 ;
200 // clang-format on
201
202 // clang-format off
203 inline const auto wf_result =
204 (Top <<= Results | Undefined)
205 | (Results <<= Result++[1])
206 | (Result <<= Terms * Bindings)
207 | (Terms <<= Term++)
208 | (Bindings <<= Binding++)
209 | (Binding <<= (Key >>= Var) * (Val >>= Term))[Key]
210 | (Term <<= Scalar | Array | Object | Set)
211 | (Array <<= Term++)
212 | (Set <<= Term++)
213 | (Object <<= ObjectItem++)
214 | (ObjectItem <<= (Key >>= Term) * (Val >>= Term))
215 | (Scalar <<= JSONString | Int | Float | True | False | Null)
216 | (Error <<= ErrorMsg * ErrorAst * ErrorCode)
217 ;
218 // clang-format on
219
221
222 struct BuiltInDef;
223
225 using BuiltIn = std::shared_ptr<BuiltInDef>;
226
228 using BuiltInBehavior = std::function<Node(const Nodes&)>;
229
232 // This is a basic, non-optimized implementation of a big integer
239 class BigInt
240 {
241 public:
247 BigInt(const Location& value);
250 BigInt(std::int64_t value);
251
254 const Location& loc() const;
258 std::optional<std::int64_t> to_int() const;
262 std::optional<std::size_t> to_size() const;
263
266 bool is_negative() const;
267
270 bool is_zero() const;
271
280 BigInt abs() const;
283 BigInt negate() const;
284
289 static bool is_int(const Location& loc);
290
295 friend BigInt operator+(const BigInt& lhs, const BigInt& rhs);
296
301 friend BigInt operator-(const BigInt& lhs, const BigInt& rhs);
302
307 friend BigInt operator*(const BigInt& lhs, const BigInt& rhs);
308
313 friend BigInt operator/(const BigInt& lhs, const BigInt& rhs);
314
319 friend BigInt operator%(const BigInt& lhs, const BigInt& rhs);
320
325 friend bool operator>(const BigInt& lhs, const BigInt& rhs);
326
331 friend bool operator<(const BigInt& lhs, const BigInt& rhs);
332
337 friend bool operator<=(const BigInt& lhs, const BigInt& rhs);
338
343 friend bool operator>=(const BigInt& lhs, const BigInt& rhs);
344
349 friend bool operator==(const BigInt& lhs, const BigInt& rhs);
350
355 friend bool operator!=(const BigInt& lhs, const BigInt& rhs);
356
361 friend std::ostream& operator<<(std::ostream& os, const BigInt& value);
362
363 private:
364 struct DivideResult
365 {
366 std::string quotient;
367 std::string remainder;
368 };
369
370 static bool less_than(
371 const std::string_view& lhs, const std::string_view& rhs);
372 static bool greater_than(
373 const std::string_view& lhs, const std::string_view& rhs);
374 static bool equal(const std::string_view& lhs, const std::string_view& rhs);
375 static std::string add(
376 const std::string_view& lhs, const std::string_view& rhs, bool negative);
377 static std::string subtract(
378 const std::string_view& lhs, const std::string_view& rhs, bool negative);
379 static DivideResult divide(
380 const std::string_view& lhs, const std::string_view& rhs);
381 static std::string multiply(
382 const std::string_view& lhs, const std::string_view& rhs);
383 std::string_view digits() const;
384 Location m_loc;
385 static Location Zero;
386 static Location One;
387 };
388
391 {
393 Node node;
394
397 };
398
416 {
417 public:
421 UnwrapOpt(std::size_t index);
422
425 bool exclude_got() const;
426
432
435 bool specify_number() const;
436
443
446 const std::string& code() const;
447
451 UnwrapOpt& code(const std::string& value);
452
456 const std::string& pre() const;
457
461 UnwrapOpt& pre(const std::string& value);
462
466 const std::string& message() const;
467
473 UnwrapOpt& message(const std::string& value);
474
478 const std::string& func() const;
479
483 UnwrapOpt& func(const std::string& value);
484
489 const std::vector<Token>& types() const;
490
496 UnwrapOpt& types(const std::vector<Token>& value);
497
500 const Token& type() const;
501
506 UnwrapOpt& type(const Token& value);
507
511 Node unwrap(const Nodes& args) const;
512
513 private:
514 bool m_exclude_got;
515 bool m_specify_number;
516 std::string m_code;
517 std::string m_prefix;
518 std::string m_message;
519 std::string m_func;
520 std::vector<Token> m_types;
521 Token m_type;
522 std::size_t m_index;
523 };
524
529 Node unwrap_arg(const Nodes& args, const UnwrapOpt& options);
530
535 UnwrapResult unwrap(const Node& term, const Token& type);
536
541 UnwrapResult unwrap(const Node& term, const std::set<Token>& types);
542
546 BigInt get_int(const Node& node);
547
553 std::optional<BigInt> try_get_int(const Node& node);
554
558 double get_double(const Node& node);
559
564 std::optional<double> try_get_double(const Node& node);
565
570 std::string get_string(const Node& node);
571
576 std::optional<std::string> try_get_string(const Node& node);
577
581 bool get_bool(const Node& node);
582
586 std::optional<bool> try_get_bool(const Node& node);
587
592 std::optional<Node> try_get_item(
593 const Node& node, const std::string_view& key);
594
600 std::string_view get_raw_string(const Node& node);
601
606 Node scalar(BigInt value);
607
612 Node scalar(double value);
613
618 Node scalar(bool value);
619
624 Node scalar(const char* value);
625
630 Node scalar(const std::string& value);
631
635 Node scalar();
636
640 Node number(double value);
641
645 Node boolean(bool value);
646
650 Node string(const char* value);
651
655 Node string(const std::string& value);
656
659 Node null();
660
665 Node object_item(const Node& key_term, const Node& val_term);
666
670 Node object(const std::initializer_list<Node>& object_items);
671
675 Node array(const std::initializer_list<Node>& array_members);
676
680 Node set(const std::initializer_list<Node>& set_members);
681
682 namespace builtins
683 {
685 const std::size_t AnyArity = std::numeric_limits<std::size_t>::max();
686
687 inline const auto Decl = TokenDef("rego-builtin-decl");
688 inline const auto Arg = TokenDef("rego-builtin-arg");
689 inline const auto Args = TokenDef("rego-builtin-args");
690 inline const auto VarArgs = TokenDef("rego-builtin-varargs");
691 inline const auto Result = TokenDef("rego-builtin-result");
692 inline const auto Void = TokenDef("rego-builtin-void");
693 inline const auto Return = TokenDef("rego-builtins-return");
694 inline const auto Name = TokenDef("rego-builtin-name", flag::print);
695 inline const auto Description =
696 TokenDef("rego-builtin-description", flag::print);
697 inline const auto Type = TokenDef("rego-builtin-type");
698 inline const auto ArgSeq = TokenDef("rego-builtin-argseq");
699 inline const auto MemberType = TokenDef("rego-builtin-membertype");
700 inline const auto TypeSeq = TokenDef("rego-builtin-typeseq");
701 inline const auto DynamicArray = TokenDef("rego-builtin-dynamicarray");
702 inline const auto StaticArray = TokenDef("rego-builtin-staticarray");
703 inline const auto Set = TokenDef("rego-builtin-set");
704 inline const auto DynamicObject = TokenDef("rego-builtin-dynamicobject");
705 inline const auto StaticObject = TokenDef("rego-builtin-staticobject");
706 inline const auto HybridObject = TokenDef("rego-builtin-hybridobject");
707 inline const auto ObjectItem = TokenDef("rego-builtin-objectitem");
708 inline const auto Any = TokenDef("rego-builtin-any");
709 inline const auto String = TokenDef("rego-builtin-string");
710 inline const auto Number = TokenDef("rego-builtin-number");
711 inline const auto Boolean = TokenDef("rego-builtin-boolean");
712 inline const auto Null = TokenDef("rego-builtin-null");
713
714 // clang-format off
715 inline const auto wf_decl =
716 (Decl <<= (Args >>= ArgSeq | VarArgs) * (Return >>= Result | Void))
717 | (ArgSeq <<= Arg++)
718 | (Arg <<= Name * Description * Type)
719 | (Type <<= Any | String | Number | Boolean | Null | DynamicArray | StaticArray | DynamicObject | StaticObject | HybridObject | Set | TypeSeq)
720 | (TypeSeq <<= Type++)
721 | (DynamicArray <<= Type)
722 | (StaticArray <<= Type++)
723 | (Set <<= Type)
724 | (DynamicObject <<= (Key >>= Type) * (Val >>= Type))
725 | (StaticObject <<= ObjectItem++)
726 | (HybridObject <<= DynamicObject * StaticObject)
727 | (ObjectItem <<= Name * Type)
728 | (Result <<= Name * Description * Type)
729 ;
730 // clang-format on
732 }
733
789 {
792 Location name;
793
796 Node decl;
797
801 std::size_t arity;
802
805
808
811 Location name_, Node decl_, BuiltInBehavior behavior_, bool available_);
812
813 virtual ~BuiltInDef() = default;
814
816 virtual void clear();
817
828 const Location& name, Node decl, BuiltInBehavior behavior);
829
841 const Location& name, size_t arity, BuiltInBehavior behavior);
842
855 const Location& name, Node decl, const std::string& message);
856 };
857
858 typedef BuiltIn (*BuiltInFactory)();
859
870 {
871 public:
873 BuiltInsDef() noexcept;
874
878 bool is_builtin(const Location& name);
879
884 Node decl(const Location& name);
885
892 bool is_deprecated(const Location& version, const Location& name) const;
893
899 Node call(const Location& name, const Location& version, const Nodes& args);
900
902 void clear();
903
908
912 BuiltIn at(const Location& name);
913
918 bool strict_errors() const;
919
925
929 template <typename T>
930 BuiltInsDef& register_builtins(const T& built_ins)
931 {
932 for (auto& built_in : built_ins)
933 {
934 register_builtin(built_in);
935 }
936
937 return *this;
938 }
939
944
950 template <typename T>
951 BuiltInsDef& whitelist(const std::initializer_list<T>& allowed)
952 {
953 m_lookup_behavior = BuiltInsDef::LookupBehavior::Whitelist;
954 m_list.clear();
955 m_list.insert(allowed.begin(), allowed.end());
956 m_builtins.clear();
957 return *this;
958 }
959
967 template <typename T>
968 BuiltInsDef& whitelist(T begin, T end)
969 {
970 m_lookup_behavior = BuiltInsDef::LookupBehavior::Whitelist;
971 m_list.clear();
972 m_list.insert(begin, end);
973 m_builtins.clear();
974 return *this;
975 }
976
983 template <typename T>
984 BuiltInsDef& blacklist(const std::initializer_list<T>& forbidden)
985 {
986 m_lookup_behavior = BuiltInsDef::LookupBehavior::Blacklist;
987 m_list.clear();
988 m_list.insert(forbidden.begin(), forbidden.end());
989 m_builtins.clear();
990 return *this;
991 }
992
1001 template <typename T>
1002 BuiltInsDef& blacklist(T begin, T end)
1003 {
1004 m_lookup_behavior = BuiltInsDef::LookupBehavior::Blacklist;
1005 m_list.clear();
1006 m_list.insert(begin, end);
1007 m_builtins.clear();
1008 return *this;
1009 }
1010
1014
1017 static std::shared_ptr<BuiltInsDef> create();
1018
1019 private:
1020 static BuiltIn lookup(const Location& name);
1021
1022 enum class LookupBehavior
1023 {
1024 AllowAll,
1025 Whitelist,
1026 Blacklist
1027 };
1028
1029 LookupBehavior m_lookup_behavior;
1030 std::set<Location> m_list;
1031 std::map<Location, BuiltIn> m_builtins;
1032 bool m_strict_errors;
1033 };
1034
1036 using BuiltIns = std::shared_ptr<BuiltInsDef>;
1037
1038 const std::string UnknownError = "unknown_error";
1039 const std::string EvalTypeError = "eval_type_error";
1040 const std::string EvalBuiltInError = "eval_builtin_error";
1041 const std::string RegoTypeError = "rego_type_error";
1042 const std::string RegoParseError = "rego_parse_error";
1043 const std::string RegoCompileError = "rego_compile_error";
1044 const std::string EvalConflictError = "eval_conflict_error";
1045 const std::string WellFormedError = "wellformed_error";
1046 const std::string RuntimeError = "runtime_error";
1047 const std::string RecursionError = "rego_recursion_error";
1048 const std::string TimeoutError = "timeout_error";
1049 const std::string DefaultVersion = "v1";
1051
1057 Node err(
1058 NodeRange& r,
1059 const std::string& msg,
1060 const std::string& code = UnknownError);
1061
1067 Node err(
1068 Node node, const std::string& msg, const std::string& code = UnknownError);
1069
1078 Node version();
1079
1087 std::string to_key(
1088 const trieste::Node& node,
1089 bool set_as_array = false,
1090 bool sort_arrays = false,
1091 const char* list_delim = ",");
1092
1094 enum class LogLevel : regoEnum
1095 {
1096 None = REGO_LOG_LEVEL_NONE,
1097 Error = REGO_LOG_LEVEL_ERROR,
1098 Output = REGO_LOG_LEVEL_OUTPUT,
1099 Warn = REGO_LOG_LEVEL_WARN,
1100 Info = REGO_LOG_LEVEL_INFO,
1101 Debug = REGO_LOG_LEVEL_DEBUG,
1102 Trace = REGO_LOG_LEVEL_TRACE
1103 };
1104
1107 namespace bundle
1108 {
1110 enum class OperandType
1111 {
1112 None,
1113 Local = 1,
1114 String = 2,
1115 True = 3,
1116 False = 4,
1117 Index,
1118 Value
1119 };
1120
1130 struct Operand
1131 {
1134 union
1135 {
1137 std::int64_t value;
1139 size_t index;
1140 };
1141
1144
1149 static Operand from_op(const Node& n);
1150
1156 static Operand from_index(const Node& n);
1157
1163 static Operand from_value(const Node& n);
1164
1169 friend std::ostream& operator<<(std::ostream& stream, const Operand& op);
1170 };
1171
1176 enum class StatementType
1177 {
1178 Nop = 0,
1179 ArrayAppend = 1,
1180 AssignInt = 2,
1181 AssignVarOnce = 3,
1182 AssignVar = 4,
1183 Block = 5,
1184 Break = 6,
1185 CallDynamic = 7,
1186 Call = 8,
1187 Dot = 9,
1188 Equal = 10,
1189 IsArray = 11,
1190 IsDefined = 12,
1191 IsObject = 13,
1192 IsSet = 14,
1193 IsUndefined = 15,
1194 Len = 16,
1195 MakeArray = 17,
1196 MakeNull = 18,
1197 MakeNumberInt = 19,
1198 MakeNumberRef = 20,
1199 MakeObject = 21,
1200 MakeSet = 22,
1201 NotEqual = 23,
1202 Not = 24,
1203 ObjectInsert = 25,
1204 ObjectInsertOnce = 26,
1205 ObjectMerge = 27,
1206 ResetLocal = 28,
1207 ResultSetAdd = 29,
1208 ReturnLocal = 30,
1209 Scan = 31,
1210 SetAdd = 32,
1211 With = 33
1212 };
1213
1214 struct Statement;
1215
1217 typedef std::vector<Statement> Block;
1218
1220 struct CallExt
1221 {
1223 Location func;
1225 std::vector<Operand> ops;
1226 };
1227
1230 {
1232 std::vector<Operand> path;
1234 std::vector<Operand> ops;
1235 };
1236
1238 struct WithExt
1239 {
1241 std::vector<size_t> path;
1244 };
1245
1249 {
1251 std::variant<CallExt, CallDynamicExt, WithExt, std::vector<Block>, Block>
1253
1256 const CallExt& call() const;
1262 const WithExt& with() const;
1265 const std::vector<Block>& blocks() const;
1268 const Block& block() const;
1269
1277 StatementExt(std::vector<Block>&& blocks);
1280 };
1281
1291 {
1295 Location location;
1296
1299
1302
1304 std::int32_t target;
1305
1307 std::shared_ptr<const StatementExt> ext;
1308
1311
1316 friend std::ostream& operator<<(
1317 std::ostream& stream, const Statement& stmt);
1318 };
1319
1321 struct Plan
1322 {
1324 Location name;
1326 std::vector<Block> blocks;
1327 };
1328
1331 {
1333 Location name;
1335 size_t arity;
1337 std::vector<Location> path;
1339 std::vector<size_t> parameters;
1341 size_t result;
1343 std::vector<Block> blocks;
1346 };
1347 }
1348
1349 struct BundleDef;
1350
1352 typedef std::shared_ptr<BundleDef> Bundle;
1353
1356 {
1358 Node data;
1360 std::map<Location, Node> builtin_functions;
1362 std::map<Location, size_t> name_to_func;
1364 std::map<Location, size_t> name_to_plan;
1366 std::vector<bundle::Plan> plans;
1368 std::vector<bundle::Function> functions;
1370 std::vector<Location> strings;
1372 std::vector<Source> files;
1376 std::optional<size_t> query_plan;
1377
1379 Source query;
1380
1384 std::optional<size_t> find_plan(const Location& name) const;
1385
1389 std::optional<size_t> find_function(const Location& name) const;
1390
1394 bool is_function(const Location& name) const;
1395
1401 void save(std::ostream& stream) const;
1402
1408 void save(const std::filesystem::path& path) const;
1409
1417 static Bundle from_node(Node bundle);
1418
1425 static Bundle load(std::istream& stream);
1426
1433 static Bundle load(const std::filesystem::path& path);
1434 };
1435
1442 {
1443 public:
1445
1454 Node run_entrypoint(const Location& entrypoint, Node input) const;
1455
1462 Node run_query(Node input) const;
1463
1468
1471 BuiltIns builtins() const;
1472
1477
1480
1483 size_t stmt_limit() const;
1484
1490
1491 private:
1492 typedef std::vector<Node> Frame;
1493
1494 enum class Code
1495 {
1496 Break,
1497 Continue,
1498 Undefined,
1499 MultipleOutputs,
1500 Return,
1501 Timeout,
1502 Error
1503 };
1504
1505 class State
1506 {
1507 public:
1508 State(Node input, Node data, size_t num_locals);
1509 Node read_local(size_t index) const;
1510 void write_local(size_t index, Node value);
1511 bool is_defined(size_t key) const;
1512 void reset_local(size_t key);
1513 void add_result(Node node);
1514 const Nodes& result_set() const;
1515 bool is_in_call_stack(const Location& func_name) const;
1516 std::string_view root_function_name() const;
1517 void push_function(const Location& func_name, size_t num_args);
1518 void pop_function(const Location& func_name);
1519 const Nodes& errors() const;
1520 void add_error(Node error);
1521 void add_error_multiple_output(Node inst);
1522 void add_error_object_insert(Node inst);
1523 void put_function_result(const Location& func_name, Node result);
1524 Node get_function_result(const Location& func_name) const;
1525 bool in_with() const;
1526 void push_with();
1527 void pop_with();
1528 bool in_break() const;
1529 void push_break(size_t levels);
1530 void pop_break();
1531 size_t stmt_count() const;
1532 size_t inc_stmts();
1533
1534 private:
1535 Frame m_frame;
1536 Nodes m_errors;
1537 BuiltIns m_builtins;
1538 std::vector<Location> m_call_stack;
1539 std::vector<size_t> m_num_args;
1540 std::map<Location, Node> m_function_cache;
1541 Nodes m_result_set;
1542 size_t m_with_count;
1543 size_t m_break_count;
1544 size_t m_stmt_count;
1545 };
1546
1547 void run_plan(const bundle::Plan& plan, State& state) const;
1548 Code run_block(State& state, const bundle::Block& block) const;
1549 Code run_stmt(
1550 State& state, size_t index, const bundle::Statement& stmt) const;
1551 Code run_scan(State& state, const bundle::Statement& stmt) const;
1552 Code run_with(State& state, const bundle::Statement& stmt) const;
1553 Code run_call(
1554 State& state,
1555 const Location& func,
1556 const std::vector<bundle::Operand>& args,
1557 size_t target) const;
1558 Node dot(const Node& source, const Node& key) const;
1559 Node merge_objects(const Node& a, const Node& b) const;
1560 Node merge_sets(const Node& a, const Node& b) const;
1561 bool insert_into_object(
1562 const Node& a, const Node& key, const Node& value, bool once) const;
1563 Node to_term(const Node& value) const;
1564 Node unpack_operand(
1565 const State& state, const bundle::Operand& operand) const;
1566 Node write_and_swap(
1567 State& state,
1568 size_t key,
1569 const std::vector<size_t>& path,
1570 Node value) const;
1571
1572 Bundle m_bundle;
1573 BuiltIns m_builtins;
1574 RE2 m_int_regex;
1575 size_t m_stmt_limit;
1576 };
1577
1613 {
1614 Node m_node;
1615 std::string m_json;
1616
1617 public:
1621
1625 bool ok() const;
1626
1629 Node node() const;
1630
1634 size_t size() const;
1635
1639 Node expressions_at(size_t index) const;
1640
1643 Node expressions() const;
1644
1650 Node binding_at(size_t index, const std::string& name) const;
1651
1655 Node binding(const std::string& name) const;
1656
1659 const std::string& json() const;
1660
1666 std::vector<std::string> errors() const;
1667 };
1668
1682 {
1683 public:
1686
1693 Node add_module_file(const std::filesystem::path& path);
1694
1702 Node add_module(const std::string& name, const std::string& contents);
1703
1710 Node add_data_json_file(const std::filesystem::path& path);
1711
1718 Node add_data_json(const std::string& json);
1719
1725 Node add_data(const Node& node);
1726
1734 Node set_input_json_file(const std::filesystem::path& path);
1735
1743 Node set_input_json(const std::string& json);
1744
1750 Node set_input_term(const std::string& term);
1751
1758 Node set_input(const Node& node);
1759
1766 Node set_query(const std::string& query);
1767
1772 const std::initializer_list<std::string>& entrypoints);
1773
1777 Interpreter& entrypoints(const std::vector<std::string>& entrypoints);
1778
1781 const std::vector<std::string>& entrypoints() const;
1782
1785 std::vector<std::string>& entrypoints();
1786
1792 std::string query();
1793
1800 std::string query(const std::string& query_expr);
1801
1809 Node query_node(const std::string& query_expr);
1810
1818
1824 Output query_output(const std::string& query_expr);
1825
1832
1833 // clang-format off
1834
1861 Node build();
1862
1863 // clang-format on
1864
1876 Node save_bundle(const std::filesystem::path& dir, const Node& bundle);
1877
1886 Node load_bundle(const std::filesystem::path& dir);
1887
1897 Node query_bundle(const Bundle& bundle);
1898
1909 Node query_bundle(const Bundle& bundle, const std::string& endpoint);
1910
1916 Interpreter& debug_path(const std::filesystem::path& prefix);
1917
1920 const std::filesystem::path& debug_path() const;
1921
1929
1932 bool debug_enabled() const;
1933
1941
1944 bool wf_check_enabled() const;
1945
1951 BuiltIns builtins() const;
1952
1957 std::string output_to_string(const Node& output) const;
1958
1962
1967
1973 Interpreter& log_level(const std::string& level);
1974
1978 const std::string& c_error() const;
1979
1984 Interpreter& c_error(const std::string& error);
1985
1988 size_t stmt_limit() const;
1989
1995
1996 private:
1997 Reader& reader();
1998 Reader& json();
1999 Rewriter& data_from_json();
2000 Rewriter& input_from_json();
2001 Rewriter& to_input();
2002 Rewriter& bundle();
2003 Rewriter& write_bundle();
2004 Rewriter& read_bundle();
2005
2006 void merge(const Node& ast);
2007
2008 Node m_dataseq;
2009 Node m_moduleseq;
2010 Node m_input;
2011 Node m_query;
2012 std::vector<std::string> m_entrypoints;
2013 std::filesystem::path m_debug_path;
2014 bool m_debug_enabled;
2015 bool m_wf_check_enabled;
2016 LogLevel m_log_level;
2017
2018 BuiltIns m_builtins;
2019 std::unique_ptr<Reader> m_reader;
2020 std::unique_ptr<Reader> m_json;
2021 std::unique_ptr<Rewriter> m_data_from_json;
2022 std::unique_ptr<Rewriter> m_input_from_json;
2023 std::unique_ptr<Rewriter> m_to_input;
2024 std::unique_ptr<Rewriter> m_bundle;
2025 std::unique_ptr<Rewriter> m_write_bundle;
2026 std::unique_ptr<Rewriter> m_read_bundle;
2027 VirtualMachine m_vm;
2028 std::size_t m_data_count;
2029 std::map<std::string, Node> m_cache;
2030
2031 std::string m_c_error;
2032 };
2033
2037 LogLevel log_level_from_string(const std::string& value);
2038
2041 inline const auto RegoBundle = TokenDef("rego-bundle", flag::symtab);
2042 inline const auto Data = TokenDef("rego-data");
2043 inline const auto ModuleFile = TokenDef("rego-modulefile");
2044 inline const auto Static = TokenDef("rego-static");
2045 inline const auto BuiltInFunction = TokenDef("rego-builtinfunction");
2046 inline const auto Plan = TokenDef("rego-plan", flag::lookup | flag::symtab);
2047 inline const auto Block = TokenDef("rego-block");
2048 inline const auto Function =
2049 TokenDef("rego-function", flag::lookup | flag::symtab);
2050 inline const auto LocalIndex = TokenDef("rego-localindex", flag::print);
2051 inline const auto Operand = TokenDef("rego-operand");
2052 inline const auto Int32 = TokenDef("rego-int32", flag::print);
2053 inline const auto Int64 = TokenDef("rego-int64", flag::print);
2054 inline const auto UInt32 = TokenDef("rego-uint32", flag::print);
2055 inline const auto StringIndex = TokenDef("rego-stringindex", flag::print);
2056 inline const auto Boolean = TokenDef("rego-boolean", flag::print);
2057 inline const auto IRString = TokenDef("rego-irstring", flag::print);
2058 inline const auto IRQuery = TokenDef("rego-irquery");
2059 inline const auto IRPath = TokenDef("rego-irpath");
2060
2061 // sequences
2062 inline const auto BlockSeq = TokenDef("rego-blockseq");
2063 inline const auto ParameterSeq = TokenDef("rego-parameterseq");
2064 inline const auto PlanSeq = TokenDef("rego-planseq");
2065 inline const auto FunctionSeq = TokenDef("rego-functionseq");
2066 inline const auto BuiltInFunctionSeq = TokenDef("rego-builtinfunctionseq");
2067 inline const auto StringSeq = TokenDef("rego-stringseq");
2068 inline const auto PathSeq = TokenDef("rego-pathseq");
2069 inline const auto OperandSeq = TokenDef("rego-operandseq");
2070 inline const auto Int32Seq = TokenDef("rego-int32seq");
2071 inline const auto EntryPointSeq = TokenDef("rego-entrypointseq");
2072 inline const auto ModuleFileSeq = TokenDef("rego-modulefileseq");
2073
2074 // Statements
2075 inline const auto ArrayAppendStmt = TokenDef("rego-arrayappendstmt");
2076 inline const auto AssignIntStmt = TokenDef("rego-assignintstmt");
2077 inline const auto AssignVarOnceStmt = TokenDef("rego-assignvaroncestmt");
2078 inline const auto AssignVarStmt = TokenDef("rego-assignvarstmt");
2079 inline const auto BlockStmt = TokenDef("rego-blockstmt");
2080 inline const auto BreakStmt = TokenDef("rego-breakstmt");
2081 inline const auto CallDynamicStmt = TokenDef("rego-calldynamicstmt");
2082 inline const auto CallStmt = TokenDef("rego-callstmt");
2083 inline const auto DotStmt = TokenDef("rego-dotstmt");
2084 inline const auto EqualStmt = TokenDef("rego-equalstmt");
2085 inline const auto IsArrayStmt = TokenDef("rego-isarraystmt");
2086 inline const auto IsDefinedStmt = TokenDef("rego-isdefinedstmt");
2087 inline const auto IsObjectStmt = TokenDef("rego-isobjectstmt");
2088 inline const auto IsSetStmt = TokenDef("rego-issetstmt");
2089 inline const auto IsUndefinedStmt = TokenDef("rego-isundefinedstmt");
2090 inline const auto LenStmt = TokenDef("rego-lenstmt");
2091 inline const auto MakeArrayStmt = TokenDef("rego-makearraystmt");
2092 inline const auto MakeNullStmt = TokenDef("rego-makenullstmt");
2093 inline const auto MakeNumberIntStmt = TokenDef("rego-makenumberintstmt");
2094 inline const auto MakeNumberRefStmt = TokenDef("rego-makenumberrefstmt");
2095 inline const auto MakeObjectStmt = TokenDef("rego-makeobjectstmt");
2096 inline const auto MakeSetStmt = TokenDef("rego-makesetstmt");
2097 inline const auto NotEqualStmt = TokenDef("rego-notequalstmt");
2098 inline const auto NotStmt = TokenDef("rego-notstmt");
2099 inline const auto ObjectInsertOnceStmt =
2100 TokenDef("rego-objectinsertoncestmt");
2101 inline const auto ObjectInsertStmt = TokenDef("rego-objectinsertstmt");
2102 inline const auto ObjectMergeStmt = TokenDef("rego-objectmergestmt");
2103 inline const auto ResetLocalStmt = TokenDef("rego-resetlocalstmt");
2104 inline const auto ResultSetAddStmt = TokenDef("rego-resultsetaddstmt");
2105 inline const auto ReturnLocalStmt = TokenDef("rego-returnlocalstmt");
2106 inline const auto ScanStmt = TokenDef("rego-scanstmt");
2107 inline const auto SetAddStmt = TokenDef("rego-setaddstmt");
2108 inline const auto WithStmt = TokenDef("rego-withstmt");
2109
2110 // other tokens
2111 inline const auto Blocks = TokenDef("rego-blocks");
2112 inline const auto Func = TokenDef("rego-func");
2113 inline const auto Capacity = TokenDef("rego-capacity");
2114 inline const auto Stmt = TokenDef("rego-stmt");
2115
2116 inline const auto wf_ir_statements = ArrayAppendStmt | AssignIntStmt |
2117 AssignVarOnceStmt | AssignVarStmt | BlockStmt | BreakStmt |
2118 CallDynamicStmt | CallStmt | DotStmt | EqualStmt | IsArrayStmt |
2119 IsDefinedStmt | IsObjectStmt | IsSetStmt | IsUndefinedStmt | LenStmt |
2120 MakeArrayStmt | MakeNullStmt | MakeNumberIntStmt | MakeNumberRefStmt |
2121 MakeObjectStmt | MakeSetStmt | NotEqualStmt | NotStmt |
2122 ObjectInsertOnceStmt | ObjectInsertStmt | ObjectMergeStmt | ResetLocalStmt |
2123 ResultSetAddStmt | ReturnLocalStmt | ScanStmt | SetAddStmt | WithStmt;
2124
2125 // clang-format off
2126 inline const auto wf_bundle =
2127 builtins::wf_decl
2128 | wf_result
2129 | (Top <<= RegoBundle)
2130 | (RegoBundle <<= Data * Policy * ModuleFileSeq)
2131 | (ModuleFileSeq <<= ModuleFile++)
2132 | (ModuleFile <<= (Name >>= IRString) * (Contents >>= IRString))
2133 | (Data <<= rego::Object)
2134 | (Policy <<= Static * PlanSeq * IRQuery * FunctionSeq)
2135 | (IRQuery <<= (IRString|Undefined))
2136 | (Static <<= StringSeq * PathSeq * BuiltInFunctionSeq)
2137 | (StringSeq <<= IRString++)
2138 | (BuiltInFunctionSeq <<= BuiltInFunction++)
2139 | (BuiltInFunction <<= (Name >>= IRString) * builtins::Decl)
2140 | (PathSeq <<= IRString++)
2141 | (PlanSeq <<= Plan++[1])
2142 | (Plan <<= (Name >>= IRString) * BlockSeq)
2143 | (BlockSeq <<= Block++)
2144 | (Block <<= wf_ir_statements++)
2145 | (FunctionSeq <<= Function++)
2146 | (Function <<= (Name >>= IRString) * IRPath * ParameterSeq * (Return >>= LocalIndex) * BlockSeq)[Name]
2147 | (IRPath <<= IRString++[1])
2148 | (ParameterSeq <<= LocalIndex++)
2149 | (ArrayAppendStmt <<= (Array >>= LocalIndex) * (Val >>= Operand))
2150 | (AssignIntStmt <<= (Val >>= Int64) * (Target >>= LocalIndex))
2151 | (AssignVarOnceStmt <<= (Src >>= Operand) * (Target >>= LocalIndex))
2152 | (AssignVarStmt <<= (Src >>= Operand) * (Target >>= LocalIndex))
2153 | (BlockStmt <<= (Blocks >>= BlockSeq))
2154 | (BreakStmt <<= (Idx >>= UInt32))
2155 | (CallDynamicStmt <<= (Func >>= OperandSeq) * (Args >>= OperandSeq) * (Result >>= LocalIndex))
2156 | (CallStmt <<= (Func >>= IRString) * (Args >>= OperandSeq) * (Result >>= LocalIndex))
2157 | (DotStmt <<= (Src >>= Operand) * (Key >>= Operand) * (Target >>= LocalIndex))
2158 | (EqualStmt <<= (Lhs >>= Operand) * (Rhs >>= Operand))
2159 | (IsArrayStmt <<= (Src >>= Operand))
2160 | (IsDefinedStmt <<= (Src >>= LocalIndex))
2161 | (IsObjectStmt <<= (Src >>= Operand))
2162 | (IsSetStmt <<= (Src >>= Operand))
2163 | (IsUndefinedStmt <<= (Src >>= LocalIndex))
2164 | (LenStmt <<= (Src >>= Operand) * (Target >>= LocalIndex))
2165 | (MakeArrayStmt <<= (Capacity >>= Int32) * (Target >>= LocalIndex))
2166 | (MakeNullStmt <<= (Target >>= LocalIndex))
2167 | (MakeNumberIntStmt <<= (Val >>= Int64) * (Target >>= LocalIndex))
2168 | (MakeNumberRefStmt <<= (Idx >>= Int32) * (Target >>= LocalIndex))
2169 | (MakeObjectStmt <<= (Target >>= LocalIndex))
2170 | (MakeSetStmt <<= (Target >>= LocalIndex))
2171 | (NotEqualStmt <<= (Lhs >>= Operand) * (Rhs >>= Operand))
2172 | (NotStmt <<= Block)
2173 | (ObjectInsertOnceStmt <<= (Key >>= Operand) * (Val >>= Operand) * (Object >>= LocalIndex))
2174 | (ObjectInsertStmt <<= (Key >>= Operand) * (Val >>= Operand) * (Object >>= LocalIndex))
2175 | (ObjectMergeStmt <<= (Lhs >>= LocalIndex) * (Rhs >>= LocalIndex) * (Target >>= LocalIndex))
2176 | (ResetLocalStmt <<= (Target >>= LocalIndex))
2177 | (ResultSetAddStmt <<= (Val >>= LocalIndex))
2178 | (ReturnLocalStmt <<= (Src >>= LocalIndex))
2179 | (ScanStmt <<= (Src >>= LocalIndex) * (Key >>= LocalIndex) * (Val >>= LocalIndex) * Block)
2180 | (SetAddStmt <<= (Val >>= Operand) * (Set >>= LocalIndex))
2181 | (WithStmt <<= LocalIndex * (Path >>= Int32Seq) * (Val >>= Operand) * Block)
2182 | (Operand <<= LocalIndex | Boolean | StringIndex)
2183 | (OperandSeq <<= Operand++)
2184 | (Int32Seq <<= Int32++)
2185 ;
2186 // clang-format on
2188
2191
2193 Rewriter rego_to_input();
2194
2196 Rewriter json_to_rego(bool as_term = false);
2197
2199 Rewriter rego_to_json();
2200
2202 Rewriter rego_to_yaml();
2203
2205 Rewriter json_to_bundle();
2206
2208 Rewriter bundle_to_json();
2209
2211 Rewriter rego_to_bundle(BuiltIns builtins = BuiltInsDef::create());
2212}
Big Integer implemention based on strings.
Definition rego.hh:240
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:870
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:984
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:930
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:968
BuiltInsDef & blacklist(T begin, T end)
Sets a blacklist of built-in names that are forbidden from being loaded.
Definition rego.hh:1002
BuiltInsDef & whitelist(const std::initializer_list< T > &allowed)
Sets a whitelist of built-in names that are allowed to be loaded.
Definition rego.hh:951
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:1682
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:1613
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:416
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:1442
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:1111
StatementType
The type of an IR statement.
Definition rego.hh:1177
std::vector< Statement > Block
A block of statements.
Definition rego.hh:1217
Definition rego.hh:18
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::string to_key(const trieste::Node &node, bool set_as_array=false, bool sort_arrays=false, const char *list_delim=",")
Converts a node to a unique key representation that can be used for comparison.
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,...
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:1352
std::shared_ptr< BuiltInDef > BuiltIn
A pointer to a BuiltInDef.
Definition rego.hh:225
std::string_view get_raw_string(const Node &node)
Returns the raw location of the node from the source.
std::function< Node(const Nodes &)> BuiltInBehavior
The function pointer to the behavior of the built-in.
Definition rego.hh:228
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:1095
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.
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:789
bool available
Whether the builtin is available.
Definition rego.hh:807
Node decl
The declaration node which adheres to the builtins::wf_decl well-formedness definition.
Definition rego.hh:796
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:804
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:801
Location name
The name used to match against expression calls in the rego program.
Definition rego.hh:792
Represents a compiled Rego bundle.
Definition rego.hh:1356
std::map< Location, size_t > name_to_plan
Map from function names to their indices.
Definition rego.hh:1364
std::vector< bundle::Function > functions
The functions in the bundle.
Definition rego.hh:1368
std::map< Location, size_t > name_to_func
Map from plan names to their indices.
Definition rego.hh:1362
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:1370
std::vector< Source > files
The module source files which were compiled into the bundle.
Definition rego.hh:1372
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:1366
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:1379
Node data
The merged base data document.
Definition rego.hh:1358
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:1360
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:1374
std::optional< size_t > query_plan
The index of the query plan, if one was included.
Definition rego.hh:1376
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:391
bool success
True if the argument was unwrapped successfully.
Definition rego.hh:396
Node node
The unwrapped argument or nullptr (if unsuccessful).
Definition rego.hh:393
Additional information for CallDynamic statements.
Definition rego.hh:1230
std::vector< Operand > ops
The arguments to the function.
Definition rego.hh:1234
std::vector< Operand > path
The path to the function being called.
Definition rego.hh:1232
Additional information for Call statements.
Definition rego.hh:1221
std::vector< Operand > ops
The arguments to the function.
Definition rego.hh:1225
Location func
The function being called.
Definition rego.hh:1223
Represents a function in the IR.
Definition rego.hh:1331
std::vector< size_t > parameters
The local indices of the function parameters.
Definition rego.hh:1339
std::vector< Block > blocks
The blocks which make up the function.
Definition rego.hh:1343
Location name
The name of the function.
Definition rego.hh:1333
size_t arity
The arity of the function.
Definition rego.hh:1335
size_t result
The index of the result local.
Definition rego.hh:1341
std::vector< Location > path
The path of the function (the name broken into segments)
Definition rego.hh:1337
bool cacheable
Whether the function result can be cached.
Definition rego.hh:1345
Represents an operand in the IR.
Definition rego.hh:1131
size_t index
A local index (if type is Local, String, or Index).
Definition rego.hh:1139
std::int64_t value
An integer value (if type is Value).
Definition rego.hh:1137
OperandType type
The type of the operand.
Definition rego.hh:1133
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:1322
Location name
The name of the plan.
Definition rego.hh:1324
std::vector< Block > blocks
The blocks which make up the plan.
Definition rego.hh:1326
Additional information for Call, CallDynamic, With, Block, Not, and Scan statements.
Definition rego.hh:1249
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:1252
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:1291
std::int32_t target
The target of the statement.
Definition rego.hh:1304
StatementType type
The type of statement.
Definition rego.hh:1293
std::shared_ptr< const StatementExt > ext
The (optional) extended information for the statement.
Definition rego.hh:1307
Location location
The location of the statement in the source document.
Definition rego.hh:1295
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:1301
Statement()
Default constructor.
Operand op0
The first operand of the statement.
Definition rego.hh:1298
Additional information for With statements.
Definition rego.hh:1239
std::vector< size_t > path
The path to the value being replaced.
Definition rego.hh:1241
Block block
The block to execute with the replacement.
Definition rego.hh:1243