From c7b39f21f0a77e74e6084f87ee6b366c8d049c54 Mon Sep 17 00:00:00 2001 From: Rob Knight Date: Wed, 30 Jul 2025 01:35:48 +0100 Subject: [PATCH] Support SELF keyword in Podlang parser (#368) * Support SELF keyword in Podlang parser * Add pretty-printing for SELF --- src/lang/grammar.pest | 3 ++- src/lang/mod.rs | 11 ++++++++--- src/lang/pretty_print.rs | 10 ++++++++++ src/lang/processor.rs | 1 + src/middleware/mod.rs | 19 ++++++++++++++++++- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/lang/grammar.pest b/src/lang/grammar.pest index 01000cb..2eeab0b 100644 --- a/src/lang/grammar.pest +++ b/src/lang/grammar.pest @@ -68,7 +68,8 @@ literal_value = { literal_raw | literal_pod_id | literal_string | - literal_int + literal_int | + self_keyword } // Primitive literal types diff --git a/src/lang/mod.rs b/src/lang/mod.rs index e5cf9a3..1a02966 100644 --- a/src/lang/mod.rs +++ b/src/lang/mod.rs @@ -34,7 +34,7 @@ mod tests { middleware::{ hash_str, CustomPredicate, CustomPredicateBatch, CustomPredicateRef, Key, NativePredicate, Params, PodId, PodType, Predicate, RawValue, StatementTmpl, - StatementTmplArg, Value, Wildcard, KEY_SIGNER, KEY_TYPE, + StatementTmplArg, Value, Wildcard, KEY_SIGNER, KEY_TYPE, SELF, }, }; @@ -877,6 +877,7 @@ mod tests { Equal(?E["int"], {}) Equal(?F["bool"], {}) Equal(?G["sk"], {}) + Equal(?H["self"], SELF) ) "#, Value::from(pk).to_podlang_string(), @@ -895,6 +896,8 @@ mod tests { Equal(?D["string"], "hello") Equal(?E["int"], 123) Equal(?F["bool"], true) + Equal(?G["sk"], SecretKey(random_secret_key_base_64)) + Equal(?H["self"], SELF) ) */ @@ -902,8 +905,6 @@ mod tests { let processed = parse(&input, ¶ms, &[])?; let request_templates = processed.request_templates; - assert_eq!(request_templates.len(), 7); - let expected_templates = vec![ StatementTmpl { pred: Predicate::Native(NativePredicate::Equal), @@ -933,6 +934,10 @@ mod tests { pred: Predicate::Native(NativePredicate::Equal), args: vec![sta_ak(("G", 6), "sk"), sta_lit(Value::from(sk))], }, + StatementTmpl { + pred: Predicate::Native(NativePredicate::Equal), + args: vec![sta_ak(("H", 7), "self"), sta_lit(Value::from(SELF))], + }, ]; assert_eq!(request_templates, expected_templates); diff --git a/src/lang/pretty_print.rs b/src/lang/pretty_print.rs index d5f5ca1..cc58b79 100644 --- a/src/lang/pretty_print.rs +++ b/src/lang/pretty_print.rs @@ -507,6 +507,16 @@ mod tests { assert_round_trip(&input); } + #[test] + fn test_round_trip_self() { + let input = r#" + self_test(Pod) = AND( + Equal(?Pod["self"], SELF) + ) + "#; + assert_round_trip(input); + } + #[test] fn test_pretty_print_demonstration() { let input = r#" diff --git a/src/lang/processor.rs b/src/lang/processor.rs index 306eae3..aa64f3e 100644 --- a/src/lang/processor.rs +++ b/src/lang/processor.rs @@ -817,6 +817,7 @@ fn process_literal_value( })?; Ok(Value::from(secret_key)) } + Rule::self_keyword => Ok(Value::from(middleware::SELF)), _ => unreachable!("Unexpected rule: {:?}", inner_lit.as_rule()), } } diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index a3bb566..415c078 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -266,7 +266,11 @@ impl fmt::Display for TypedValue { TypedValue::PublicKey(p) => write!(f, "PublicKey({})", p), TypedValue::SecretKey(p) => write!(f, "SecretKey({})", p), TypedValue::PodId(p) => { - write!(f, "0x{}", p.0.encode_hex::()) + if *p == SELF { + write!(f, "SELF") + } else { + write!(f, "0x{}", p.0.encode_hex::()) + } } TypedValue::Raw(r) => { write!(f, "Raw(0x{})", r.encode_hex::()) @@ -341,6 +345,18 @@ impl JsonSchema for TypedValue { ..Default::default() }; + let pod_id_schema = schemars::schema::SchemaObject { + instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Object))), + object: Some(Box::new(schemars::schema::ObjectValidation { + properties: [("PodId".to_string(), gen.subschema_for::())] + .into_iter() + .collect(), + required: ["PodId".to_string()].into_iter().collect(), + ..Default::default() + })), + ..Default::default() + }; + let public_key_schema = schemars::schema::SchemaObject { instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Object))), object: Some(Box::new(schemars::schema::ObjectValidation { @@ -377,6 +393,7 @@ impl JsonSchema for TypedValue { Schema::Object(SchemaObject { subschemas: Some(Box::new(schemars::schema::SubschemaValidation { any_of: Some(vec![ + Schema::Object(pod_id_schema), Schema::Object(int_schema), Schema::Object(raw_schema), Schema::Object(public_key_schema),