-
Notifications
You must be signed in to change notification settings - Fork 1
Continued the static analysis for pbessymmetry #48
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR continues static analysis work for the pbessymmetry tool by implementing cycle notation parsing for permutations and adding validation logic. The main accomplishment is the completion of parsing permutations in cycle notation (one of the two tasks in the PR description).
- Added cycle notation parsing for permutations (e.g., "(0 2 1)(3 4)")
- Introduced permutation validation to ensure control flow parameters are correctly mapped
- Fixed a critical bug in C++ FFI code where
mcrl2_srf_summand_conditionwas incorrectly returning the summand variable instead of the condition
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
tools/mcrl2/pbes/src/symmetry.rs |
Added documentation comments to struct fields, improved logging output format, and introduced is_valid_permutation method to validate permutation constraints |
tools/mcrl2/pbes/src/permutation.rs |
Renamed from_input to from_mapping_notation, added from_cycle_notation parser, added domain method, and included test for cycle notation parsing |
tools/mcrl2/pbes/src/main.rs |
Updated CLI arguments, added automatic detection of permutation format (mapping vs cycle notation), and integrated permutation validation |
tools/mcrl2/crates/mcrl2/src/pbes.rs |
Added Display trait for PbesExpression and updated Debug formatting for SrfSummand to use Display instead of Debug |
tools/mcrl2/crates/mcrl2-sys/src/pbes.rs |
Changed FFI signature from &aterm to &_aterm for consistency with C++ implementation |
tools/mcrl2/crates/mcrl2-sys/cpp/pbes.h |
Fixed critical bug where mcrl2_srf_summand_condition returned summand.variable() instead of summand.condition(), and updated mcrl2_pbes_expression_to_string to properly handle _aterm references |
.gitmodules |
Updated boost-include-only submodule URL to point to MERCorg fork |
f45a124 to
2f6d669
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.
2f6d669 to
07c585a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.
| pub fn is_valid_permutation(&self, pi: &Permutation) -> Result<(), MercError> { | ||
| // Check that all control flow parameters are mapped to control flow parameters. | ||
| for index in pi.domain() { | ||
| let mapped_index = pi.value(index); | ||
| if self.all_control_flow_parameters.contains(&index) != self.all_control_flow_parameters.contains(&mapped_index) { | ||
| return Err(format!( | ||
| "A parameter at index {} is mapped to parameter at index {}, but they are not both control flow parameters.", | ||
| index, mapped_index | ||
| ).into()); | ||
| } | ||
|
|
||
| if index >= self.parameters.len() || mapped_index >= self.parameters.len() { | ||
| return Err(format!( | ||
| "A parameter at index {} is mapped to parameter at index {}, but the PBES only has {} parameters.", | ||
| index, mapped_index, self.parameters.len() | ||
| ).into()); | ||
| } | ||
| } | ||
|
|
||
| Ok(()) | ||
| } |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new is_valid_permutation method lacks test coverage. Consider adding tests to verify the validation logic for both valid and invalid cases, including boundary conditions and control flow parameter constraints.
tools/mcrl2/pbes/src/main.rs
Outdated
| default_value_t = false | ||
| )] | ||
| partition_data_sorts: bool, | ||
| partition_data_sorts: bool, |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing whitespace detected. Remove the trailing space at the end of this line.
| partition_data_sorts: bool, | |
| partition_data_sorts: bool, |
tools/mcrl2/pbes/src/symmetry.rs
Outdated
| let mut result: Vec<Vec<T>> = Vec::new(); | ||
|
|
||
| for element in elements { | ||
|
|
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary blank line. Remove this empty line for consistency with the codebase formatting style.
| format: Option<PbesFormat>, | ||
|
|
||
| /// Pass a single permutation in cycles notation to check for begin a (syntactic) symmetry | ||
| /// Pass a single permutation in cycles notation to check whether it is a symmetry. |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documentation comment is slightly inaccurate. The permutation can be in either mapping notation (e.g., [0->2, 1->0]) or cycle notation (e.g., (0 2 1)), not just cycle notation. Consider updating to: "Pass a single permutation in mapping notation [0->2, 1->0] or cycle notation (0 2 1) to check whether it is a symmetry."
| /// Pass a single permutation in cycles notation to check whether it is a symmetry. | |
| /// Pass a single permutation in mapping notation [0->2, 1->0] or cycle notation (0 2 1) to check whether it is a symmetry. |
| pub fn from_cycle_notation(cycle_notation: &str) -> Result<Self, MercError> { | ||
| let mut mapping: Vec<(usize, usize)> = Vec::new(); | ||
|
|
||
| // Split the input into cycles by finding all '(...)' groups | ||
| for cycle_str in cycle_notation.split('(').skip(1) { | ||
| // Find the closing parenthesis | ||
| let cycle_content = cycle_str | ||
| .split(')') | ||
| .next() | ||
| .ok_or_else(|| MercError::from("Invalid cycle notation: missing closing ')'"))?; | ||
|
|
||
| // Skip empty cycles | ||
| if cycle_content.trim().is_empty() { | ||
| continue; | ||
| } | ||
|
|
||
| // Parse all numbers in this cycle | ||
| let cycle_elements: Result<Vec<usize>, MercError> = cycle_content | ||
| .split_whitespace() | ||
| .map(|num_str| { | ||
| num_str | ||
| .parse::<usize>() | ||
| .map_err(|_| MercError::from(format!("Invalid number in cycle notation: {}", num_str))) | ||
| }) | ||
| .collect(); | ||
|
|
||
| let cycle_elements = cycle_elements?; | ||
|
|
||
| // Create mappings for the current cycle (each element maps to the next) | ||
| let len = cycle_elements.len(); | ||
| for i in 0..len { | ||
| let from = cycle_elements[i]; | ||
| let to = cycle_elements[(i + 1) % len]; | ||
| mapping.push((from, to)); | ||
| } | ||
| } | ||
|
|
||
| Ok(Permutation::from_mapping(mapping)) | ||
| } |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding test coverage for edge cases in from_cycle_notation, such as empty input, single-element cycles, invalid formatting (missing parentheses, invalid numbers), and cycles with duplicate elements.
…pdate expressions.
This reverts commit b5598b7.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 27 out of 29 changed files in this pull request and generated 10 comments.
| pub fn value(&self) -> u64 { | ||
| // The Rust::Str should ensure that this is a valid string. | ||
| 0 | ||
| } |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The value() method always returns 0 instead of the actual integer value stored in the ATerm. This is a placeholder implementation that needs to be completed. The method should extract the actual value from the underlying C++ aterm_int. Additionally, the comment mentions 'Rust::Str' which is incorrect for an integer value method.
| use crate::Todo; | ||
| use crate::is_aterm_int; | ||
|
|
||
| /// Represents an atermpp::aterm_string from the mCRL2 toolset. |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation states this represents an 'aterm_string', but the struct is ATermInt which represents an integer term. The comment should be corrected to 'Represents an atermpp::aterm_int from the mCRL2 toolset.'
| } | ||
|
|
||
| impl ATermInt { | ||
| /// Creates a new ATermInt from the given string value. |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation incorrectly states 'from the given string value' when it should be 'from the given integer value' since the parameter is value: u64.
| } | ||
| } | ||
|
|
||
| /// Returns the string value. |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation incorrectly states 'Returns the string value' when it should be 'Returns the integer value' since the method returns u64.
| /// | ||
| /// TODO: This is not yet functional, the replacements actually do not work. |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function data_expression_replace_variables has a TODO indicating it is not functional, but it's being exported and potentially used. If this is truly non-functional, consider marking it as #[doc(hidden)] or with a #[deprecated] attribute to prevent its use, or remove it until it's implemented correctly.
| pub fn data_expression_variables(expr: &DataExpressionRef<'_>) -> Vec<DataVariable> { | ||
| let mut result = Vec::new(); | ||
|
|
||
| /// Local struct that is used to collect PVI occurrences. |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says 'PVI occurrences' but should be 'variable occurrences' since this is for the VariableOccurrences struct in the data_expression_variables function.
|
|
||
| impl DataExpressionVisitor for VariableOccurrences<'_> { | ||
| fn visit_variable(&mut self, var: &DataVariableRef<'_>) -> Option<DataExpression> { | ||
| // Found a propositional variable instantiation, return true. |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says 'Found a propositional variable instantiation' but should be 'Found a data variable' since this is in the visit_variable method of VariableOccurrences.
| let all_data_groups = | ||
| Box::new(permutation_group(parameter_indices.clone())) as Box<dyn CloneIterator<Item = Permutation>>; | ||
| // Compute the product of the current data group with the already concatenated ones. | ||
| let number_of_parametes = parameter_indices.len(); |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected spelling of 'parametes' to 'parameters'.
| } | ||
|
|
||
| /// Checks whether the mapping represents a valid permutation | ||
| pub fn is_valid_permutation(mapping: &Vec<(usize, usize)>) -> bool { |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter type &Vec<T> should be &[T] to accept any slice type. Change &Vec<(usize, usize)> to &[(usize, usize)] for more idiomatic Rust.
| /// Obtain the underlying value of a machine number. | ||
| pub fn value(&self) -> u64 { | ||
| 0 | ||
| ATermIntRef::from(self.term.copy()).value() |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This calls ATermIntRef::value() which is inherited from ATermInt::value() that always returns 0. This will return incorrect values until the value() method in aterm_int.rs is properly implemented.
Reopened the pull request to run tests, now as part of a fork since the main repository has been moved.
Tasks: