Skip to content

Commit 8326a6d

Browse files
committed
review feedback
Signed-off-by: Shaobo He <[email protected]>
1 parent 170e707 commit 8326a6d

File tree

2 files changed

+47
-57
lines changed

2 files changed

+47
-57
lines changed

cedar-policy-core/src/expr_builder.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::{
2525
BinaryOp, EntityType, ExpressionConstructionError, Literal, Name, Pattern, SlotId, UnaryOp,
2626
Unknown, Var,
2727
},
28-
parser::{cst, cst_to_ast::construct_exprs_extended_has, Loc},
28+
parser::{cst, Loc},
2929
};
3030

3131
#[cfg(feature = "tolerant-ast")]
@@ -183,7 +183,49 @@ pub trait ExprBuilder: Clone {
183183
/// Create an `Expr` which tests for the existence of a given
184184
/// non-empty list of attributes on a given `Entity` or record.
185185
fn extended_has_attr(self, expr: Self::Expr, attrs: &NonEmpty<SmolStr>) -> Self::Expr {
186-
construct_exprs_extended_has::<Self>(expr, attrs, None)
186+
let (first, rest) = attrs.split_first();
187+
let has_expr = Self::new()
188+
.with_maybe_source_loc(self.loc())
189+
.has_attr(expr.clone(), first.to_owned());
190+
let get_expr = Self::new()
191+
.with_maybe_source_loc(self.loc())
192+
.get_attr(expr, first.to_owned());
193+
// Foldl on the attribute list
194+
// It produces the following for `principal has contactInfo.address.zip`
195+
// Expr.and
196+
// (Expr.and
197+
// (Expr.hasAttr (Expr.var .principal) "contactInfo")
198+
// (Expr.hasAttr
199+
// (Expr.getAttr (Expr.var .principal) "contactInfo")
200+
// "address"))
201+
// (Expr.hasAttr
202+
// (Expr.getAttr
203+
// (Expr.getAttr (Expr.var .principal) "contactInfo")
204+
// "address")
205+
// "zip")
206+
// This is sound. However, the evaluator has to recur multiple times to the
207+
// left-most node to evaluate the existence of the first attribute. The
208+
// desugared expression should be the following to avoid the issue above,
209+
// Expr.and
210+
// Expr.hasAttr (Expr.var .principal) "contactInfo"
211+
// (Expr.and
212+
// (Expr.hasAttr (Expr.getAttr (Expr.var .principal) "contactInfo")"address")
213+
// (Expr.hasAttr ..., "zip"))
214+
rest.iter()
215+
.fold((has_expr, get_expr), |(has_expr, get_expr), attr| {
216+
(
217+
Self::new().with_maybe_source_loc(self.loc()).and(
218+
has_expr,
219+
Self::new()
220+
.with_maybe_source_loc(self.loc())
221+
.has_attr(get_expr.clone(), attr.to_owned()),
222+
),
223+
Self::new()
224+
.with_maybe_source_loc(self.loc())
225+
.get_attr(get_expr, attr.to_owned()),
226+
)
227+
})
228+
.0
187229
}
188230

189231
/// Create a 'like' expression.

cedar-policy-core/src/parser/cst_to_ast.rs

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,11 +1473,9 @@ impl Node<Option<cst::Relation>> {
14731473
});
14741474
let (target, field) = flatten_tuple_2(maybe_target, maybe_field)?;
14751475
Ok(ExprOrSpecial::Expr {
1476-
expr: construct_exprs_extended_has::<Build>(
1477-
target,
1478-
&field,
1479-
self.loc.as_loc_ref(),
1480-
),
1476+
expr: Build::new()
1477+
.with_maybe_source_loc(self.loc.as_loc_ref())
1478+
.extended_has_attr(target, &field),
14811479
loc: self.loc.clone(),
14821480
})
14831481
}
@@ -2405,56 +2403,6 @@ fn construct_expr_rel<Build: ExprBuilder>(
24052403
}
24062404
}
24072405

2408-
pub(crate) fn construct_exprs_extended_has<Build: ExprBuilder>(
2409-
t: Build::Expr,
2410-
attrs: &NonEmpty<SmolStr>,
2411-
loc: Option<&Loc>,
2412-
) -> Build::Expr {
2413-
let (first, rest) = attrs.split_first();
2414-
let has_expr = Build::new()
2415-
.with_maybe_source_loc(loc)
2416-
.has_attr(t.clone(), first.to_owned());
2417-
let get_expr = Build::new()
2418-
.with_maybe_source_loc(loc)
2419-
.get_attr(t, first.to_owned());
2420-
// Foldl on the attribute list
2421-
// It produces the following for `principal has contactInfo.address.zip`
2422-
// Expr.and
2423-
// (Expr.and
2424-
// (Expr.hasAttr (Expr.var .principal) "contactInfo")
2425-
// (Expr.hasAttr
2426-
// (Expr.getAttr (Expr.var .principal) "contactInfo")
2427-
// "address"))
2428-
// (Expr.hasAttr
2429-
// (Expr.getAttr
2430-
// (Expr.getAttr (Expr.var .principal) "contactInfo")
2431-
// "address")
2432-
// "zip")
2433-
// This is sound. However, the evaluator has to recur multiple times to the
2434-
// left-most node to evaluate the existence of the first attribute. The
2435-
// desugared expression should be the following to avoid the issue above,
2436-
// Expr.and
2437-
// Expr.hasAttr (Expr.var .principal) "contactInfo"
2438-
// (Expr.and
2439-
// (Expr.hasAttr (Expr.getAttr (Expr.var .principal) "contactInfo")"address")
2440-
// (Expr.hasAttr ..., "zip"))
2441-
rest.iter()
2442-
.fold((has_expr, get_expr), |(has_expr, get_expr), attr| {
2443-
(
2444-
Build::new().with_maybe_source_loc(loc).and(
2445-
has_expr,
2446-
Build::new()
2447-
.with_maybe_source_loc(loc)
2448-
.has_attr(get_expr.clone(), attr.to_owned()),
2449-
),
2450-
Build::new()
2451-
.with_maybe_source_loc(loc)
2452-
.get_attr(get_expr, attr.to_owned()),
2453-
)
2454-
})
2455-
.0
2456-
}
2457-
24582406
// PANIC SAFETY: Unit Test Code
24592407
#[allow(clippy::panic)]
24602408
// PANIC SAFETY: Unit Test Code

0 commit comments

Comments
 (0)