rego-cpp 0.4.5
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
8#include <trieste/trieste.h>
9
16namespace rego
17{
18 using namespace trieste;
19 using namespace wf::ops;
20
21 inline const auto Module = TokenDef("rego-module", flag::symtab);
22 inline const auto Package = TokenDef("rego-package");
23 inline const auto Policy = TokenDef("rego-policy");
24 inline const auto Rule = TokenDef("rego-rule", flag::symtab);
25 inline const auto RuleHead = TokenDef("rego-rulehead");
26 inline const auto RuleHeadComp = TokenDef("rego-ruleheadcomp");
27 inline const auto RuleHeadFunc = TokenDef("rego-ruleheadfunc");
28 inline const auto RuleHeadSet = TokenDef("rego-ruleheadset");
29 inline const auto RuleHeadObj = TokenDef("rego-ruleheadobj");
30 inline const auto RuleArgs = TokenDef("rego-ruleargs");
31 inline const auto Query = TokenDef("rego-query");
32 inline const auto Literal = TokenDef("rego-literal");
33 inline const auto Expr = TokenDef("rego-expr");
34 inline const auto ExprInfix = TokenDef("rego-exprinfix");
35 inline const auto ExprCall = TokenDef("rego-exprcall");
36 inline const auto ExprEvery = TokenDef("rego-exprevery");
37 inline const auto ExprParens = TokenDef("rego-exprparens");
38 inline const auto UnaryExpr = TokenDef("rego-unaryexpr");
39 inline const auto NotExpr = TokenDef("rego-not-expr");
40 inline const auto Term = TokenDef("rego-term");
41 inline const auto InfixOperator = TokenDef("rego-infixoperator");
42 inline const auto BoolOperator = TokenDef("rego-booloperator");
43 inline const auto ArithOperator = TokenDef("rego-arithoperator");
44 inline const auto AssignOperator = TokenDef("rego-assignoperator");
45 inline const auto BinOperator = TokenDef("rego-binoperator");
46 inline const auto Ref = TokenDef("rego-ref");
47 inline const auto RefArgBrack = TokenDef("rego-refargbrack");
48 inline const auto RefArgDot = TokenDef("rego-refargdot");
49 inline const auto Var = TokenDef("rego-var", flag::print);
50 inline const auto Scalar = TokenDef("rego-scalar");
51 inline const auto String = TokenDef("rego-string");
52 inline const auto Array = TokenDef("rego-array");
53 inline const auto Object = TokenDef("rego-object");
54 inline const auto Set = TokenDef("rego-set");
55 inline const auto ObjectItem = TokenDef("rego-objectitem");
56 inline const auto RawString = TokenDef("rego-rawstring", flag::print);
57 inline const auto JSONString = TokenDef("rego-STRING", flag::print);
58 inline const auto Int = TokenDef("rego-INT", flag::print);
59 inline const auto Float = TokenDef("rego-FLOAT", flag::print);
60 inline const auto True = TokenDef("rego-true");
61 inline const auto False = TokenDef("rego-false");
62 inline const auto Null = TokenDef("rego-null");
63 inline const auto Equals = TokenDef("rego-equals");
64 inline const auto NotEquals = TokenDef("rego-notequals");
65 inline const auto LessThan = TokenDef("rego-lessthan");
66 inline const auto GreaterThan = TokenDef("rego-greaterthan");
67 inline const auto LessThanOrEquals = TokenDef("rego-lessthanorequals");
68 inline const auto GreaterThanOrEquals = TokenDef("rego-greaterthanorequals");
69 inline const auto Add = TokenDef("rego-add");
70 inline const auto Subtract = TokenDef("rego-subtract");
71 inline const auto Multiply = TokenDef("rego-multiply");
72 inline const auto Divide = TokenDef("rego-divide");
73 inline const auto Modulo = TokenDef("rego-modulo");
74 inline const auto And = TokenDef("rego-and");
75 inline const auto Or = TokenDef("rego-or");
76 inline const auto Assign = TokenDef("rego-assign");
77 inline const auto Unify = TokenDef("rego-unify");
78 inline const auto Default = TokenDef("rego-default");
79 inline const auto Some = TokenDef("rego-some");
80 inline const auto SomeDecl = TokenDef("rego-somedecl");
81 inline const auto If = TokenDef("rego-if");
82 inline const auto IsIn = TokenDef("rego-in");
83 inline const auto Contains = TokenDef("rego-contains");
84 inline const auto Else = TokenDef("rego-else");
85 inline const auto As = TokenDef("rego-as");
86 inline const auto With = TokenDef("rego-with");
87 inline const auto Every = TokenDef("rego-every");
88 inline const auto ArrayCompr = TokenDef("rego-arraycompr");
89 inline const auto ObjectCompr = TokenDef("rego-objectcompr");
90 inline const auto SetCompr = TokenDef("rego-setcompr");
91 inline const auto Membership = TokenDef("rego-membership");
92 inline const auto Not = TokenDef("rego-not");
93 inline const auto Import =
94 TokenDef("rego-import", flag::lookdown | flag::lookup | flag::shadowing);
95 inline const auto Placeholder = TokenDef("rego-placeholder");
96 inline const auto Version = TokenDef("rego-version", flag::print);
97
98 // intermediate tokens
99 inline const auto RuleBodySeq = TokenDef("rego-rulebodyseq");
100 inline const auto ImportSeq = TokenDef("rego-importseq");
101 inline const auto RuleRef = TokenDef("rego-ruleref");
102 inline const auto RuleHeadType = TokenDef("rego-ruleheadtype");
103 inline const auto WithSeq = TokenDef("rego-withseq");
104 inline const auto TermSeq = TokenDef("rego-termseq");
105 inline const auto ExprSeq = TokenDef("rego-exprseq");
106 inline const auto VarSeq = TokenDef("rego-varseq");
107 inline const auto RefHead = TokenDef("rego-refhead");
108 inline const auto RefArgSeq = TokenDef("rego-refargseq");
109 inline const auto Key = TokenDef("rego-key", flag::print);
110 inline const auto Val = TokenDef("rego-value");
111 inline const auto Undefined = TokenDef("rego-undefined");
112
113 // other tokens
114 inline const auto Results = TokenDef("rego-results", flag::symtab);
115 inline const auto Result = TokenDef("rego-result", flag::symtab);
116 inline const auto Bindings = TokenDef("rego-bindings");
117 inline const auto Terms = TokenDef("rego-terms");
118 inline const auto Binding = TokenDef("rego-binding", flag::lookdown);
119 inline const auto ErrorCode = TokenDef("rego-errorcode");
120 inline const auto ErrorSeq = TokenDef("rego-errorseq");
121
122 inline const auto wf_assign_op = Assign | Unify;
123 inline const auto wf_arith_op = Add | Subtract | Multiply | Divide | Modulo;
124 inline const auto wf_bin_op = And | Or | Subtract;
125 inline const auto wf_bool_op = Equals | NotEquals | LessThan |
126 LessThanOrEquals | GreaterThan | GreaterThanOrEquals | Not;
127 inline const auto wf_exprs =
128 Term | ExprCall | ExprInfix | ExprEvery | ExprParens | UnaryExpr;
129
130 // clang-format off
131 inline const auto wf =
132 (Top <<= Query | Module)
133 | (Module <<= Package * Version * ImportSeq * Policy)
134 | (ImportSeq <<= Import++)
135 | (Import <<= Ref * Var)
136 | (Package <<= Ref)
137 | (Policy <<= Rule++)
138 | (Rule <<= (Default >>= True | False) * RuleHead * RuleBodySeq)
139 | (RuleHead <<= RuleRef * (RuleHeadType >>= (RuleHeadSet | RuleHeadObj | RuleHeadFunc | RuleHeadComp)))
140 | (RuleRef <<= Var | Ref)
141 | (RuleHeadComp <<= Expr)
142 | (RuleHeadObj <<= Expr * Expr)
143 | (RuleHeadFunc <<= RuleArgs * Expr)
144 | (RuleHeadSet <<= Expr)
145 | (RuleArgs <<= Term++)
146 | (RuleBodySeq <<= (Else | Query)++)
147 | (Else <<= Expr * Query)
148 | (Query <<= Literal++)
149 | (Literal <<= (Expr >>= SomeDecl | Expr | NotExpr) * WithSeq)
150 | (WithSeq <<= With++)
151 | (With <<= Term * Expr)
152 | (SomeDecl <<= ExprSeq * (IsIn >>= Expr | Undefined))
153 | (NotExpr <<= Expr)
154 | (Expr <<= (Term | ExprCall | ExprInfix | ExprEvery | ExprParens | UnaryExpr))
155 | (ExprCall <<= Ref * ExprSeq)
156 | (ExprSeq <<= Expr++)
157 | (ExprInfix <<= Expr * InfixOperator * Expr)
158 | (ExprEvery <<= VarSeq * (IsIn >>= Term | ExprCall | ExprInfix) * Query)
159 | (VarSeq <<= Var++[1])
160 | (ExprParens <<= Expr)
161 | (UnaryExpr <<= Expr)
162 | (Membership <<= ExprSeq * Expr)
163 | (Term <<= Ref | Var | Scalar | Array | Object | Set | Membership | ArrayCompr | ObjectCompr | SetCompr)
164 | (ArrayCompr <<= Expr * Query)
165 | (SetCompr <<= Expr * Query)
166 | (ObjectCompr <<= Expr * Expr * Query)
167 | (InfixOperator <<= AssignOperator | BoolOperator | ArithOperator | BinOperator)
168 | (BoolOperator <<= Equals | NotEquals | LessThan | GreaterThan | LessThanOrEquals | GreaterThanOrEquals)
169 | (ArithOperator <<= Add | Subtract | Multiply | Divide | Modulo)
170 | (BinOperator <<= And | Or)
171 | (AssignOperator <<= Assign | Unify)
172 | (Ref <<= RefHead * RefArgSeq)
173 | (RefHead <<= Var | Array | Object | Set | ArrayCompr | ObjectCompr | SetCompr | ExprCall)
174 | (RefArgSeq <<= (RefArgDot | RefArgBrack)++)
175 | (RefArgBrack <<= Expr | Placeholder)
176 | (RefArgDot <<= Var)
177 | (Scalar <<= String | Int | Float | True | False | Null)
178 | (String <<= JSONString | RawString)
179 | (Array <<= Expr++)
180 | (Object <<= ObjectItem++)
181 | (ObjectItem <<= (Key >>= Expr) * (Val >>= Expr))
182 | (Set <<= Expr++)
183 ;
184 // clang-format on
185
186 // clang-format off
187 inline const auto wf_result =
188 (Top <<= Results | Undefined)
189 | (Results <<= Result++[1])
190 | (Result <<= Terms * Bindings)
191 | (Terms <<= Term++)
192 | (Bindings <<= Binding++)
193 | (Binding <<= (Key >>= Var) * (Val >>= Term))[Key]
194 | (Term <<= Scalar | Array | Object | Set)
195 | (Array <<= Term++)
196 | (Set <<= Term++)
197 | (Object <<= ObjectItem++)
198 | (ObjectItem <<= (Key >>= Term) * (Val >>= Term))
199 | (Scalar <<= JSONString | Int | Float | True | False | Null)
200 | (Error <<= ErrorMsg * ErrorAst * ErrorCode)
201 ;
202 // clang-format on
203
204 struct BuiltInDef;
206 using BuiltIn = std::shared_ptr<BuiltInDef>;
207
209 using BuiltInBehavior = std::function<Node(const Nodes&)>;
210
219 class BigInt
220 {
221 public:
222 BigInt();
223 BigInt(const Location& value);
224 BigInt(std::int64_t value);
225 BigInt(std::size_t value);
226
227 const Location& loc() const;
228 std::int64_t to_int() const;
229 std::size_t to_size() const;
230 bool is_negative() const;
231 bool is_zero() const;
232 BigInt increment() const;
233 BigInt decrement() const;
234
235 static bool is_int(const Location& loc);
236
237 friend BigInt operator+(const BigInt& lhs, const BigInt& rhs);
238 friend BigInt operator-(const BigInt& lhs, const BigInt& rhs);
239 friend BigInt operator*(const BigInt& lhs, const BigInt& rhs);
240 friend BigInt operator/(const BigInt& lhs, const BigInt& rhs);
241 friend BigInt operator%(const BigInt& lhs, const BigInt& rhs);
242
243 friend bool operator>(const BigInt& lhs, const BigInt& rhs);
244 friend bool operator<(const BigInt& lhs, const BigInt& rhs);
245 friend bool operator<=(const BigInt& lhs, const BigInt& rhs);
246 friend bool operator>=(const BigInt& lhs, const BigInt& rhs);
247 friend bool operator==(const BigInt& lhs, const BigInt& rhs);
248 friend bool operator!=(const BigInt& lhs, const BigInt& rhs);
249
250 friend std::ostream& operator<<(std::ostream& os, const BigInt& value);
251
252 BigInt negate() const;
253
254 private:
255 struct DivideResult
256 {
257 std::string quotient;
258 std::string remainder;
259 };
260
261 static bool less_than(
262 const std::string_view& lhs, const std::string_view& rhs);
263 static bool greater_than(
264 const std::string_view& lhs, const std::string_view& rhs);
265 static bool equal(const std::string_view& lhs, const std::string_view& rhs);
266 static std::string add(
267 const std::string_view& lhs, const std::string_view& rhs, bool negative);
268 static std::string subtract(
269 const std::string_view& lhs, const std::string_view& rhs, bool negative);
270 static DivideResult divide(
271 const std::string_view& lhs, const std::string_view& rhs);
272 static std::string multiply(
273 const std::string_view& lhs, const std::string_view& rhs);
274 std::string_view digits() const;
275 Location m_loc;
276 static Location Zero;
277 static Location One;
278 };
279
284 {
286 Node node;
287
290 };
291
311 {
312 public:
318 UnwrapOpt(std::size_t index);
319
324 bool exclude_got() const;
326
331 bool specify_number() const;
333
339 const std::string& code() const;
340 UnwrapOpt& code(const std::string& value);
341
348 const std::string& pre() const;
349 UnwrapOpt& pre(const std::string& value);
350
357 const std::string& message() const;
358 UnwrapOpt& message(const std::string& value);
359
365 const std::string& func() const;
366 UnwrapOpt& func(const std::string& value);
367
374 const std::vector<Token>& types() const;
375 UnwrapOpt& types(const std::vector<Token>& value);
376
380 const Token& type() const;
381 UnwrapOpt& type(const Token& value);
382
389 Node unwrap(const Nodes& args) const;
390
391 private:
392 bool m_exclude_got;
393 bool m_specify_number;
394 std::string m_code;
395 std::string m_prefix;
396 std::string m_message;
397 std::string m_func;
398 std::vector<Token> m_types;
399 std::size_t m_index;
400 };
401
409 Node unwrap_arg(const Nodes& args, const UnwrapOpt& options);
410
418 UnwrapResult unwrap(const Node& term, const Token& type);
419
427 UnwrapResult unwrap(const Node& term, const std::set<Token>& types);
428
435 BigInt get_int(const Node& node);
436
443 double get_double(const Node& node);
444
453 std::optional<BigInt> try_get_int(const Node& node);
454
463 std::string get_string(const Node& node);
464
471 bool get_bool(const Node& node);
472
479 std::optional<Node> try_get_item(
480 const Node& node, const std::string_view& key);
481
488 Node scalar(BigInt value);
489
496 Node scalar(double value);
497
504 Node scalar(bool value);
505
512 Node scalar(const char* value);
513
520 Node scalar(const std::string& value);
521
528 Node scalar();
529
537 Node object_item(const Node& key_term, const Node& val_term);
538
545 Node object(const Nodes& object_items);
546
553 Node array(const Nodes& array_members);
554
561 Node set(const Nodes& set_members);
562
574 void set_tzdata_path(const std::filesystem::path& path);
575
578 const std::size_t AnyArity = std::numeric_limits<std::size_t>::max();
579
625 {
627 Location name;
633 std::size_t arity;
634
637
641 BuiltInDef(Location name_, std::size_t arity_, BuiltInBehavior behavior_);
642
643 virtual ~BuiltInDef() = default;
644
648 virtual void clear();
649
662 const Location& name, std::size_t arity, BuiltInBehavior behavior);
663 };
664
670 {
671 public:
673 BuiltInsDef() noexcept;
674
681 bool is_builtin(const Location& name) const;
682
690 bool is_deprecated(const Location& version, const Location& name) const;
691
700 Node call(const Location& name, const Location& version, const Nodes& args);
701
705 void clear();
706
713
717 const BuiltIn& at(const Location& name) const;
718
725 bool strict_errors() const;
727
733 template <typename T>
734 BuiltInsDef& register_builtins(const T& built_ins)
735 {
736 for (auto& built_in : built_ins)
737 {
738 register_builtin(built_in);
739 }
740
741 return *this;
742 }
743
756
760 static std::shared_ptr<BuiltInsDef> create();
761
762 std::map<Location, BuiltIn>::const_iterator begin() const;
763 std::map<Location, BuiltIn>::const_iterator end() const;
764
765 private:
766 std::map<Location, BuiltIn> m_builtins;
767 bool m_strict_errors;
768 };
769
770 using BuiltIns = std::shared_ptr<BuiltInsDef>;
771
772 const std::string UnknownError = "unknown_error";
773 const std::string EvalTypeError = "eval_type_error";
774 const std::string EvalBuiltInError = "eval_builtin_error";
775 const std::string RegoTypeError = "rego_type_error";
776 const std::string RegoParseError = "rego_parse_error";
777 const std::string RegoCompileError = "rego_compile_error";
778 const std::string EvalConflictError = "eval_conflict_error";
779 const std::string WellFormedError = "wellformed_error";
780 const std::string RuntimeError = "runtime_error";
781 const std::string RecursionError = "rego_recursion_error";
782 const std::string DefaultVersion = "v0";
783
791 Node err(
792 NodeRange& r,
793 const std::string& msg,
794 const std::string& code = UnknownError);
795
803 Node err(
804 Node node, const std::string& msg, const std::string& code = UnknownError);
805
815 Node version();
816
822 std::string to_key(
823 const trieste::Node& node,
824 bool set_as_array = false,
825 bool sort_arrays = false);
826
830 enum class LogLevel : char
831 {
832 None = REGO_LOG_LEVEL_NONE,
833 Error = REGO_LOG_LEVEL_ERROR,
834 Output = REGO_LOG_LEVEL_OUTPUT,
835 Warn = REGO_LOG_LEVEL_WARN,
836 Info = REGO_LOG_LEVEL_INFO,
837 Debug = REGO_LOG_LEVEL_DEBUG,
838 Trace = REGO_LOG_LEVEL_TRACE,
839 };
840
847
855 std::string set_log_level_from_string(const std::string& level);
856
873 {
874 public:
880 Interpreter(bool v1_compatible = false);
881
891 Node add_module_file(const std::filesystem::path& path);
892
902 Node add_module(const std::string& name, const std::string& contents);
903
913 Node add_data_json_file(const std::filesystem::path& path);
914
924 Node add_data_json(const std::string& json);
925
934 Node add_data(const Node& node);
935
946 Node set_input_json_file(const std::filesystem::path& path);
947
956 Node set_input_term(const std::string& term);
957
966 Node set_input(const Node& node);
967
977 std::string query(const std::string& query_expr);
978
989 Node raw_query(const std::string& query_expr);
990
998 Interpreter& debug_path(const std::filesystem::path& prefix);
999 const std::filesystem::path& debug_path() const;
1000
1008 bool debug_enabled() const;
1009
1017 bool wf_check_enabled() const;
1018
1026
1027 private:
1028 friend const char* ::regoGetError(regoInterpreter* rego);
1029 friend void setError(regoInterpreter* rego, const std::string& error);
1030 friend regoOutput* ::regoQuery(
1031 regoInterpreter* rego, const char* query_expr);
1032
1033 void merge(const Node& ast);
1034 std::string output_to_string(const Node& output) const;
1035 Reader m_reader;
1036 Node m_ast;
1037 std::filesystem::path m_debug_path;
1038 BuiltIns m_builtins;
1039 Rewriter m_unify;
1040 Reader m_json;
1041 Rewriter m_from_json;
1042 Rewriter m_to_input;
1043 std::size_t m_data_count;
1044
1045 std::string m_c_error;
1046 };
1047
1051 Reader reader(bool v1_compatible = false);
1052
1056 Rewriter to_input();
1057
1061 Rewriter unify(BuiltIns builtins = BuiltInsDef::create());
1062
1066 Rewriter from_json(bool as_term = false);
1067
1071 Rewriter to_json();
1072
1076 Rewriter to_yaml();
1077}
Definition rego.hh:220
Definition rego.hh:670
static std::shared_ptr< BuiltInsDef > create()
bool is_deprecated(const Location &version, const Location &name) const
bool strict_errors() const
Node call(const Location &name, const Location &version, const Nodes &args)
BuiltInsDef & register_builtins(const T &built_ins)
Definition rego.hh:734
BuiltInsDef & register_standard_builtins()
BuiltInsDef() noexcept
BuiltInsDef & register_builtin(const BuiltIn &built_in)
const BuiltIn & at(const Location &name) const
bool is_builtin(const Location &name) const
Definition rego.hh:873
Interpreter & debug_path(const std::filesystem::path &prefix)
std::string query(const std::string &query_expr)
Node add_module(const std::string &name, const std::string &contents)
Node set_input_term(const std::string &term)
Interpreter(bool v1_compatible=false)
Node add_data_json_file(const std::filesystem::path &path)
Node set_input_json_file(const std::filesystem::path &path)
friend regoOutput * regoQuery(regoInterpreter *rego, const char *query_expr)
Node set_input(const Node &node)
BuiltInsDef & builtins() const
Node add_data_json(const std::string &json)
friend const char * regoGetError(regoInterpreter *rego)
Interpreter & wf_check_enabled(bool enabled)
Node add_data(const Node &node)
Interpreter & debug_enabled(bool enabled)
Node raw_query(const std::string &query_expr)
Node add_module_file(const std::filesystem::path &path)
Definition rego.hh:311
bool exclude_got() const
const std::string & func() const
const Token & type() const
UnwrapOpt(std::size_t index)
bool specify_number() const
const std::string & pre() const
const std::string & code() const
const std::string & message() const
Node unwrap(const Nodes &args) const
const std::vector< Token > & types() const
Definition rego.hh:17
void set_log_level(LogLevel level)
bool get_bool(const Node &node)
std::optional< Node > try_get_item(const Node &node, const std::string_view &key)
Node scalar()
Node object_item(const Node &key_term, const Node &val_term)
Node set(const Nodes &set_members)
Node object(const Nodes &object_items)
Rewriter to_input()
BigInt get_int(const Node &node)
double get_double(const Node &node)
Node unwrap_arg(const Nodes &args, const UnwrapOpt &options)
Node err(NodeRange &r, const std::string &msg, const std::string &code=UnknownError)
std::optional< BigInt > try_get_int(const Node &node)
void set_tzdata_path(const std::filesystem::path &path)
Reader reader(bool v1_compatible=false)
Rewriter to_yaml()
Rewriter unify(BuiltIns builtins=BuiltInsDef::create())
std::shared_ptr< BuiltInDef > BuiltIn
Definition rego.hh:206
Rewriter from_json(bool as_term=false)
std::function< Node(const Nodes &)> BuiltInBehavior
Definition rego.hh:209
Node version()
UnwrapResult unwrap(const Node &term, const Token &type)
const std::size_t AnyArity
Definition rego.hh:578
std::string to_key(const trieste::Node &node, bool set_as_array=false, bool sort_arrays=false)
std::string get_string(const Node &node)
Node array(const Nodes &array_members)
LogLevel
Definition rego.hh:831
Rewriter to_json()
std::string set_log_level_from_string(const std::string &level)
Definition rego.hh:625
BuiltInDef(Location name_, std::size_t arity_, BuiltInBehavior behavior_)
virtual void clear()
BuiltInBehavior behavior
Definition rego.hh:636
std::size_t arity
Definition rego.hh:633
Location name
Definition rego.hh:627
static BuiltIn create(const Location &name, std::size_t arity, BuiltInBehavior behavior)
Definition rego.hh:284
bool success
Definition rego.hh:289
Node node
Definition rego.hh:286