Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to use optional operator ? in binding rule queries #1222

Open
ggiraldez opened this issue Jan 20, 2025 · 1 comment
Open

Unable to use optional operator ? in binding rule queries #1222

ggiraldez opened this issue Jan 20, 2025 · 1 comment
Labels
bug Something isn't working

Comments

@ggiraldez
Copy link
Contributor

ggiraldez commented Jan 20, 2025

It's not possible to use the ? operator in binding rule queries. The reason is the query engine will not create a capture key when the node is absent and this causes a panic when the graph builder attempts to evaluate the capture value.

Eg. the rule for Solidity:

@mapping [MappingType
    @key [MappingKey [MappingKeyType] @key_name [Identifier]?]
] {
  node @mapping.defs

  if some @key_name {
    node @key.def
    attr (@key.def) node_definition = @key_name
    attr (@key.def) definiens_node = @key
    edge @key.def -> @mapping.defs
  }
}

Will panic here with:

thread 'bindings_output::generated::mappings::named_parameters' panicked at /home/ggiraldez/Projects/slang/crates/metaslang/graph_builder/src/execution/lazy.rs:691:41:
no entry found for key

CAVEAT: Whether we want to fix this or not is up for debate. Because our query engine works more like unification than pattern matching, the above rule would be problematic as it will match twice if the Identifier is present: one time capturing it, and a second time without capturing it. This problem gets worse if the query contains multiple optional captures, as the engine will return matches for all possible combinations.

@ggiraldez
Copy link
Contributor Author

This patch would fix the issue, but as stated in the caveat above, this could potentially result in a more confusing behaviour. It's also unclear to me that the resulting behaviour is useful for implementing the binding rules.

diff --git a/crates/metaslang/graph_builder/src/execution/lazy.rs b/crates/metaslang/graph_builder/src/execution/lazy.rs
index 9b589607b..8a74631ac 100644
--- a/crates/metaslang/graph_builder/src/execution/lazy.rs
+++ b/crates/metaslang/graph_builder/src/execution/lazy.rs
@@ -688,8 +688,12 @@ impl ast::Capture {
         &self,
         exec: &mut ExecutionContext<'_, '_, '_, KT>,
     ) -> Result<LazyValue, ExecutionError> {
-        let capture = &exec.mat.captures[&*self.name.0];
-        Ok(Value::from_nodes(exec.graph, capture.iter().cloned(), self.quantifier).into())
+        let value = if let Some(capture) = &exec.mat.captures.get(&*self.name.0) {
+            Value::from_nodes(exec.graph, capture.iter().cloned(), self.quantifier)
+        } else {
+            Value::from_nodes(exec.graph, std::iter::empty().into_iter(), self.quantifier)
+        };
+        Ok(value.into())
     }
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Status: Todo
Development

No branches or pull requests

1 participant