veripb 3.0.2

VeriPB is a proof checker for verifying pseudo-Boolean certificates of satisfiability, unsatisfiability, and optimality bounds.
Documentation
use std::rc::Rc;

use logos::Lexer;
use veripb_formula::prelude::*;
use veripb_parser::{error::ParserError, opb_parser::parse_single_constraint};

use crate::prelude::*;

#[derive(Debug)]
pub struct ImpliesRule {
    constraint: Rc<DBConstraint>,
    hint: Option<isize>,
    add_result: bool,
}

impl ImpliesRule {
    pub fn new(constraint: PBConstraintEnum, hint: Option<isize>, add_result: bool) -> Self {
        Self {
            constraint: Rc::new(DBConstraint::from(constraint)),
            hint,
            add_result,
        }
    }

    #[inline]
    pub fn parse(
        lex: Lexer<super::RuleToken>,
        context: &mut Context,
        add_result: bool,
    ) -> Result<Self, ParserError> {
        let mut lex = lex.morph();
        let (geq_constraint, leq_constraint) =
            parse_single_constraint(&mut lex, &mut context.var_names)?;
        if leq_constraint.is_some() {
            return Err(ParserError::token_error(
                0..lex.span().end,
                "inequality constraint",
            ));
        }
        let hint = IntegerToken::parse_optional(&mut lex.morph())?;
        Ok(ImpliesRule {
            constraint: Rc::new(DBConstraint::from(geq_constraint)),
            hint,
            add_result,
        })
    }
}

impl Rule for ImpliesRule {
    #[inline]
    fn compute(
        &mut self,
        context: &mut Context,
        database: &mut Database,
    ) -> Result<Vec<Rc<DBConstraint>>, CheckingError> {
        self.hint = Some(check_implication(
            context,
            database,
            &self.constraint,
            self.hint,
        )?);

        if self.add_result {
            Ok(vec![self.constraint.clone()])
        } else {
            Ok(vec![])
        }
    }

    #[inline]
    fn get_returned_id(&self) -> Option<isize> {
        if self.add_result {
            None
        } else {
            self.hint
        }
    }

    #[inline]
    fn elaborate(
        &self,
        context: &mut Context,
        database: &Database,
    ) -> Result<(), ElaborationError> {
        let elaborator = context.elaborator.as_mut().unwrap();
        if self.add_result {
            elaborator.write("ia ");
            elaborator.write(&self.constraint.to_pretty_string(&context.var_names));
            elaborator.write(" : ");
            let premise = database
                .get_entry_usize(self.hint.unwrap() as usize)
                .expect("constraint accessed before");
            elaborator.write(
                &premise
                    .get_out_id(premise.get_some_id())
                    .unwrap()
                    .to_string(),
            );
            elaborator.writeln(";");
        }
        Ok(())
    }

    #[inline]
    fn is_subproof_friendly(&self) -> bool {
        true
    }
}