diff --git a/src/translate/verify_properties.rs b/src/translate/verify_properties.rs index a072ef8..3be97ef 100644 --- a/src/translate/verify_properties.rs +++ b/src/translate/verify_properties.rs @@ -18,6 +18,9 @@ struct Definitions struct Context { + pub definitions: std::collections::BTreeMap::, Definitions>, + pub integrity_constraints: foliage::Formulas, + pub function_declarations: foliage::FunctionDeclarations, pub predicate_declarations: foliage::PredicateDeclarations, pub variable_declaration_stack: foliage::VariableDeclarationStack, @@ -29,6 +32,8 @@ impl Context { Self { + definitions: std::collections::BTreeMap::<_, _>::new(), + integrity_constraints: vec![], function_declarations: foliage::FunctionDeclarations::new(), predicate_declarations: foliage::PredicateDeclarations::new(), variable_declaration_stack: foliage::VariableDeclarationStack::new(), @@ -98,6 +103,16 @@ pub fn translate(program: &str) -> i32 } } +fn universal_closure(scoped_formula: ScopedFormula) -> foliage::Formula +{ + match scoped_formula.free_variable_declarations.is_empty() + { + true => scoped_formula.formula, + false => foliage::Formula::for_all(scoped_formula.free_variable_declarations, + Box::new(scoped_formula.formula)), + } +} + fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crate::Error> { use super::common::FindOrCreatePredicateDeclaration; @@ -105,9 +120,6 @@ fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crat let head_type = determine_head_type(rule.head(), |name, arity| context.predicate_declarations.find_or_create(name, arity))?; - let mut definitions - = std::collections::BTreeMap::, Definitions>::new(); - let declare_predicate_parameters = |predicate_declaration: &foliage::PredicateDeclaration| { std::rc::Rc::new((0..predicate_declaration.arity) @@ -115,13 +127,14 @@ fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crat .collect()) }; - match head_type + match &head_type { - HeadType::SingleAtom(head_atom) => + HeadType::SingleAtom(head_atom) + | HeadType::ChoiceWithSingleAtom(head_atom) => { - if !definitions.contains_key(&head_atom.predicate_declaration) + if !context.definitions.contains_key(&head_atom.predicate_declaration) { - definitions.insert(std::rc::Rc::clone(&head_atom.predicate_declaration), + context.definitions.insert(std::rc::Rc::clone(&head_atom.predicate_declaration), Definitions { head_atom_parameters: declare_predicate_parameters(&head_atom.predicate_declaration), @@ -129,7 +142,7 @@ fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crat }); } - let definitions = definitions.get_mut(&head_atom.predicate_declaration).unwrap(); + let definitions = context.definitions.get_mut(&head_atom.predicate_declaration).unwrap(); context.variable_declaration_stack.push(std::rc::Rc::clone( &definitions.head_atom_parameters)); @@ -140,6 +153,18 @@ fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crat assert_eq!(definitions.head_atom_parameters.len(), head_atom.arguments.len()); + if let HeadType::ChoiceWithSingleAtom(_) = head_type + { + let head_arguments = definitions.head_atom_parameters.iter() + .map(|x| Box::new(foliage::Term::variable(x))) + .collect::>(); + + let head_predicate = foliage::Formula::predicate(&head_atom.predicate_declaration, + head_arguments); + + definition_arguments.push(Box::new(head_predicate)); + } + let mut head_atom_arguments_iterator = head_atom.arguments.iter(); for head_atom_parameter in definitions.head_atom_parameters.iter() @@ -168,15 +193,36 @@ fn read_rule(rule: &clingo::ast::Rule, context: &mut Context) -> Result<(), crat formula: definition, }; - log::trace!("translated rule with single atom in head: {:?}", definition.formula); + log::debug!("translated rule with single atom in head: {:?}", definition.formula); definitions.definitions.push(definition); }, - HeadType::ChoiceWithSingleAtom(_) => - log::debug!("translating choice rule with single atom"), HeadType::IntegrityConstraint => - log::debug!("translated integrity constraint"), - HeadType::Trivial => log::debug!("skipping trivial rule"), + { + let arguments = translate_body(rule.body(), + &mut context.function_declarations, &mut context.predicate_declarations, + &mut context.variable_declaration_stack)?; + + let mut free_variable_declarations = vec![]; + + std::mem::swap(&mut context.variable_declaration_stack.free_variable_declarations, + &mut free_variable_declarations); + + let and = foliage::Formula::and(arguments); + let not = foliage::Formula::not(Box::new(and)); + let scoped_formula = ScopedFormula + { + free_variable_declarations, + formula: not, + }; + + let integrity_constraint = universal_closure(scoped_formula); + + log::debug!("translated integrity constraint: {:?}", integrity_constraint); + + context.integrity_constraints.push(Box::new(integrity_constraint)); + }, + HeadType::Trivial => log::info!("skipping trivial rule"), } Ok(())