// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. use crate::lexer::*; use crate::value::Value; use crate::*; use core::{cmp, fmt, ops::Deref}; #[derive(Debug, PartialEq, Eq, Clone)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub enum BinOp { Intersection, Union, } #[derive(Debug, PartialEq, Eq, Clone)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub enum ArithOp { Add, Sub, Mul, Div, Mod, } #[derive(Debug, PartialEq, Eq, Clone)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub enum BoolOp { Lt, Le, Eq, Ge, Gt, Ne, } #[derive(Debug, PartialEq, Eq, Clone)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub enum AssignOp { Eq, ColEq, } #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub struct NodeRef { #[cfg_attr(feature = "ast", serde(flatten))] r: Rc, } impl Clone for NodeRef { fn clone(&self) -> Self { Self { r: self.r.clone() } } } impl fmt::Debug for NodeRef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.r.as_ref().fmt(f) } } impl cmp::PartialEq for NodeRef { fn eq(&self, other: &Self) -> bool { Rc::as_ptr(&self.r).eq(&Rc::as_ptr(&other.r)) } } impl cmp::Eq for NodeRef {} impl cmp::Ord for NodeRef { fn cmp(&self, other: &Self) -> cmp::Ordering { Rc::as_ptr(&self.r).cmp(&Rc::as_ptr(&other.r)) } } impl cmp::PartialOrd for NodeRef { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Deref for NodeRef { type Target = T; fn deref(&self) -> &Self::Target { &self.r } } impl AsRef for NodeRef { fn as_ref(&self) -> &T { self.deref() } } impl NodeRef { pub fn new(t: T) -> Self { Self { r: Rc::new(t) } } } pub type Ref = NodeRef; #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub enum Expr { // Simple items that only have a span as content. String((Span, Value)), RawString((Span, Value)), Number((Span, Value)), True(Span), False(Span), Null(Span), Var((Span, Value)), // array Array { span: Span, items: Vec>, }, // set Set { span: Span, items: Vec>, }, Object { span: Span, fields: Vec<(Span, Ref, Ref)>, }, // Comprehensions ArrayCompr { span: Span, term: Ref, query: Ref, }, SetCompr { span: Span, term: Ref, query: Ref, }, ObjectCompr { span: Span, key: Ref, value: Ref, query: Ref, }, Call { span: Span, fcn: Ref, params: Vec>, }, UnaryExpr { span: Span, expr: Ref, }, // ref RefDot { span: Span, refr: Ref, field: (Span, Value), }, RefBrack { span: Span, refr: Ref, index: Ref, }, // Infix expressions BinExpr { span: Span, op: BinOp, lhs: Ref, rhs: Ref, }, BoolExpr { span: Span, op: BoolOp, lhs: Ref, rhs: Ref, }, ArithExpr { span: Span, op: ArithOp, lhs: Ref, rhs: Ref, }, AssignExpr { span: Span, op: AssignOp, lhs: Ref, rhs: Ref, }, Membership { span: Span, key: Option>, value: Ref, collection: Ref, }, #[cfg(feature = "rego-extensions")] OrExpr { span: Span, lhs: Ref, rhs: Ref, }, } impl Expr { pub fn span(&self) -> &Span { use Expr::*; match self { String(s) | RawString(s) | Number(s) | Var(s) => &s.0, True(s) | False(s) | Null(s) => s, Array { span, .. } | Set { span, .. } | Object { span, .. } | ArrayCompr { span, .. } | SetCompr { span, .. } | ObjectCompr { span, .. } | Call { span, .. } | UnaryExpr { span, .. } | RefDot { span, .. } | RefBrack { span, .. } | BinExpr { span, .. } | BoolExpr { span, .. } | ArithExpr { span, .. } | AssignExpr { span, .. } | Membership { span, .. } => span, #[cfg(feature = "rego-extensions")] OrExpr { span, .. } => span, } } } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub enum Literal { SomeVars { span: Span, vars: Vec, }, SomeIn { span: Span, key: Option>, value: Ref, collection: Ref, }, Expr { span: Span, expr: Ref, }, NotExpr { span: Span, expr: Ref, }, Every { span: Span, key: Option, value: Span, domain: Ref, query: Ref, }, } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub struct WithModifier { pub span: Span, pub refr: Ref, pub r#as: Ref, } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub struct LiteralStmt { pub span: Span, pub literal: Literal, #[cfg_attr(feature = "ast", serde(skip_serializing_if = "Vec::is_empty"))] pub with_mods: Vec, } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub struct Query { pub span: Span, pub stmts: Vec, } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub struct RuleAssign { pub span: Span, pub op: AssignOp, pub value: Ref, } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub struct RuleBody { pub span: Span, pub assign: Option, pub query: Ref, } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub enum RuleHead { Compr { span: Span, refr: Ref, assign: Option, }, Set { span: Span, refr: Ref, key: Option>, }, Func { span: Span, refr: Ref, args: Vec>, assign: Option, }, } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub enum Rule { Spec { span: Span, head: RuleHead, bodies: Vec, }, Default { span: Span, refr: Ref, args: Vec>, op: AssignOp, value: Ref, }, } impl Rule { pub fn span(&self) -> &Span { match self { Self::Spec { span, .. } | Self::Default { span, .. } => span, } } } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub struct Package { pub span: Span, pub refr: Ref, } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub struct Import { pub span: Span, pub refr: Ref, #[cfg_attr(feature = "ast", serde(skip_serializing_if = "Option::is_none"))] pub r#as: Option, } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub struct Module { pub package: Package, pub imports: Vec, #[cfg_attr(feature = "ast", serde(rename(serialize = "rules")))] pub policy: Vec>, pub rego_v1: bool, } pub type ExprRef = Ref;