Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cedar-policy-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ thiserror = "1.0"
smol_str = { version = "0.2", features = ["serde"] }
stacker = "0.1.15"
arbitrary = { version = "1", features = ["derive"], optional = true }
miette = "5.9.0"
miette = { version = "5.9.0", features = ["serde"] }

# decimal extension requires regex
regex = { version = "1.8", features = ["unicode"], optional = true }
Expand Down
74 changes: 33 additions & 41 deletions cedar-policy-core/src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@
* limitations under the License.
*/

use crate::{
ast::*,
parser::{err::ParseErrors, SourceInfo},
};
use crate::{ast::*, parser::err::ParseErrors};
use serde::{Deserialize, Serialize};
use smol_str::SmolStr;
use std::{
Expand All @@ -37,7 +34,7 @@ use thiserror::Error;
#[derive(Serialize, Deserialize, Hash, Debug, Clone, PartialEq, Eq)]
pub struct Expr<T = ()> {
expr_kind: ExprKind<T>,
source_info: Option<SourceInfo>,
source_span: Option<miette::SourceSpan>,
data: T,
}

Expand Down Expand Up @@ -160,7 +157,7 @@ pub enum ExprKind<T = ()> {
impl From<Value> for Expr {
fn from(v: Value) -> Self {
match v {
Value::Lit(l) => Expr::val(l),
Value::Lit(lit) => Expr::val(lit),
Value::Set(s) => Expr::set(s.iter().map(|v| Expr::from(v.clone()))),
// PANIC SAFETY: cannot have duplicate key because the input was already a BTreeMap
#[allow(clippy::expect_used)]
Expand All @@ -185,10 +182,10 @@ impl From<PartialValue> for Expr {
}

impl<T> Expr<T> {
fn new(expr_kind: ExprKind<T>, source_info: Option<SourceInfo>, data: T) -> Self {
fn new(expr_kind: ExprKind<T>, source_span: Option<miette::SourceSpan>, data: T) -> Self {
Self {
expr_kind,
source_info,
source_span,
data,
}
}
Expand All @@ -215,14 +212,9 @@ impl<T> Expr<T> {
self.data
}

/// Access the data stored on the `Expr`.
pub fn source_info(&self) -> &Option<SourceInfo> {
&self.source_info
}

/// Access the data stored on the `Expr`, taking ownership.
pub fn into_source_info(self) -> Option<SourceInfo> {
self.source_info
/// Access the `SourceSpan` stored on the `Expr`.
pub fn source_span(&self) -> Option<miette::SourceSpan> {
self.source_span
}

/// Update the data for this `Expr`. A convenient function used by the
Expand Down Expand Up @@ -659,10 +651,10 @@ impl std::fmt::Display for Unknown {
}

/// Builder for constructing `Expr` objects annotated with some `data`
/// (possibly taking default value) and optional some `source_info`.
/// (possibly taking default value) and optionally a `source_span`.
#[derive(Debug)]
pub struct ExprBuilder<T> {
source_info: Option<SourceInfo>,
source_span: Option<miette::SourceSpan>,
data: T,
}

Expand All @@ -674,7 +666,7 @@ where
/// takes a default value.
pub fn new() -> Self {
Self {
source_info: None,
source_span: None,
data: T::default(),
}
}
Expand All @@ -683,8 +675,8 @@ where
/// Defined only for `T: Default` because the caller would otherwise need to
/// provide a `data` for the intermediate `not` Expr node.
pub fn noteq(self, e1: Expr<T>, e2: Expr<T>) -> Expr<T> {
match &self.source_info {
Some(source_info) => ExprBuilder::new().with_source_info(source_info.clone()),
match self.source_span {
Some(source_span) => ExprBuilder::new().with_source_span(source_span),
None => ExprBuilder::new(),
}
.not(self.with_expr_kind(ExprKind::BinaryApp {
Expand All @@ -703,40 +695,40 @@ impl<T: Default> Default for ExprBuilder<T> {

impl<T> ExprBuilder<T> {
/// Construct a new `ExprBuild` where the specified data will be stored on
/// the `Expr`. This constructor does not populate the `source_info` field,
/// so `with_source_info` should be called if constructing an `Expr` where
/// the `Expr`. This constructor does not populate the `source_span` field,
/// so `with_source_span` should be called if constructing an `Expr` where
/// the source location is known.
pub fn with_data(data: T) -> Self {
Self {
source_info: None,
source_span: None,
data,
}
}

/// Update the `ExprBuilder` to build an expression with some known location
/// in policy source code.
pub fn with_source_info(self, source_info: SourceInfo) -> Self {
self.with_maybe_source_info(Some(source_info))
pub fn with_source_span(self, source_span: miette::SourceSpan) -> Self {
self.with_maybe_source_span(Some(source_span))
}

/// Utility used the validator to get an expression with the same source
/// location as an existing expression. This is done when reconstructing the
/// `Expr` with type information.
pub fn with_same_source_info<U>(self, expr: &Expr<U>) -> Self {
self.with_maybe_source_info(expr.source_info.clone())
pub fn with_same_source_span<U>(self, expr: &Expr<U>) -> Self {
self.with_maybe_source_span(expr.source_span)
}

/// internally used to update SourceInfo to the given `Some` or `None`
fn with_maybe_source_info(mut self, maybe_source_info: Option<SourceInfo>) -> Self {
self.source_info = maybe_source_info;
/// internally used to update SourceSpan to the given `Some` or `None`
fn with_maybe_source_span(mut self, maybe_source_span: Option<miette::SourceSpan>) -> Self {
self.source_span = maybe_source_span;
self
}

/// Internally used by the following methods to construct an `Expr`
/// containing the `data` and `source_info` in this `ExprBuilder` with some
/// containing the `data` and `source_span` in this `ExprBuilder` with some
/// inner `ExprKind`.
fn with_expr_kind(self, expr_kind: ExprKind<T>) -> Expr<T> {
Expr::new(expr_kind, self.source_info, self.data)
Expr::new(expr_kind, self.source_span, self.data)
}

/// Create an `Expr` that's just a single `Literal`.
Expand Down Expand Up @@ -1023,11 +1015,11 @@ impl<T: Clone> ExprBuilder<T> {
///
/// This may create multiple AST `&&` nodes. If it does, all the nodes will have the same
/// source location and the same `T` data (taken from this builder) unless overridden, e.g.,
/// with another call to `with_source_info()`.
/// with another call to `with_source_span()`.
pub fn and_nary(self, first: Expr<T>, others: impl IntoIterator<Item = Expr<T>>) -> Expr<T> {
others.into_iter().fold(first, |acc, next| {
Self::with_data(self.data.clone())
.with_maybe_source_info(self.source_info.clone())
.with_maybe_source_span(self.source_span.clone())
.and(acc, next)
})
}
Expand All @@ -1038,11 +1030,11 @@ impl<T: Clone> ExprBuilder<T> {
///
/// This may create multiple AST `||` nodes. If it does, all the nodes will have the same
/// source location and the same `T` data (taken from this builder) unless overridden, e.g.,
/// with another call to `with_source_info()`.
/// with another call to `with_source_span()`.
pub fn or_nary(self, first: Expr<T>, others: impl IntoIterator<Item = Expr<T>>) -> Expr<T> {
others.into_iter().fold(first, |acc, next| {
Self::with_data(self.data.clone())
.with_maybe_source_info(self.source_info.clone())
.with_maybe_source_span(self.source_span.clone())
.or(acc, next)
})
}
Expand All @@ -1051,7 +1043,7 @@ impl<T: Clone> ExprBuilder<T> {
pub fn greater(self, e1: Expr<T>, e2: Expr<T>) -> Expr<T> {
// e1 > e2 is defined as !(e1 <= e2)
let leq = Self::with_data(self.data.clone())
.with_maybe_source_info(self.source_info.clone())
.with_maybe_source_span(self.source_span.clone())
.lesseq(e1, e2);
self.not(leq)
}
Expand All @@ -1060,7 +1052,7 @@ impl<T: Clone> ExprBuilder<T> {
pub fn greatereq(self, e1: Expr<T>, e2: Expr<T>) -> Expr<T> {
// e1 >= e2 is defined as !(e1 < e2)
let leq = Self::with_data(self.data.clone())
.with_maybe_source_info(self.source_info.clone())
.with_maybe_source_span(self.source_span.clone())
.less(e1, e2);
self.not(leq)
}
Expand Down Expand Up @@ -1114,7 +1106,7 @@ impl<T> Expr<T> {
pub fn eq_shape<U>(&self, other: &Expr<U>) -> bool {
use ExprKind::*;
match (self.expr_kind(), other.expr_kind()) {
(Lit(l), Lit(l1)) => l == l1,
(Lit(lit), Lit(lit1)) => lit == lit1,
(Var(v), Var(v1)) => v == v1,
(Slot(s), Slot(s1)) => s == s1,
(
Expand Down Expand Up @@ -1234,7 +1226,7 @@ impl<T> Expr<T> {
{
mem::discriminant(self).hash(state);
match self.expr_kind() {
ExprKind::Lit(l) => l.hash(state),
ExprKind::Lit(lit) => lit.hash(state),
ExprKind::Var(v) => v.hash(state),
ExprKind::Slot(s) => s.hash(state),
ExprKind::Unknown(u) => u.hash(state),
Expand Down
6 changes: 3 additions & 3 deletions cedar-policy-core/src/ast/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1652,7 +1652,7 @@ mod test {
ast::{entity, name, EntityUID},
parser::{
err::{ParseError, ParseErrors, ToASTError, ToASTErrorKind},
parse_policy, SourceInfo,
parse_policy,
},
};

Expand Down Expand Up @@ -2000,7 +2000,7 @@ mod test {
ToASTErrorKind::UnexpectedTemplate {
slot: crate::parser::cst::Slot::Principal
},
SourceInfo(0..50)
miette::SourceSpan::from(0..50)
))
);
assert_eq!(errs.len(), 1);
Expand All @@ -2011,7 +2011,7 @@ mod test {
ToASTErrorKind::UnexpectedTemplate {
slot: crate::parser::cst::Slot::Principal
},
SourceInfo(50..74)
miette::SourceSpan::from(50..74)
))));
assert_eq!(errs.len(), 2);
}
Expand Down
7 changes: 2 additions & 5 deletions cedar-policy-core/src/ast/restricted_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,10 +622,7 @@ pub enum RestrictedExprParseError {
#[cfg(test)]
mod test {
use super::*;
use crate::parser::{
err::{ParseError, ToASTError, ToASTErrorKind},
SourceInfo,
};
use crate::parser::err::{ParseError, ToASTError, ToASTErrorKind};
use std::str::FromStr;

#[test]
Expand Down Expand Up @@ -675,7 +672,7 @@ mod test {
Err(RestrictedExprParseError::Parse(ParseErrors(vec![
ParseError::ToAST(ToASTError::new(
ToASTErrorKind::DuplicateKeyInRecordLiteral { key: "foo".into() },
SourceInfo(0..32)
miette::SourceSpan::from(0..32)
))
]))),
)
Expand Down
4 changes: 2 additions & 2 deletions cedar-policy-core/src/ast/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl TryFrom<Expr> for Value {

fn try_from(value: Expr) -> Result<Self, Self::Error> {
match value.into_expr_kind() {
ExprKind::Lit(l) => Ok(Value::Lit(l)),
ExprKind::Lit(lit) => Ok(Value::Lit(lit)),
ExprKind::Unknown(_) => Err(NotValue::NotValue),
ExprKind::Var(_) => Err(NotValue::NotValue),
ExprKind::Slot(_) => Err(NotValue::NotValue),
Expand Down Expand Up @@ -223,7 +223,7 @@ impl FromIterator<Value> for Set {
literals
.into_iter()
.map(|v| match v {
Value::Lit(l) => l,
Value::Lit(lit) => lit,
// PANIC SAFETY: This is unreachable as every item in `literals` matches Value::Lit
#[allow(clippy::unreachable)]
_ => unreachable!(),
Expand Down
10 changes: 6 additions & 4 deletions cedar-policy-core/src/est.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,13 @@ impl TryFrom<cst::Policy> for Policy {
.conds
.into_iter()
.map(|node| {
let (cond, l) = node.into_inner();
let (cond, span) = node.into_inner();
let cond = cond.ok_or_else(|| {
ParseErrors(vec![
ToASTError::new(ToASTErrorKind::EmptyClause(None), l).into()
])
ParseErrors(vec![ToASTError::new(
ToASTErrorKind::EmptyClause(None),
span,
)
.into()])
})?;
cond.try_into()
})
Expand Down
Loading