Allow literals in statements (#276)

Implements #229 and #261.
This commit is contained in:
Daniel Gulotta 2025-06-13 10:27:19 -07:00 committed by GitHub
parent 21ab3c2d0d
commit 7d0d3ad769
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 992 additions and 825 deletions

View file

@ -115,7 +115,7 @@ mod tests {
fn test_e2e_simple_request() -> Result<(), LangError> {
let input = r#"
REQUEST(
ValueOf(?ConstPod["my_val"], 0x0000000000000000000000000000000000000000000000000000000000000001)
Equal(?ConstPod["my_val"], 0x0000000000000000000000000000000000000000000000000000000000000001)
Lt(?GovPod["dob"], ?ConstPod["my_val"])
)
"#;
@ -133,7 +133,7 @@ mod tests {
// Expected structure
let expected_templates = vec![
StatementTmpl {
pred: Predicate::Native(NativePredicate::ValueOf),
pred: Predicate::Native(NativePredicate::Equal),
args: vec![
sta_ak(("ConstPod", 0), k("my_val")), // ?ConstPod["my_val"] -> Wildcard(0), Key("my_val")
sta_lit(SELF_ID_HASH),
@ -158,7 +158,7 @@ mod tests {
let input = r#"
uses_private(A, private: Temp) = AND(
Equal(?A["input_key"], ?Temp["const_key"])
ValueOf(?Temp["const_key"], "some_value")
Equal(?Temp["const_key"], "some_value")
)
"#;
@ -182,7 +182,7 @@ mod tests {
],
},
StatementTmpl {
pred: Predicate::Native(NativePredicate::ValueOf),
pred: Predicate::Native(NativePredicate::Equal),
args: vec![
sta_ak(("Temp", 1), k("const_key")), // ?Temp["const_key"] -> Wildcard(1), Key("const_key")
sta_lit("some_value"), // Literal("some_value")
@ -390,8 +390,8 @@ mod tests {
Lt(?gov["dateOfBirth"], ?SELF_HOLDER_18Y["const_18y"])
Equal(?pay["startDate"], ?SELF_HOLDER_1Y["const_1y"])
Equal(?gov["socialSecurityNumber"], ?pay["socialSecurityNumber"])
ValueOf(?SELF_HOLDER_18Y["const_18y"], 1169909388)
ValueOf(?SELF_HOLDER_1Y["const_1y"], 1706367566)
Equal(?SELF_HOLDER_18Y["const_18y"], 1169909388)
Equal(?SELF_HOLDER_1Y["const_1y"], 1706367566)
)
"#;
@ -463,9 +463,9 @@ mod tests {
sta_ak((wc_pay.name.as_str(), wc_pay.index), ssn_key.clone()),
],
},
// 5. ValueOf(?SELF_HOLDER_18Y["const_18y"], 1169909388)
// 5. Equal(?SELF_HOLDER_18Y["const_18y"], 1169909388)
StatementTmpl {
pred: Predicate::Native(NativePredicate::ValueOf),
pred: Predicate::Native(NativePredicate::Equal),
args: vec![
sta_ak(
(wc_self_18y.name.as_str(), wc_self_18y.index),
@ -474,9 +474,9 @@ mod tests {
sta_lit(now_minus_18y_val.clone()),
],
},
// 6. ValueOf(?SELF_HOLDER_1Y["const_1y"], 1706367566)
// 6. Equal(?SELF_HOLDER_1Y["const_1y"], 1706367566)
StatementTmpl {
pred: Predicate::Native(NativePredicate::ValueOf),
pred: Predicate::Native(NativePredicate::Equal),
args: vec![
sta_ak(
(wc_self_1y.name.as_str(), wc_self_1y.index),
@ -518,19 +518,19 @@ mod tests {
let input = r#"
eth_friend(src_key, dst_key, private: attestation_pod) = AND(
ValueOf(?attestation_pod["_type"], 1)
Equal(?attestation_pod["_type"], 1)
Equal(?attestation_pod["_signer"], SELF[?src_key])
Equal(?attestation_pod["attestation"], SELF[?dst_key])
)
eth_dos_distance_base(src_key, dst_key, distance_key) = AND(
Equal(SELF[?src_key], SELF[?dst_key])
ValueOf(SELF[?distance_key], 0)
Equal(SELF[?distance_key], 0)
)
eth_dos_distance_ind(src_key, dst_key, distance_key, private: one_key, shorter_distance_key, intermed_key) = AND(
eth_dos_distance(?src_key, ?dst_key, ?distance_key)
ValueOf(SELF[?one_key], 1)
Equal(SELF[?one_key], 1)
SumOf(SELF[?distance_key], SELF[?shorter_distance_key], SELF[?one_key])
eth_friend(?intermed_key, ?dst_key)
)
@ -558,7 +558,7 @@ mod tests {
// eth_friend (Index 0)
let expected_friend_stmts = vec![
StatementTmpl {
pred: Predicate::Native(NativePredicate::ValueOf),
pred: Predicate::Native(NativePredicate::Equal),
args: vec![
sta_ak(("attestation_pod", 2), k("_type")), // Pub(0-1), Priv(2)
sta_lit(PodType::MockSigned),
@ -598,7 +598,7 @@ mod tests {
],
},
StatementTmpl {
pred: Predicate::Native(NativePredicate::ValueOf),
pred: Predicate::Native(NativePredicate::Equal),
args: vec![sta_ak_self(ko_wc("distance_key", 2)), sta_lit(0i64)],
},
];
@ -625,7 +625,7 @@ mod tests {
],
},
StatementTmpl {
pred: Predicate::Native(NativePredicate::ValueOf),
pred: Predicate::Native(NativePredicate::Equal),
args: vec![sta_ak_self(ko_wc("one_key", 3)), sta_lit(1i64)], // private arg
},
StatementTmpl {

View file

@ -27,7 +27,8 @@ fn get_span(pair: &Pair<Rule>) -> (usize, usize) {
pub fn native_predicate_from_string(s: &str) -> Option<NativePredicate> {
match s {
"ValueOf" => Some(NativePredicate::ValueOf),
// TODO: update any code that still uses ValueOf to use Equal instead
"ValueOf" => Some(NativePredicate::Equal),
"Equal" => Some(NativePredicate::Equal),
"NotEqual" => Some(NativePredicate::NotEqual),
// Syntactic sugar for Gt/GtEq is handled at a later stage
@ -347,17 +348,16 @@ fn validate_and_build_statement_template(
) -> Result<StatementTmplBuilder, ProcessorError> {
match pred {
Predicate::Native(native_pred) => {
let (expected_arity, mapped_pred_for_arity_check) = match native_pred {
NativePredicate::Gt => (2, NativePredicate::Lt),
NativePredicate::GtEq => (2, NativePredicate::LtEq),
NativePredicate::ValueOf
let expected_arity = match native_pred {
NativePredicate::Gt
| NativePredicate::GtEq
| NativePredicate::Equal
| NativePredicate::NotEqual
| NativePredicate::Lt
| NativePredicate::LtEq
| NativePredicate::SetContains
| NativePredicate::DictNotContains
| NativePredicate::SetNotContains => (2, *native_pred),
| NativePredicate::SetNotContains => 2,
NativePredicate::NotContains
| NativePredicate::Contains
| NativePredicate::ArrayContains
@ -365,8 +365,8 @@ fn validate_and_build_statement_template(
| NativePredicate::SumOf
| NativePredicate::ProductOf
| NativePredicate::MaxOf
| NativePredicate::HashOf => (3, *native_pred),
NativePredicate::None | NativePredicate::False => (0, *native_pred),
| NativePredicate::HashOf => 3,
NativePredicate::None | NativePredicate::False => 0,
};
if args.len() != expected_arity {
@ -378,30 +378,9 @@ fn validate_and_build_statement_template(
});
}
if mapped_pred_for_arity_check == NativePredicate::ValueOf {
if !matches!(args.get(0), Some(BuilderArg::Key(..))) {
return Err(ProcessorError::TypeError {
expected: "Anchored Key".to_string(),
found: args
.get(0)
.map_or("None".to_string(), |a| format!("{:?}", a)),
item: format!("argument 1 of native predicate '{}'", stmt_name_str),
span: Some(stmt_span),
});
}
if !matches!(args.get(1), Some(BuilderArg::Literal(..))) {
return Err(ProcessorError::TypeError {
expected: "Literal".to_string(),
found: args
.get(1)
.map_or("None".to_string(), |a| format!("{:?}", a)),
item: format!("argument 2 of native predicate '{}'", stmt_name_str),
span: Some(stmt_span),
});
}
} else if expected_arity > 0 {
if expected_arity > 0 {
for (i, arg) in args.iter().enumerate() {
if !matches!(arg, BuilderArg::Key(..)) {
if !matches!(arg, BuilderArg::Key(..) | BuilderArg::Literal(..)) {
return Err(ProcessorError::TypeError {
expected: "Anchored Key".to_string(),
found: format!("{:?}", arg),
@ -1056,7 +1035,7 @@ mod processor_tests {
fn test_fp_multiple_predicates() -> Result<(), ProcessorError> {
let input = r#"
pred1(X) = AND( Equal(?X["k"],?X["k"]) )
pred2(Y, Z) = OR( ValueOf(?Y["v"], 123) )
pred2(Y, Z) = OR( Equal(?Y["v"], 123) )
"#;
let pairs = get_document_content_pairs(input)?;
let params = Params::default();