// 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: Span, value: Value, eidx: u32, }, RawString { span: Span, value: Value, eidx: u32, }, Number { span: Span, value: Value, eidx: u32, }, Bool { span: Span, value: Value, eidx: u32, }, Null { span: Span, value: Value, eidx: u32, }, Var { span: Span, value: Value, eidx: u32, }, // array Array { span: Span, items: Vec>, eidx: u32, }, // set Set { span: Span, items: Vec>, eidx: u32, }, Object { span: Span, fields: Vec<(Span, Ref, Ref)>, eidx: u32, }, // Comprehensions ArrayCompr { span: Span, term: Ref, query: Ref, eidx: u32, }, SetCompr { span: Span, term: Ref, query: Ref, eidx: u32, }, ObjectCompr { span: Span, key: Ref, value: Ref, query: Ref, eidx: u32, }, Call { span: Span, fcn: Ref, params: Vec>, eidx: u32, }, UnaryExpr { span: Span, expr: Ref, eidx: u32, }, // ref RefDot { span: Span, refr: Ref, field: (Span, Value), eidx: u32, }, RefBrack { span: Span, refr: Ref, index: Ref, eidx: u32, }, // Infix expressions BinExpr { span: Span, op: BinOp, lhs: Ref, rhs: Ref, eidx: u32, }, BoolExpr { span: Span, op: BoolOp, lhs: Ref, rhs: Ref, eidx: u32, }, ArithExpr { span: Span, op: ArithOp, lhs: Ref, rhs: Ref, eidx: u32, }, AssignExpr { span: Span, op: AssignOp, lhs: Ref, rhs: Ref, eidx: u32, }, Membership { span: Span, key: Option>, value: Ref, collection: Ref, eidx: u32, }, #[cfg(feature = "rego-extensions")] OrExpr { span: Span, lhs: Ref, rhs: Ref, eidx: u32, }, } impl Expr { pub const fn span(&self) -> &Span { match *self { Self::String { ref span, .. } | Self::RawString { ref span, .. } | Self::Number { ref span, .. } | Self::Bool { ref span, .. } | Self::Null { ref span, .. } | Self::Var { ref span, .. } | Self::Array { ref span, .. } | Self::Set { ref span, .. } | Self::Object { ref span, .. } | Self::ArrayCompr { ref span, .. } | Self::SetCompr { ref span, .. } | Self::ObjectCompr { ref span, .. } | Self::Call { ref span, .. } | Self::UnaryExpr { ref span, .. } | Self::RefDot { ref span, .. } | Self::RefBrack { ref span, .. } | Self::BinExpr { ref span, .. } | Self::BoolExpr { ref span, .. } | Self::ArithExpr { ref span, .. } | Self::AssignExpr { ref span, .. } | Self::Membership { ref span, .. } => span, #[cfg(feature = "rego-extensions")] Self::OrExpr { ref span, .. } => span, } } pub const fn eidx(&self) -> u32 { match *self { Self::String { eidx, .. } | Self::RawString { eidx, .. } | Self::Number { eidx, .. } | Self::Bool { eidx, .. } | Self::Null { eidx, .. } | Self::Var { eidx, .. } | Self::Array { eidx, .. } | Self::Set { eidx, .. } | Self::Object { eidx, .. } | Self::ArrayCompr { eidx, .. } | Self::SetCompr { eidx, .. } | Self::ObjectCompr { eidx, .. } | Self::Call { eidx, .. } | Self::UnaryExpr { eidx, .. } | Self::RefDot { eidx, .. } | Self::RefBrack { eidx, .. } | Self::BinExpr { eidx, .. } | Self::BoolExpr { eidx, .. } | Self::ArithExpr { eidx, .. } | Self::AssignExpr { eidx, .. } | Self::Membership { eidx, .. } => eidx, #[cfg(feature = "rego-extensions")] Self::OrExpr { eidx, .. } => eidx, } } } #[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, pub sidx: u32, } #[derive(Debug)] #[cfg_attr(feature = "ast", derive(serde::Serialize))] pub struct Query { pub span: Span, pub stmts: Vec, pub qidx: u32, } #[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 const fn span(&self) -> &Span { match *self { Self::Spec { ref span, .. } | Self::Default { ref 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, // Target name if specified via __target__ rule #[cfg_attr(feature = "ast", serde(skip_serializing_if = "Option::is_none"))] pub target: Option, // Number of expressions in the module. pub num_expressions: u32, // Number of statements in the module. pub num_statements: u32, // Number of queries in the module. pub num_queries: u32, } pub type ExprRef = Ref;