mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
Add `or` operator to Rego languages. Available via `rego-extensions` Cargo feature. If the evaluated lhs value is not false, null or undefined it is returned. Otherwise rhs is evaluated and returned. or operator has least precedence, and is left-associative. closes #314
391 lines
7.7 KiB
Rust
391 lines
7.7 KiB
Rust
// 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<T> {
|
|
#[cfg_attr(feature = "ast", serde(flatten))]
|
|
r: Rc<T>,
|
|
}
|
|
|
|
impl<T> Clone for NodeRef<T> {
|
|
fn clone(&self) -> Self {
|
|
Self { r: self.r.clone() }
|
|
}
|
|
}
|
|
|
|
impl<T: fmt::Debug> fmt::Debug for NodeRef<T> {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
self.r.as_ref().fmt(f)
|
|
}
|
|
}
|
|
|
|
impl<T> cmp::PartialEq for NodeRef<T> {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
Rc::as_ptr(&self.r).eq(&Rc::as_ptr(&other.r))
|
|
}
|
|
}
|
|
|
|
impl<T> cmp::Eq for NodeRef<T> {}
|
|
|
|
impl<T> cmp::Ord for NodeRef<T> {
|
|
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
|
Rc::as_ptr(&self.r).cmp(&Rc::as_ptr(&other.r))
|
|
}
|
|
}
|
|
|
|
impl<T> cmp::PartialOrd for NodeRef<T> {
|
|
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
|
Some(self.cmp(other))
|
|
}
|
|
}
|
|
|
|
impl<T> Deref for NodeRef<T> {
|
|
type Target = T;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.r
|
|
}
|
|
}
|
|
|
|
impl<T> AsRef<T> for NodeRef<T> {
|
|
fn as_ref(&self) -> &T {
|
|
self.deref()
|
|
}
|
|
}
|
|
|
|
impl<T> NodeRef<T> {
|
|
pub fn new(t: T) -> Self {
|
|
Self { r: Rc::new(t) }
|
|
}
|
|
}
|
|
|
|
pub type Ref<T> = NodeRef<T>;
|
|
|
|
#[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<Ref<Expr>>,
|
|
},
|
|
|
|
// set
|
|
Set {
|
|
span: Span,
|
|
items: Vec<Ref<Expr>>,
|
|
},
|
|
|
|
Object {
|
|
span: Span,
|
|
fields: Vec<(Span, Ref<Expr>, Ref<Expr>)>,
|
|
},
|
|
|
|
// Comprehensions
|
|
ArrayCompr {
|
|
span: Span,
|
|
term: Ref<Expr>,
|
|
query: Ref<Query>,
|
|
},
|
|
|
|
SetCompr {
|
|
span: Span,
|
|
term: Ref<Expr>,
|
|
query: Ref<Query>,
|
|
},
|
|
|
|
ObjectCompr {
|
|
span: Span,
|
|
key: Ref<Expr>,
|
|
value: Ref<Expr>,
|
|
query: Ref<Query>,
|
|
},
|
|
|
|
Call {
|
|
span: Span,
|
|
fcn: Ref<Expr>,
|
|
params: Vec<Ref<Expr>>,
|
|
},
|
|
|
|
UnaryExpr {
|
|
span: Span,
|
|
expr: Ref<Expr>,
|
|
},
|
|
|
|
// ref
|
|
RefDot {
|
|
span: Span,
|
|
refr: Ref<Expr>,
|
|
field: (Span, Value),
|
|
},
|
|
|
|
RefBrack {
|
|
span: Span,
|
|
refr: Ref<Expr>,
|
|
index: Ref<Expr>,
|
|
},
|
|
|
|
// Infix expressions
|
|
BinExpr {
|
|
span: Span,
|
|
op: BinOp,
|
|
lhs: Ref<Expr>,
|
|
rhs: Ref<Expr>,
|
|
},
|
|
BoolExpr {
|
|
span: Span,
|
|
op: BoolOp,
|
|
lhs: Ref<Expr>,
|
|
rhs: Ref<Expr>,
|
|
},
|
|
|
|
ArithExpr {
|
|
span: Span,
|
|
op: ArithOp,
|
|
lhs: Ref<Expr>,
|
|
rhs: Ref<Expr>,
|
|
},
|
|
|
|
AssignExpr {
|
|
span: Span,
|
|
op: AssignOp,
|
|
lhs: Ref<Expr>,
|
|
rhs: Ref<Expr>,
|
|
},
|
|
|
|
Membership {
|
|
span: Span,
|
|
key: Option<Ref<Expr>>,
|
|
value: Ref<Expr>,
|
|
collection: Ref<Expr>,
|
|
},
|
|
|
|
#[cfg(feature = "rego-extensions")]
|
|
OrExpr {
|
|
span: Span,
|
|
lhs: Ref<Expr>,
|
|
rhs: Ref<Expr>,
|
|
},
|
|
}
|
|
|
|
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<Span>,
|
|
},
|
|
SomeIn {
|
|
span: Span,
|
|
key: Option<Ref<Expr>>,
|
|
value: Ref<Expr>,
|
|
collection: Ref<Expr>,
|
|
},
|
|
Expr {
|
|
span: Span,
|
|
expr: Ref<Expr>,
|
|
},
|
|
NotExpr {
|
|
span: Span,
|
|
expr: Ref<Expr>,
|
|
},
|
|
Every {
|
|
span: Span,
|
|
key: Option<Span>,
|
|
value: Span,
|
|
domain: Ref<Expr>,
|
|
query: Ref<Query>,
|
|
},
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
#[cfg_attr(feature = "ast", derive(serde::Serialize))]
|
|
pub struct WithModifier {
|
|
pub span: Span,
|
|
pub refr: Ref<Expr>,
|
|
pub r#as: Ref<Expr>,
|
|
}
|
|
|
|
#[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<WithModifier>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
#[cfg_attr(feature = "ast", derive(serde::Serialize))]
|
|
pub struct Query {
|
|
pub span: Span,
|
|
pub stmts: Vec<LiteralStmt>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
#[cfg_attr(feature = "ast", derive(serde::Serialize))]
|
|
pub struct RuleAssign {
|
|
pub span: Span,
|
|
pub op: AssignOp,
|
|
pub value: Ref<Expr>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
#[cfg_attr(feature = "ast", derive(serde::Serialize))]
|
|
pub struct RuleBody {
|
|
pub span: Span,
|
|
pub assign: Option<RuleAssign>,
|
|
pub query: Ref<Query>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
#[cfg_attr(feature = "ast", derive(serde::Serialize))]
|
|
pub enum RuleHead {
|
|
Compr {
|
|
span: Span,
|
|
refr: Ref<Expr>,
|
|
assign: Option<RuleAssign>,
|
|
},
|
|
Set {
|
|
span: Span,
|
|
refr: Ref<Expr>,
|
|
key: Option<Ref<Expr>>,
|
|
},
|
|
Func {
|
|
span: Span,
|
|
refr: Ref<Expr>,
|
|
args: Vec<Ref<Expr>>,
|
|
assign: Option<RuleAssign>,
|
|
},
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
#[cfg_attr(feature = "ast", derive(serde::Serialize))]
|
|
pub enum Rule {
|
|
Spec {
|
|
span: Span,
|
|
head: RuleHead,
|
|
bodies: Vec<RuleBody>,
|
|
},
|
|
Default {
|
|
span: Span,
|
|
refr: Ref<Expr>,
|
|
args: Vec<Ref<Expr>>,
|
|
op: AssignOp,
|
|
value: Ref<Expr>,
|
|
},
|
|
}
|
|
|
|
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<Expr>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
#[cfg_attr(feature = "ast", derive(serde::Serialize))]
|
|
pub struct Import {
|
|
pub span: Span,
|
|
pub refr: Ref<Expr>,
|
|
#[cfg_attr(feature = "ast", serde(skip_serializing_if = "Option::is_none"))]
|
|
pub r#as: Option<Span>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
#[cfg_attr(feature = "ast", derive(serde::Serialize))]
|
|
pub struct Module {
|
|
pub package: Package,
|
|
pub imports: Vec<Import>,
|
|
#[cfg_attr(feature = "ast", serde(rename(serialize = "rules")))]
|
|
pub policy: Vec<Ref<Rule>>,
|
|
pub rego_v1: bool,
|
|
}
|
|
|
|
pub type ExprRef = Ref<Expr>;
|