예제 #1
0
/**Function********************************************************************

  Synopsis    [Pure virtual function, tries to solve formulas from
  the groups belonging to the solver except the groups in the list.
  the permanent group must not be in the list]

  Description [It is a pure virtual function and SatIncSolver is an abstract
  base class. Every derived class must ovewrwrite this function.]

  SideEffects []

  SeeAlso     [SatIncSolver_add]

******************************************************************************/
SatSolverResult
sat_inc_solver_solve_without_groups (const SatIncSolver_ptr self,
                                     const Olist_ptr groups)
{
  error_unreachable_code(); /* Pure Virtual Member Function */
  return SAT_SOLVER_INTERNAL_ERROR;
}
예제 #2
0
/**Function********************************************************************

  Synopsis    [Finalize method of SatIncSolver class.]

  Description [Pure virtual function. This must be refined by derived classes.]

  SideEffects []

  SeeAlso     []

******************************************************************************/
static void sat_inc_solver_finalize(Object_ptr object, void* dummy)
{
  SatIncSolver_ptr self = SAT_INC_SOLVER(object);

  SAT_INC_SOLVER_CHECK_INSTANCE(self);

  sat_inc_solver_deinit(self);
  error_unreachable_code();
}
예제 #3
0
파일: exprWff.c 프로젝트: hklarner/NuSMV-a
boolean Wff_is_propositional(SymbTable_ptr symb_table,
                             node_ptr wff,
                             node_ptr context,
                             boolean is_next_allowed)
{
  NuSMVEnv_ptr env = NULL;
  MasterLogicRecognizer_ptr master_recogn = NULL;

  TypeChecker_ptr type_checker = NULL;
  SymbType_ptr symb_type = NULL;
  LogicType logic = EXP_NONE;
  boolean retval = true;

  SYMB_TABLE_CHECK_INSTANCE(symb_table);
  nusmv_assert(retval);

  env = EnvObject_get_environment(ENV_OBJECT(symb_table));
  master_recogn = MASTER_LOGIC_RECOGNIZER(NuSMVEnv_get_value(env, ENV_MASTER_LOGIC_RECOGNIZER));

  type_checker = SymbTable_get_type_checker(symb_table);

  if (TypeChecker_is_expression_type_checked(type_checker, wff, context)) {
    symb_type = TypeChecker_get_expression_type(type_checker, wff, context);
    if (! SymbType_is_boolean(symb_type)) retval = false;
  }

  if (retval) {
    logic = MasterLogicRecognizer_recognize(master_recogn, wff, context);
    switch(logic) {
    case EXP_CTL:
    case EXP_LTL:
      retval = false; break;

    case EXP_NEXT:
      if (! is_next_allowed) retval = false;
      break;

    case EXP_SIMPLE:
      break;

    default:
      error_unreachable_code();
    }
  }

  if (retval) {
    if (! TypeChecker_is_expression_type_checked(type_checker, wff, context)) {
      symb_type = TypeChecker_get_expression_type(type_checker, wff, context);
      if (! SymbType_is_boolean(symb_type)) retval = false;
    }
  }

  return retval;
}
예제 #4
0
/**Function********************************************************************

   Synopsis           [Aux fun of w2w_wff_expand_case]

   Description        [Aux fun of w2w_wff_expand_case]

   SideEffects        []

   SeeAlso            []

******************************************************************************/
static node_ptr w2w_wff_expand_case_aux(node_ptr wff)
{
  if (CASE == node_get_type(wff) || IFTHENELSE == node_get_type(wff)) {
    node_ptr cur_cond  = car(car(wff));
    node_ptr cur_rslt  = cdr(car(wff));
    node_ptr case_rest = cdr(wff);
    node_ptr res;

    nusmv_assert(node_get_type(car(wff)) == COLON);

    /* here lazy evaluation is required to get rid of FAILURE node
       in case-expressions (see this function below)
    */
    if (cur_cond == Wff_make_truth()) return cur_rslt;
    if (cur_cond == Wff_make_falsity()) return case_rest;

    res = Wff_make_or( Wff_make_and(cur_cond, cur_rslt),
                       Wff_make_and(Wff_make_not(cur_cond),
                                    w2w_wff_expand_case_aux(case_rest))
                       );
    return res;

  }
  else {
    if (FAILURE == node_get_type(wff)) {
      if (failure_get_kind(wff) == FAILURE_CASE_NOT_EXHAUSTIVE) {
        warning_case_not_exhaustive(wff);
        /* forces a default */
        return Wff_make_truth();
      }
      else if (failure_get_kind(wff) == FAILURE_DIV_BY_ZERO) {
        warning_possible_div_by_zero(wff);
        /* forces a default */
        return Wff_make_truth();
      }
      else if (failure_get_kind(wff) == FAILURE_ARRAY_OUT_OF_BOUNDS) {
        warning_possible_array_out_of_bounds(wff);
        /* forces a default */
        return Wff_make_truth();
      }
      else {
        report_failure_node(wff); /* some error in the input expr */
        error_unreachable_code();
      }
    }

    return wff;
  }
}
예제 #5
0
hash_ptr Bmc_Tableau_get_handled_hash(SymbTable_ptr symb_table,
                                      char* hash_str)
{
  if (! strcmp(ST_BMC_TABLEAU_LTL_HASH, hash_str)) {
    return
      SymbTable_get_handled_hash_ptr(
                      symb_table,
                      ST_BMC_TABLEAU_LTL_HASH,
                      (ST_PFICPCP)NULL,
                      (ST_PFICPI)NULL,
                      (ST_PFSR)NULL,
                      (SymbTableTriggerFun)NULL,
                      SymbTable_clear_handled_remove_action_hash,
                      (SymbTableTriggerFun)NULL);
  }
  else error_unreachable_code();
}
예제 #6
0
void SymbLayer_remove_var(SymbLayer_ptr self, node_ptr name)
{
  SymbType_ptr type;

  /* IMPORTANT: do not remove this assertion! (read comment) */
  nusmv_assert(self->committed_to_encs == 0); /* not in use */

  nusmv_assert(SymbCache_is_symbol_var(self->cache, name));

  type = SymbCache_get_var_type(self->cache, name);


  if (SymbCache_is_symbol_state_var(self->cache, name)) {
    --self->state_vars_num;
    if (SymbType_is_boolean(type)) {
      --self->bool_state_vars_num;
    }
  }
  else if (SymbCache_is_symbol_frozen_var(self->cache, name)) {
    --self->frozen_vars_num;
    if (SymbType_is_boolean(type)) {
      --self->bool_frozen_vars_num;
    }
  }
  else if (SymbCache_is_symbol_input_var(self->cache, name)) {
    --self->input_vars_num;
    if (SymbType_is_boolean(type)) {
      --self->bool_input_vars_num;
    }
  }
  else {
    error_unreachable_code();
  }

  /* removes the variable  */
  SymbCache_remove_var(self->cache, name);

  symb_layer_remove_symbol(self, name);

  if (opt_verbose_level_gt(self->options, 3)) {
    Logger_nlog(self->logger, self->printer,
                "SymbLayer '%s': removed variable '%N'\n",
                self->name, name);
  }
}
예제 #7
0
/**Function********************************************************************

  Synopsis    [Pure virtual function, moves all formulas from
  a given group into the permanent one, and then destroys the given group]

  Description [It is a pure virtual function and SatIncSolver is an abstract
  base class. Every derived class must ovewrwrite this function.]

  SideEffects []

  SeeAlso     [SatIncSolver_add]

******************************************************************************/
void
sat_inc_solver_move_to_permanent_and_destroy_group (const SatIncSolver_ptr self,
                                                    SatSolverGroup group)
{
  error_unreachable_code(); /* Pure Virtual Member Function */
}
예제 #8
0
/**Function********************************************************************

  Synopsis    [Pure virtual function, create a new group]

  Description [It is a pure virtual function and SatIncSolver is an abstract
  base class. Every derived class must ovewrwrite this function.]

  SideEffects []

  SeeAlso     [SatIncSolver_add]

******************************************************************************/
SatSolverGroup
sat_inc_solver_create_group (const SatIncSolver_ptr self)
{
  error_unreachable_code(); /* Pure Virtual Member Function */
  return -1;
}
예제 #9
0
be_ptr
BmcInt_Tableau_GetAtTime(const BeEnc_ptr be_enc, const node_ptr ltl_wff,
                         const int time, const int k, const int l)
{
  const NuSMVEnv_ptr env = EnvObject_get_environment(ENV_OBJECT(be_enc));
  const StreamMgr_ptr streams =
    STREAM_MGR(NuSMVEnv_get_value(env, ENV_STREAM_MANAGER));
  const ErrorMgr_ptr errmgr =
    ERROR_MGR(NuSMVEnv_get_value(env, ENV_ERROR_MANAGER));
  const MasterPrinter_ptr wffprint =
    MASTER_PRINTER(NuSMVEnv_get_value(env, ENV_WFF_PRINTER));
  const NodeMgr_ptr nodemgr =
    NODE_MGR(NuSMVEnv_get_value(env, ENV_NODE_MGR));

  be_ptr result = (be_ptr)NULL;
  SymbTable_ptr st;
  Be_Manager_ptr be_mgr;
  node_ptr key;
  hash_ptr tableau_ltl_hash;

  /* checks out the validity of [l, k] only if a loop exists: */
  nusmv_assert(Bmc_Utils_IsNoLoopback(l) || (k > l));
  nusmv_assert((time < k) || (time==k && Bmc_Utils_IsNoLoopback(l)) );

  st = BaseEnc_get_symb_table(BASE_ENC(be_enc));
  be_mgr = BeEnc_get_be_manager(be_enc);

  tableau_ltl_hash = Bmc_Tableau_get_handled_hash(st, ST_BMC_TABLEAU_LTL_HASH);

  key = bmc_tableau_memoization_get_key(nodemgr, ltl_wff, time, k, l);
  result = bmc_tableau_memoization_lookup(tableau_ltl_hash, key);
  if (result != (be_ptr) NULL) return result;

  switch (node_get_type(ltl_wff)) {
  case TRUEEXP:
    return Be_Truth(be_mgr); /* not memoized */

  case FALSEEXP:
    return Be_Falsity(be_mgr); /* not memoized */

  case BIT:
  case DOT:
    if ((time == k) &&
        BeEnc_is_index_input_var(be_enc,
                                 BeEnc_name_to_index(be_enc, ltl_wff))) {
      /* input vars when time == max_time evaluate to false: */
      return Be_Falsity(be_mgr); /* not memoized */
    }

    return BeEnc_name_to_timed(be_enc, ltl_wff, time); /* not memoized */

  case ARRAY:
    if (!SymbTable_is_symbol_declared(st, ltl_wff)) {
      ErrorMgr_internal_error(errmgr, "Unexpected array node\n");
    }

    if (!SymbTable_is_symbol_bool_var(st, ltl_wff)) {
      StreamMgr_print_error(streams,  "Detected scalar array variable '");
      StreamMgr_nprint_error(streams, wffprint, "%N", ltl_wff);
      StreamMgr_print_error(streams,  "'");
      ErrorMgr_internal_error(errmgr, "Scalar array variable has been found where a boolean "
                     "variable had to be used instead.\n"
                     "This might be due to a bug on your model.");
    }

    if ((time == k) &&
        BeEnc_is_index_input_var(be_enc,
                                 BeEnc_name_to_index(be_enc, ltl_wff))) {
      /* input vars when time == max_time evaluate to false: */
      return Be_Falsity(be_mgr); /* not memoized */
    }

    return BeEnc_name_to_timed(be_enc, ltl_wff, time); /* not memoized */

  case NOT:
    /* checks out that argument of NOT operator is actually a variable: */
    nusmv_assert( node_get_type(car(ltl_wff)) == DOT ||
                  node_get_type(car(ltl_wff)) == BIT ||
                  node_get_type(car(ltl_wff)) == ARRAY);

    if (!SymbTable_is_symbol_declared(st, car(ltl_wff))) {
      ErrorMgr_internal_error(errmgr, "Unexpected scalar or undefined node\n");
    }

    if ((node_get_type(car(ltl_wff)) == ARRAY) &&
        ! SymbTable_is_symbol_bool_var(st, car(ltl_wff))) {
      StreamMgr_print_error(streams,  "Detected scalar array variable '");
      StreamMgr_nprint_error(streams, wffprint, "%N", car(ltl_wff));
      StreamMgr_print_error(streams,  "'");
      ErrorMgr_internal_error(errmgr, "Scalar array variable has been found where a boolean "
                     "variable had to be used instead.\n"
                     "This might be due to a bug on your model.");
    }

    if ((time == k) &&
        BeEnc_is_index_input_var(be_enc,
                                 BeEnc_name_to_index(be_enc, car(ltl_wff)))) {
      /* input vars when time == max_time evaluate to false: */
      result = Be_Falsity(be_mgr);
      break;
    }

    result = Be_Not(be_mgr, BeEnc_name_to_timed(be_enc, car(ltl_wff), time));
    break;

  case AND:
    result = Be_And(be_mgr,
                    BmcInt_Tableau_GetAtTime(be_enc,car(ltl_wff), time, k, l),
                    BmcInt_Tableau_GetAtTime(be_enc,cdr(ltl_wff), time, k, l));
    break;

  case OR:
    result = Be_Or(be_mgr,
                   BmcInt_Tableau_GetAtTime(be_enc,car(ltl_wff), time, k, l),
                   BmcInt_Tableau_GetAtTime(be_enc,cdr(ltl_wff), time, k, l));
    break;

  case IFF:
    result = Be_Iff(be_mgr,
                    BmcInt_Tableau_GetAtTime(be_enc,car(ltl_wff),time,k,l),
                    BmcInt_Tableau_GetAtTime(be_enc,cdr(ltl_wff),time,k,l));
    break;

  case OP_NEXT:
    result = bmc_tableauGetNextAtTime(be_enc, car(ltl_wff), time, k, l);
    break;

  case OP_GLOBAL:
    result = bmc_tableauGetGloballyAtTime(be_enc, car(ltl_wff), time, k, l);
    break;

  case OP_FUTURE: /* EVENTUALLY */
    result = bmc_tableauGetEventuallyAtTime(be_enc, car(ltl_wff), time, k, l);

    break;

  case UNTIL:
    result = bmc_tableauGetUntilAtTime(be_enc, car(ltl_wff), cdr(ltl_wff),
                                       time, k, l);
    break;

  case RELEASES:
    result = bmc_tableauGetReleasesAtTime(be_enc, car(ltl_wff), cdr(ltl_wff),
                                          time, k, l );
    break;

  case IMPLIES:
    ErrorMgr_internal_error(errmgr, "'Implies' should had been nnf-ed away!\n");

  case ATOM:
  case EX:
  case AX:
  case EF:
  case AF:
  case EG:
  case AG:
  case EBF:
  case EBG:
  case ABF:
  case ABG:
    ErrorMgr_internal_error(errmgr,  "Unexpected CTL operator, node type %d\n",
                    node_get_type(ltl_wff) );

  default:
    /* no other type are available here: */
    error_unreachable_code();
  }

  nusmv_assert(result != NULL); /*it must be assigned! */
  bmc_tableau_memoization_insert(tableau_ltl_hash, key, result);
  return result;
}
예제 #10
0
/**Function********************************************************************

  Synopsis           [The type core violation handler.]

  Description        [The violation handler is implemented as
  a virtual method, which is invoked by the checker when an expression
  being checked violates the type system.
  See the violation handler TypeCheckingViolationHandler_ptr
  for more explanations.

  The below function is the default violation handler, and a
  user can potentially define its own violation handler, by deriving
  a new class from this class and by overriding this virtual method.

  This violation handler outputs an error and warning message to
  nusmv_stderr. A warning is output if the detected violation is
  TC_VIOLATION_TYPE_BACK_COMP and the system variable
  "type_checking_backward_compatibility" is true. Also the
  TC_VIOLATION_TYPE_WARNING violation outputs a warning. Only in this
  case the false value is returned, indicating that this is NOT an
  error. Otherwise the true value is returned, indicating that this is
  an error.

  Also, if the system variable "type_check_warning_on" is false,
  warning messages are not output.

  NB: if the expression is checked in some context (context is not null) then
  before providing the expression to this function the expression should be
  wrapped into context, i.e. with find_node(CONEXT, context, expr)]

  SideEffects       []

  SeeAlso           [TypeSystemViolation]

******************************************************************************/
static boolean
checker_psl_viol_handler(CheckerBase_ptr self,
                         TypeSystemViolation violation, node_ptr expression)
{
  /* In the output message, the information about the expression
     location are output. So, make sure that the input file name and
     line number are correctly set!
  */

  boolean isError = true; /* is this error or warning */

  /* get rid of the context the expression may be wrapped in */
  PslNode_ptr context = PSL_NULL;
  PslNode_ptr expr = PslNode_convert_from_node_ptr(expression);

  if (node_get_type(expression) == CONTEXT) {
    context = PslNode_convert_from_node_ptr(car(expression));
    expr = PslNode_convert_from_node_ptr(cdr(expression));
  }

  /* checks the given violation */
  nusmv_assert(TypeSystemViolation_is_valid(violation));

  /* only violation TC_VIOLATION_TYPE_BACK_COMP and the variable
     type_checking_backward_compatibility being true, may make a
     warning from an error.
     TC_VIOLATION_TYPE_WARNING always forces a warning
  */
  if (  TC_VIOLATION_TYPE_WARNING == violation
     || ( TC_VIOLATION_TYPE_BACK_COMP == violation
         && opt_backward_comp(OptsHandler_get_instance()))) {
    isError = false;
  }

  if (!isError && !opt_type_checking_warning_on(OptsHandler_get_instance())) {
    /* this is a warning and warning messages are not allowed.
     So, do nothing, just return false (this is not an error)
    */
    return false;
  }

  _PRINT_ERROR_MSG(expr, isError);

  switch (violation) {
  case TC_VIOLATION_AMBIGUOUS_IDENTIFIER:
    fprintf(nusmv_stderr,  "identifier '");
    print_node(nusmv_stderr, PslNode_convert_to_node_ptr(expr));
    fprintf(nusmv_stderr, "' is ambiguous\n");
    break;

  case TC_VIOLATION_UNCONSTANT_EXPRESSION:
    fprintf(nusmv_stderr, "Expected constant expression in '");
    print_node(nusmv_stderr, PslNode_convert_to_node_ptr(expr));
    fprintf(nusmv_stderr, "'\n");
    break;

  case TC_VIOLATION_TYPE_MANDATORY:
  case TC_VIOLATION_TYPE_BACK_COMP:
  case TC_VIOLATION_TYPE_WARNING:
    if (isError) fprintf(nusmv_stderr, "illegal ");
    else         fprintf(nusmv_stderr, "potentially incorrect ");

    switch (psl_node_get_op(expr)) {

    case PSL_SERE:
    case PSL_SERECOMPOUND:
      fprintf(nusmv_stderr, "sere type of {");
      print_node(stderr, PslNode_convert_to_node_ptr(psl_node_get_left(expr)));
      fprintf(nusmv_stderr, "} : ");
      checker_base_print_type(self, nusmv_stderr,
                      PslNode_convert_to_node_ptr(psl_node_get_left(expr)),
                      PslNode_convert_to_node_ptr(context));
      break;

    case PSL_SERECONCAT:
      fprintf(nusmv_stderr, "operand types of sere concatenation: ");
      checker_base_print_type(self, nusmv_stderr,
                      PslNode_convert_to_node_ptr(psl_node_get_left(expr)),
                      PslNode_convert_to_node_ptr(context));
      fprintf(nusmv_stderr, " ");
      print_operator(nusmv_stderr, expr);
      fprintf(nusmv_stderr, " ");
      checker_base_print_type(self, nusmv_stderr,
                      PslNode_convert_to_node_ptr(psl_node_get_right(expr)),
                      PslNode_convert_to_node_ptr(context));
      break;

    case PSL_SEREFUSION:
      fprintf(nusmv_stderr, "operand types of sere fusion: ");
      checker_base_print_type(self, nusmv_stderr,
                      PslNode_convert_to_node_ptr(psl_node_get_left(expr)),
                      PslNode_convert_to_node_ptr(context));
      fprintf(nusmv_stderr, " ");
      print_operator(nusmv_stderr, expr);
      fprintf(nusmv_stderr, " ");
      checker_base_print_type(self, nusmv_stderr,
                      PslNode_convert_to_node_ptr(psl_node_get_right(expr)),
                      PslNode_convert_to_node_ptr(context));
      break;


    case PSL_SEREREPEATED:
      {
        PslNode_ptr sere = psl_node_sere_repeated_get_expr(expr);
        PslNode_ptr count = psl_node_sere_repeated_get_count(expr);

        fprintf(nusmv_stderr, "operand types of sere repeated: ");
        if (sere != PSL_NULL) {
          checker_base_print_type(self, nusmv_stderr,
                                  PslNode_convert_to_node_ptr(sere),
                                  PslNode_convert_to_node_ptr(context));
        }
        print_operator(nusmv_stderr, psl_node_get_left(expr));
        fprintf(nusmv_stderr, " ");

        if (count != PSL_NULL) {
          checker_base_print_type(self, nusmv_stderr,
                                  PslNode_convert_to_node_ptr(count),
                                  PslNode_convert_to_node_ptr(context));
        }
        fprintf(nusmv_stderr, " ]");
        break;
      }

    case PSL_REPLPROP:
      {
        PslNode_ptr prop = psl_node_repl_prop_get_property(expr);

        fprintf(nusmv_stderr, "operand type of ");
        print_operator(nusmv_stderr, expr);
        fprintf(nusmv_stderr, " property: ");
        checker_base_print_type(self, nusmv_stderr,
                                PslNode_convert_to_node_ptr(prop),
                                PslNode_convert_to_node_ptr(context));
        break;
      }

      /* suffix implication */
    case PSL_PIPEMINUSGT:
    case PSL_PIPEEQGT:
      {
        PslNode_ptr pre = psl_node_suffix_implication_get_premise(expr);
        PslNode_ptr con = psl_node_suffix_implication_get_consequence(expr);

        fprintf(nusmv_stderr, "operand types of suffix implication: ");
        checker_base_print_type(self, nusmv_stderr,
                                PslNode_convert_to_node_ptr(pre),
                                PslNode_convert_to_node_ptr(context));

        fprintf(nusmv_stderr, " ");
        print_operator(nusmv_stderr, expr);
        fprintf(nusmv_stderr, " ");

        checker_base_print_type(self, nusmv_stderr,
                                PslNode_convert_to_node_ptr(con),
                                PslNode_convert_to_node_ptr(context));
        break;
      }

      /* unary operators: */
    case PSL_ALWAYS:
    case PSL_NEVER:
    case PSL_EVENTUALLYBANG:
        fprintf(nusmv_stderr, "operand types of \"");
        print_operator(nusmv_stderr, expr);
        fprintf(nusmv_stderr, "\" : ");
        checker_base_print_type(self, nusmv_stderr,
                                PslNode_convert_to_node_ptr(psl_node_get_left(expr)),
                                PslNode_convert_to_node_ptr(context));
        break;

      /* within operators */
    case PSL_WITHINBANG:
    case PSL_WITHIN:
    case PSL_WITHINBANG_:
    case PSL_WITHIN_:
      {
        PslNode_ptr n1 = psl_node_get_left(psl_node_get_left(expr));
        PslNode_ptr n2 = psl_node_get_right(psl_node_get_left(expr));
        PslNode_ptr n3 = psl_node_get_right(expr);

        fprintf(nusmv_stderr, "operand types of \"");
        print_operator(nusmv_stderr, expr);
        fprintf(nusmv_stderr, "\" : (");
        checker_base_print_type(self, nusmv_stderr,
                                PslNode_convert_to_node_ptr(n1),
                                PslNode_convert_to_node_ptr(context));
        fprintf(nusmv_stderr, ", ");
        checker_base_print_type(self, nusmv_stderr,
                                PslNode_convert_to_node_ptr(n2),
                                PslNode_convert_to_node_ptr(context));
        fprintf(nusmv_stderr, ") ");
        checker_base_print_type(self, nusmv_stderr,
                                PslNode_convert_to_node_ptr(n3),
                                PslNode_convert_to_node_ptr(context));
        break;
      }

      /* next operators */
    case PSL_NEXT_EVENT_ABANG:
    case PSL_NEXT_EVENT_A:
    case PSL_NEXT_EVENT_EBANG:
    case PSL_NEXT_EVENT_E:
    case PSL_NEXT_EVENTBANG:
    case PSL_NEXT_EVENT:
    case PSL_NEXT_ABANG:
    case PSL_NEXT_EBANG:
    case PSL_NEXT_A:
    case PSL_NEXT_E:
    case PSL_NEXTBANG:
    case PSL_NEXT:
    case PSL_X:
    case PSL_XBANG:
      {
        PslNode_ptr n1 = psl_node_extended_next_get_expr(expr);
        PslNode_ptr n2 = psl_node_extended_next_get_when(expr);
        PslNode_ptr n3 = psl_node_extended_next_get_condition(expr);

        fprintf(nusmv_stderr, "operand types of \"");
        print_operator(nusmv_stderr, expr);
        fprintf(nusmv_stderr, "\" : ");

        if (n3 != PSL_NULL) {
          fprintf(nusmv_stderr, " (");
          checker_base_print_type(self, nusmv_stderr,
                                  PslNode_convert_to_node_ptr(n3),
                                  PslNode_convert_to_node_ptr(context));
          fprintf(nusmv_stderr, ")");
        }

        if (n2 != PSL_NULL) {
          fprintf(nusmv_stderr, " [");
          checker_base_print_type(self, nusmv_stderr,
                                  PslNode_convert_to_node_ptr(n2),
                                  PslNode_convert_to_node_ptr(context));
          fprintf(nusmv_stderr, "]");
        }

        nusmv_assert(n1 != PSL_NULL); /* n1 must occur here */
        fprintf(nusmv_stderr, " (");
        checker_base_print_type(self, nusmv_stderr,
                                PslNode_convert_to_node_ptr(n1),
                                PslNode_convert_to_node_ptr(context));
        fprintf(nusmv_stderr, ")");
        break;
      }

      /* Binary operators */
    case PSL_BEFOREBANG:
    case PSL_BEFORE:
    case PSL_BEFOREBANG_:
    case PSL_BEFORE_:
    case PSL_UNTILBANG:
    case PSL_UNTIL:
    case PSL_UNTILBANG_:
    case PSL_UNTIL_:
    case PSL_ABORT:
    case PSL_W:
    case PSL_OR:
    case PSL_CARET:
    case PSL_TILDE:
    case PSL_EQEQ:
    case PSL_PIPEPIPE:
    case PSL_AMPERSANDAMPERSAND:
    case PSL_WHILENOTBANG:
    case PSL_WHILENOT:
    case PSL_WHILENOTBANG_:
    case PSL_WHILENOT_:
      fprintf(nusmv_stderr, "operand types of \"");
      print_operator(nusmv_stderr, expr);
      fprintf(nusmv_stderr,"\" : ");
      checker_base_print_type(self, nusmv_stderr,
                      PslNode_convert_to_node_ptr(psl_node_get_left(expr)),
                      PslNode_convert_to_node_ptr(context));
      fprintf(nusmv_stderr," and ");
      checker_base_print_type(self, nusmv_stderr,
                      PslNode_convert_to_node_ptr(psl_node_get_right(expr)),
                      PslNode_convert_to_node_ptr(context));
      break;

    case PSL_ITE:
      fprintf(nusmv_stderr, "operand types of \"");
      print_operator(nusmv_stderr, expr);
      fprintf(nusmv_stderr,"\" : ");
      checker_base_print_type(self, nusmv_stderr,
                      PslNode_convert_to_node_ptr(psl_node_get_ite_cond(expr)),
                      PslNode_convert_to_node_ptr(context));
      fprintf(nusmv_stderr," ? ");
      checker_base_print_type(self, nusmv_stderr,
                      PslNode_convert_to_node_ptr(psl_node_get_ite_then(expr)),
                      PslNode_convert_to_node_ptr(context));
      fprintf(nusmv_stderr," : ");
      checker_base_print_type(self, nusmv_stderr,
                      PslNode_convert_to_node_ptr(psl_node_get_ite_else(expr)),
                      PslNode_convert_to_node_ptr(context));
      break;


    default: /* unknown kind of an expression */
      error_unreachable_code();
    } /* switch (node_get_type(expr)) */

    fprintf(nusmv_stderr,"\n");
    break;

  default:
    error_unreachable_code(); /* unknown kind of error */

  } /* switch (errorKind) */

  return isError;
}
예제 #11
0
/**Function********************************************************************

  Synopsis    []

  Description []

  SideEffects []

  SeeAlso     []

******************************************************************************/
static SymbType_ptr checker_psl_check_expr(CheckerBase_ptr self,
                                           node_ptr e, node_ptr ctx)
{
  /* converts and operates on PslNodes, not node_ptr: */
  PslNode_ptr expr = PslNode_convert_from_node_ptr(e);
  PslNode_ptr context = PslNode_convert_from_node_ptr(ctx);

  PslNode_ptr ctx_expr;

  /* wrap expr into the context. This is required by
     the facilities which remembers the type of expressions
     and by the violation handler. */
  if (context != PSL_NULL) {
    ctx_expr = PslNode_new_context(psl_node_context_to_main_context(context),
                                   expr);
  }
  else ctx_expr = expr;

  { /* checks memoizing */
    SymbType_ptr tmp = _GET_TYPE(ctx_expr);
    if (nullType != tmp) return tmp;
  }

  switch (psl_node_get_op(expr)) {
  case PSL_INF: return _SET_TYPE(ctx_expr, SymbTablePkg_integer_set_type());

  case PSL_SERE:
  case PSL_SERECOMPOUND:
    {
      SymbType_ptr type = _THROW(psl_node_get_left(expr), context);

      if (SymbType_is_error(type)) {
        /* earlier error */
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      if (SymbType_is_boolean(type)) return _SET_TYPE(ctx_expr, type);

      /* there is violation */
      if (_VIOLATION(SymbType_is_back_comp(type) ?
                     TC_VIOLATION_TYPE_BACK_COMP : TC_VIOLATION_TYPE_MANDATORY,
                     ctx_expr)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }


      /* keeps the current type */
      return _SET_TYPE(ctx_expr, type);
    }

    /* concatenation and multiple concatenation */
  case PSL_CONCATENATION:
    {
      PslNode_ptr iter;
      SymbType_ptr left = SYMB_TYPE(NULL);
      SymbType_ptr right = SYMB_TYPE(NULL);
      boolean is_ok = true;

      if (psl_node_get_right(expr) != PSL_NULL) {
        /* multiple concatenation */
        right = _THROW(psl_node_get_right(expr), context);
        if (SymbType_is_error(right)) {
          return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
        }

        if (!SymbType_is_boolean(right)) {
          if (_VIOLATION(SymbType_is_back_comp(right) ?
                         TC_VIOLATION_TYPE_BACK_COMP :
                         TC_VIOLATION_TYPE_MANDATORY,
                         ctx_expr)) {
            return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
          }
        }
      }

      /* checks all the list's elements */
      iter = psl_node_get_left(expr);
      while (is_ok && iter != PSL_NULL) {
        left = _THROW(psl_node_get_left(iter), context);
        if (SymbType_is_error(left)) {
          return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
        }

        is_ok = SymbType_is_boolean(left);
        iter = psl_node_get_right(iter);
      }

      if (!is_ok && _VIOLATION(SymbType_is_back_comp(left) ?
                               TC_VIOLATION_TYPE_BACK_COMP :
                               TC_VIOLATION_TYPE_MANDATORY,
                               ctx_expr)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      /* this is not an error after all -> return boolean type */
      return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
    }

  case PSL_SERECONCAT:
  case PSL_SEREFUSION:
    {
      SymbType_ptr type1 = _THROW(psl_node_get_left(expr), context);
      SymbType_ptr type2 = _THROW(psl_node_get_right(expr), context);


      if (SymbType_is_error(type1) || SymbType_is_error(type2)) {
        /* earlier error */
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      if (SymbType_is_boolean(type1) && SymbType_is_boolean(type2)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
      }

      /* there is violation */
      if (_VIOLATION(SymbType_is_back_comp(type1) &&
                     SymbType_is_back_comp(type2)?
                     TC_VIOLATION_TYPE_BACK_COMP : TC_VIOLATION_TYPE_MANDATORY,
                     ctx_expr)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      /* this is not an error after all -> return boolean type */
      return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
    }


  case PSL_SEREREPEATED:
    {
      PslNode_ptr sere, count;
      boolean is_ok = true;
      SymbType_ptr tcount = SYMB_TYPE(NULL);
      SymbType_ptr tsere;

      nusmv_assert(psl_node_get_left(expr) != PSL_NULL);
      sere = psl_node_sere_repeated_get_expr(expr);
      count = psl_node_sere_repeated_get_count(expr);

      /* checks the count at first: */
      if (count != PSL_NULL) {
        tcount = _THROW(count, context);

        if (SymbType_is_error(tcount)) return _SET_TYPE(ctx_expr, tcount);
        if (tcount != SymbTablePkg_integer_type() &&
            tcount != SymbTablePkg_boolean_type()) {
          is_ok = false;
        }
      }

      /* checks the sere now: */
      if (sere != PSL_NULL && is_ok) {
        tsere = _THROW(sere, context);
        if (SymbType_is_error(tsere)) {
          return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
        }

        if (SymbType_is_boolean(tsere)) {
          /* ok */
          return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
        }
      }
      else tsere = SymbTablePkg_error_type();

      /* is this a type error ? */
      if (!is_ok && _VIOLATION(SymbType_is_back_comp(tcount) &&
                               SymbType_is_back_comp(tsere) ?
                               TC_VIOLATION_TYPE_BACK_COMP :
                               TC_VIOLATION_TYPE_MANDATORY,
                               ctx_expr)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      /* this is not an error after all -> return boolean type */
      return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
    }


  case PSL_REPLPROP:
    {
      SymbTable_ptr symb_table =
        TypeChecker_get_symb_table(TYPE_CHECKER(NODE_WALKER(self)->master));

      PslNode_ptr repl = psl_node_repl_prop_get_replicator(expr);
      PslNode_ptr prop = psl_node_repl_prop_get_property(expr);
      PslNode_ptr value_set = psl_node_get_replicator_value_set(repl);
      PslNode_ptr evalue_set =
        psl_node_get_replicator_normalized_value_set(repl);
      PslNode_ptr id = psl_node_get_replicator_id(repl);
      boolean first_loop = true;
      ResolveSymbol_ptr rs;
      node_ptr id_ctx;

      rs = SymbTable_resolve_symbol(symb_table,
                            PslNode_convert_to_node_ptr(id), ctx);
      id_ctx = ResolveSymbol_get_resolved_name(rs);

      /* Prepares the forall value set */
      if (!psl_node_is_boolean_type(value_set)) {
        /* not boolean checks the value_set content */
        SymbType_ptr tvs = SymbType_create(SYMB_TYPE_ENUM, evalue_set);
        if (!TypeChecker_is_type_wellformed(
                                    TYPE_CHECKER(NODE_WALKER(self)->master),
                                    tvs, id_ctx)) {
          return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
        }
      }

      /* loops over the set of possible values of the ID, and defines
         a new define for each value. Then checks the replicated
         property */
      while (evalue_set != PSL_NULL) {
        SymbType_ptr prop_type;
        boolean is_ok = true;

        /* creates a new temporary layer to contain the id as input var */
        SymbLayer_ptr layer =
          SymbTable_create_layer(symb_table, NULL, SYMB_LAYER_POS_DEFAULT);

        /* checks the forall identifier: */
        if (!SymbLayer_can_declare_define(layer, id_ctx)) {
          _VIOLATION(TC_VIOLATION_AMBIGUOUS_IDENTIFIER, id);
          return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
        }

        /* declares a new temporary define to represent the id */
        SymbLayer_declare_define(layer, id_ctx, ctx,
                         PslNode_convert_to_node_ptr(
                             psl_node_cons_get_element(evalue_set)));


        /* now checks the replicated property: */
        prop_type = _THROW(prop, context);
        if (SymbType_is_error(prop_type)) {
          return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
        }

        is_ok = SymbType_is_boolean(prop_type);

        /* handle violation */
        if (!is_ok && _VIOLATION(SymbType_is_back_comp(prop_type) ?
                                 TC_VIOLATION_TYPE_BACK_COMP :
                                 TC_VIOLATION_TYPE_MANDATORY,
                                 ctx_expr)) {
          return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
        }

        /* gets rid of the temporary layer: */
        SymbTable_remove_layer(symb_table, layer);

        /* Disables memoizing, to force checking of the property event
           if already checked, as the property that is going to be
           checked at next iteration is grammatically identically to
           the one that is being checked, but contain different value
           for the forall ID */
        if (first_loop) {
          type_checker_enable_memoizing(
                TYPE_CHECKER(NODE_WALKER(self)->master), false);
          first_loop = false;
        }

        evalue_set = psl_node_cons_get_next(evalue_set); /* iterates on */
      } /* loop over forall range */

      /* re-enables memoizing. The property has already been memoized
         during the first loop iteration */
      type_checker_enable_memoizing(TYPE_CHECKER(NODE_WALKER(self)->master),
                                    true);

      /* this is not an error after all -> return boolean type */
      return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
    }

    case PSL_WSELECT:
      {
        SymbTable_ptr symb_table =
          TypeChecker_get_symb_table(TYPE_CHECKER(NODE_WALKER(self)->master));

        PslNode_ptr left = psl_node_get_left(expr);
        PslNode_ptr right = psl_node_get_right(expr);
        /* get the operand' type */
        SymbType_ptr type = _THROW(left, context);

        node_ptr hbit, lbit;
        int width;
        int highBound;
        int lowBound;

        if (SymbType_is_error(type)) { /* earlier error */
          return _SET_TYPE(ctx_expr, type);
        }

        hbit = PslNode_convert_to_node_ptr(psl_node_get_left(right));
        lbit = PslNode_convert_to_node_ptr(psl_node_get_right(right));

        hbit = CompileFlatten_resolve_number(symb_table, hbit, context);
        lbit = CompileFlatten_resolve_number(symb_table, lbit, context);

        nusmv_assert(COLON == psl_node_get_op(right));

        /* Non constant expressions for range */
        if ((Nil == hbit || Nil == lbit) ||
            (NUMBER != node_get_type(hbit) || NUMBER != node_get_type(lbit))) {
          if (_VIOLATION(TC_VIOLATION_UNCONSTANT_EXPRESSION, ctx_expr)) {
            return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
          }
          else { /* return arbitrary Word type */
            return _SET_TYPE(ctx_expr, SymbTablePkg_unsigned_word_type(1));
          }
        }

        /* check the first operand type */
        if (!SymbType_is_word(type)) { /* ERROR */
          if (_VIOLATION(TC_VIOLATION_TYPE_MANDATORY, ctx_expr)) {
            return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
          }
          else { /* return arbitrary Word type */
            return _SET_TYPE(ctx_expr, SymbTablePkg_unsigned_word_type(1));
          }
        }
        width = SymbType_get_word_width(type);
        highBound = NODE_TO_INT(car(hbit));
        lowBound  = NODE_TO_INT(car(lbit));

        /* checks the bit width */
        if (width <= highBound || highBound < lowBound || lowBound < 0) {
          /* ERROR */
          if (_VIOLATION(TC_VIOLATION_OUT_OF_WORD_WIDTH, ctx_expr)) {
            return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
          }
          else { /* give some realistic bit specifiers */
            highBound = 0;
            lowBound = 0;
          }
        }
        /* everything is OK */
        return _SET_TYPE(ctx_expr,
                         SymbTablePkg_unsigned_word_type(highBound - lowBound + 1));
      }

  case PSL_PIPEMINUSGT:
  case PSL_PIPEEQGT:
    {
      PslNode_ptr pre = psl_node_suffix_implication_get_premise(expr);
      PslNode_ptr con = psl_node_suffix_implication_get_consequence(expr);
      SymbType_ptr type1 = _THROW(pre, context);
      SymbType_ptr type2 = _THROW(con, context);

      if (SymbType_is_error(type1) || SymbType_is_error(type2)) {
        /* earlier error */
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      if (SymbType_is_boolean(type1) && SymbType_is_boolean(type2)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
      }

      /* there is violation */
      if (_VIOLATION(SymbType_is_back_comp(type1) &&
                     SymbType_is_back_comp(type2)?
                     TC_VIOLATION_TYPE_BACK_COMP : TC_VIOLATION_TYPE_MANDATORY,
                     ctx_expr)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      /* this is not an error after all -> return boolean type */
      return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
    }


  case PSL_ALWAYS:
  case PSL_NEVER:
  case PSL_EVENTUALLYBANG:
    {
      SymbType_ptr type = _THROW(psl_node_get_left(expr), context);

      if (SymbType_is_error(type)) {
        /* earlier error */
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      if (SymbType_is_boolean(type)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
      }

      /* there is violation */
      if (_VIOLATION(SymbType_is_back_comp(type) ?
                     TC_VIOLATION_TYPE_BACK_COMP : TC_VIOLATION_TYPE_MANDATORY,
                     ctx_expr)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      /* this is not an error after all -> return boolean type */
      return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
    }


  case PSL_WITHINBANG:
  case PSL_WITHIN:
  case PSL_WITHINBANG_:
  case PSL_WITHIN_:
    {
      PslNode_ptr n1 = psl_node_get_left(psl_node_get_left(expr));
      PslNode_ptr n2 = psl_node_get_right(psl_node_get_left(expr));
      PslNode_ptr n3 = psl_node_get_right(expr);

      SymbType_ptr t1 = _THROW(n1, context);
      SymbType_ptr t2 = _THROW(n2, context);
      SymbType_ptr t3 = _THROW(n3, context);

      if (SymbType_is_error(t1) || SymbType_is_error(t2) ||
          SymbType_is_error(t3) ) {
        /* earlier error */
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      if (SymbType_is_boolean(t1) && SymbType_is_boolean(t2) &&
          SymbType_is_boolean(t3)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
      }

      /* there is violation */
      if (_VIOLATION(SymbType_is_back_comp(t1) &&
                     SymbType_is_back_comp(t2) && SymbType_is_back_comp(t3) ?
                     TC_VIOLATION_TYPE_BACK_COMP : TC_VIOLATION_TYPE_MANDATORY,
                     ctx_expr)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      /* this is not an error after all -> return boolean type */
      return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
    }


  case PSL_NEXT_EVENT_ABANG:
  case PSL_NEXT_EVENT_A:
  case PSL_NEXT_EVENT_EBANG:
  case PSL_NEXT_EVENT_E:
  case PSL_NEXT_EVENTBANG:
  case PSL_NEXT_EVENT:
  case PSL_NEXT_ABANG:
  case PSL_NEXT_EBANG:
  case PSL_NEXT_A:
  case PSL_NEXT_E:
  case PSL_NEXTBANG:
  case PSL_NEXT:
  case PSL_X:
  case PSL_XBANG:
    {
      PslNode_ptr n1 = psl_node_extended_next_get_expr(expr);
      PslNode_ptr n2 = psl_node_extended_next_get_when(expr);
      PslNode_ptr n3 = psl_node_extended_next_get_condition(expr);

      SymbType_ptr t1 = _THROW(n1, context);

      SymbType_ptr t2 =
        (n2 != PSL_NULL) ? _THROW(n2, context) : SYMB_TYPE(NULL);

      SymbType_ptr t3 =
        (n3 != PSL_NULL) ? _THROW(n3, context) : SYMB_TYPE(NULL);

      if (SymbType_is_error(t1) ||
          (t2 != SYMB_TYPE(NULL) && SymbType_is_error(t2)) ||
          (t3 != SYMB_TYPE(NULL) && SymbType_is_error(t3))) {
        /* earlier error */
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      if (SymbType_is_boolean(t1) &&
          (t3 == SYMB_TYPE(NULL) || SymbType_is_boolean(t3))) {
        switch (psl_node_get_op(expr)) {
        case PSL_NEXTBANG:
        case PSL_NEXT:
        case PSL_X:
        case PSL_XBANG:
          /* number */
          if ((t2 == SYMB_TYPE(NULL)) ||
              ((SymbType_get_tag(t2) == SYMB_TYPE_INTEGER ||
                SymbType_is_pure_int_enum(t2) ||
                SymbType_is_boolean(t2)) &&
               psl_node_number_get_value(n2) >= 0)) {
            return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
          }
          break;

        case PSL_NEXT_ABANG:
        case PSL_NEXT_EBANG:
        case PSL_NEXT_A:
        case PSL_NEXT_E:
          /* finite range */
          if (t2 == SYMB_TYPE(NULL)) {
            return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
          }

          if (SymbType_get_tag(t2) == SYMB_TYPE_SET_INT) {
            PslNode_ptr low = psl_node_range_get_low(n2);
            PslNode_ptr high = psl_node_range_get_high(n2);
            if (!psl_node_is_infinite(high) &&
                psl_node_number_get_value(low) >= 0 &&
                psl_node_number_get_value(low) <= psl_node_number_get_value(high)) {
              return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
            }
          }
          break;


        case PSL_NEXT_EVENT_ABANG:
        case PSL_NEXT_EVENT_A:
        case PSL_NEXT_EVENT_EBANG:
        case PSL_NEXT_EVENT_E:
          /* finite positive range */
          if (t2 == SYMB_TYPE(NULL)) {
            return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
          }

          if (SymbType_get_tag(t2) == SYMB_TYPE_SET_INT) {
            PslNode_ptr low = psl_node_range_get_low(n2);
            PslNode_ptr high = psl_node_range_get_high(n2);
            if (!psl_node_is_infinite(high) &&
                psl_node_number_get_value(low) > 0 &&
                psl_node_number_get_value(low) <= psl_node_number_get_value(high)) {
              return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
            }
          }
          break;

        case PSL_NEXT_EVENTBANG:
        case PSL_NEXT_EVENT:
          /* positive number */
          if ((t2 == SYMB_TYPE(NULL)) ||
              ((SymbType_get_tag(t2) == SYMB_TYPE_INTEGER ||
                SymbType_is_pure_int_enum(t2) ||
                SymbType_is_boolean(t2)) &&
               psl_node_number_get_value(n2) > 0)) {
            return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
          }
          break;

        default:
          error_unreachable_code(); /* no other cases */
        }
      }

      /* there is violation */
      if (_VIOLATION(SymbType_is_back_comp(t1) &&
                     (t2 == SYMB_TYPE(NULL) || SymbType_is_back_comp(t2)) &&
                     (t3 == SYMB_TYPE(NULL) || SymbType_is_back_comp(t3)) ?
                     TC_VIOLATION_TYPE_BACK_COMP : TC_VIOLATION_TYPE_MANDATORY,
                     ctx_expr)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      /* this is not an error after all -> return boolean type */
      return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
    }


  case PSL_RANGE:
    /* colon is used only for index ranges */
    return _SET_TYPE(ctx_expr, SymbTablePkg_integer_set_type());


    /* binary operators */
  case PSL_BEFOREBANG:
  case PSL_BEFORE:
  case PSL_BEFOREBANG_:
  case PSL_BEFORE_:
  case PSL_UNTILBANG:
  case PSL_UNTIL:
  case PSL_UNTILBANG_:
  case PSL_UNTIL_:
  case PSL_ABORT:
  case PSL_W:
  case PSL_OR:
  case PSL_CARET:
  case PSL_TILDE:
  case PSL_EQEQ:
  case PSL_PIPEPIPE:
  case PSL_AMPERSANDAMPERSAND:
  case PSL_WHILENOTBANG:
  case PSL_WHILENOT:
  case PSL_WHILENOTBANG_:
  case PSL_WHILENOT_:
    {
      SymbType_ptr type1 = _THROW(psl_node_get_left(expr), context);
      SymbType_ptr type2 = _THROW(psl_node_get_right(expr), context);


      if (SymbType_is_error(type1) || SymbType_is_error(type2)) {
        /* earlier error */
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      if (SymbType_is_boolean(type1) && SymbType_is_boolean(type2)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
      }

      /* there is violation */
      if (_VIOLATION(SymbType_is_back_comp(type1) &&
                     SymbType_is_back_comp(type2)?
                     TC_VIOLATION_TYPE_BACK_COMP : TC_VIOLATION_TYPE_MANDATORY,
                     ctx_expr)) {
        return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
      }

      /* this is not an error after all -> return boolean type */
      return _SET_TYPE(ctx_expr, SymbTablePkg_boolean_type());
    }


  case PSL_ITE:
  {
    /* get the operands' type */
    SymbType_ptr returnType;
    SymbType_ptr condType = _THROW(psl_node_get_ite_cond(expr), context);
    SymbType_ptr thenType = _THROW(psl_node_get_ite_then(expr), context);
    SymbType_ptr elseType = _THROW(psl_node_get_ite_else(expr), context);

    if (SymbType_is_error(condType) ||
        SymbType_is_error(thenType) || SymbType_is_error(elseType)) {
      /* earlier error */
      return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
    }

   /* condition should be boolean */
    if ( (!SymbType_is_boolean(condType)) &&
         _VIOLATION(SymbType_is_back_comp(condType) ?
                    TC_VIOLATION_TYPE_BACK_COMP :
                    TC_VIOLATION_TYPE_MANDATORY,
                    expr) ) {
      return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
    }

    /* both ITE expressions should be convertable to a common type.
       If one of the expressions is of a set-type then before implicit
       convertion the other expression is converted to a corresponding
       set-type.
    */
    {
      SymbType_ptr tmp1 = SymbType_is_set(elseType) ?
        SymbType_make_set_type(thenType) : thenType;

      SymbType_ptr tmp2 = SymbType_is_set(thenType) ?
        SymbType_make_set_type(elseType) : elseType;

      if (nullType != tmp1 && nullType != tmp2) {
        returnType = SymbType_get_minimal_common(tmp1, tmp2);
      }
      else returnType = nullType;
    }

    /* we do not care which type exactly is obtained, since only
       correct type could pass the above code
    */
    if (nullType != returnType) {
      return _SET_TYPE(ctx_expr, returnType);
    }

    /* is this a type error ? */
    if (_VIOLATION(SymbType_is_back_comp(thenType) &&
                   SymbType_is_back_comp(elseType) ?
                   TC_VIOLATION_TYPE_BACK_COMP :
                   TC_VIOLATION_TYPE_MANDATORY,
                   expr)) {
      return _SET_TYPE(ctx_expr, SymbTablePkg_error_type());
    }

    /* this is not an error after all -> return one of the types  */
    return _SET_TYPE(ctx_expr, thenType);
  }

  default:
    internal_error("checker_psl_check_expr: not supported type");
  }

  return nullType;
}
예제 #12
0
/**Static function*************************************************************

  Synopsis           [Just prints an expression's operator to output_stream]

  Description        [This function is the almost the same as
  print_sexp, except this function does not print the children of the node.
  The expr must be a correct expression.
  The function is used in printing of an error messages only.]

  SideEffects        []

  SeeAlso            [print_sexp]
******************************************************************************/
static void print_operator(FILE* output_stream, PslNode_ptr expr)
{
  nusmv_assert(expr != PSL_NULL);
  switch (psl_node_get_op(expr)) {

  case PSL_INF: fprintf(output_stream, "inf"); return;

  case PSL_SERECONCAT: fprintf(output_stream, ";"); return;
  case PSL_SEREFUSION: fprintf(output_stream, ":"); return;

  case PSL_LBSPLAT: fprintf(output_stream, "[*"); return;
  case PSL_LBPLUSRB: fprintf(output_stream, "[+"); return;
  case PSL_LBEQ: fprintf(output_stream, "[="); return;
  case PSL_LBMINUSGT: fprintf(output_stream, "[->"); return;

  case PSL_REPLPROP: fprintf(output_stream, "forall"); return;

  case PSL_PIPEMINUSGT: fprintf(output_stream, "|->"); return;
  case PSL_PIPEEQGT: fprintf(output_stream, "|=>"); return;

  case PSL_ALWAYS: fprintf(output_stream, "always"); return;
  case PSL_NEVER: fprintf(output_stream, "never"); return;
  case PSL_EVENTUALLYBANG: fprintf(output_stream, "eventually!"); return;

  case PSL_WITHINBANG: fprintf(output_stream, "within!"); return;
  case PSL_WITHIN: fprintf(output_stream, "within"); return;
  case PSL_WITHINBANG_: fprintf(output_stream, "within!_"); return;
  case PSL_WITHIN_: fprintf(output_stream, "within_"); return;

  case PSL_NEXT_EVENT_ABANG: fprintf(output_stream, "next_event_a!"); return;
  case PSL_NEXT_EVENT_A: fprintf(output_stream, "next_event_a"); return;
  case PSL_NEXT_EVENT_EBANG: fprintf(output_stream, "next_event_e!"); return;
  case PSL_NEXT_EVENT_E: fprintf(output_stream, "next_event_e"); return;
  case PSL_NEXT_EVENTBANG: fprintf(output_stream, "next_event!"); return;
  case PSL_NEXT_EVENT: fprintf(output_stream, "next_event"); return;
  case PSL_NEXT_ABANG: fprintf(output_stream, "next_a!"); return;
  case PSL_NEXT_EBANG: fprintf(output_stream, "next_e!"); return;
  case PSL_NEXT_A: fprintf(output_stream, "next_a"); return;
  case PSL_NEXT_E: fprintf(output_stream, "next_e"); return;
  case PSL_NEXTBANG: fprintf(output_stream, "next!"); return;
  case PSL_NEXT: fprintf(output_stream, "next"); return;
  case PSL_X: fprintf(output_stream, "X"); return;
  case PSL_XBANG: fprintf(output_stream, "X!"); return;

  case PSL_BEFOREBANG: fprintf(output_stream, "before!"); return;
  case PSL_BEFORE: fprintf(output_stream, "before"); return;
  case PSL_BEFOREBANG_: fprintf(output_stream, "before!_"); return;
  case PSL_BEFORE_: fprintf(output_stream, "before_"); return;
  case PSL_UNTILBANG: fprintf(output_stream, "until!"); return;
  case PSL_UNTIL: fprintf(output_stream, "until"); return;
  case PSL_UNTILBANG_: fprintf(output_stream,"until!_"); return;
  case PSL_UNTIL_: fprintf(output_stream,"until_"); return;
  case PSL_ABORT: fprintf(output_stream,"abort"); return;
  case PSL_W: fprintf(output_stream,"W"); return;
  case PSL_OR: fprintf(output_stream,"or"); return;
  case PSL_CARET: fprintf(output_stream,"^"); return;
  case PSL_TILDE: fprintf(output_stream,"~"); return;
  case PSL_EQEQ: fprintf(output_stream,"=="); return;
  case PSL_PIPEPIPE: fprintf(output_stream,"||"); return;
  case PSL_AMPERSANDAMPERSAND: fprintf(output_stream,"&&"); return;
  case PSL_WHILENOTBANG: fprintf(output_stream,"whilenot!"); return;
  case PSL_WHILENOT: fprintf(output_stream,"whilenot"); return;
  case PSL_WHILENOTBANG_: fprintf(output_stream,"whilenot!_"); return;
  case PSL_WHILENOT_: fprintf(output_stream,"whilenot_"); return;

  case PSL_ITE: fprintf(output_stream,"ITE"); return;

    /* these are for sere compound */
  case AND: fprintf(output_stream,"&"); return;
  case OR: fprintf(output_stream,"|"); return;

  default:
    fprintf(nusmv_stderr, "\n%d\n", psl_node_get_op(expr));
    error_unreachable_code();
  }

}
예제 #13
0
int printer_psl_print_node(PrinterBase_ptr self, node_ptr n, int priority)
{
  const NuSMVEnv_ptr env = EnvObject_get_environment(ENV_OBJECT(self));
  const ErrorMgr_ptr errmgr =
    ERROR_MGR(NuSMVEnv_get_value(env, ENV_ERROR_MANAGER));

  PslNode_ptr psl = PslNode_convert_from_node_ptr(n);

  switch (psl_node_get_op(psl)) {

  case PSL_INF: return _PRINT("inf");

  case PSL_SERE:
    {
      int retval;

      if (!psl_node_is_sere(psl_node_get_left(psl))) retval = _PRINT("{");
      else retval = 1;

      retval = retval && _THROW(psl_node_get_left(psl));

      if (!psl_node_is_sere(psl_node_get_left(psl))) retval = _PRINT("}");
      return retval;
    }

  case PSL_SERECONCAT:
    return _PRINT("{") && \
      _THROW(psl_node_get_left(psl)) && _PRINT("; ") &&
      _THROW(psl_node_get_right(psl)) && _PRINT("}");

  case PSL_SEREFUSION:
    return _PRINT("{") && \
      _THROW(psl_node_get_left(psl)) && _PRINT(" : ") &&
      _THROW(psl_node_get_right(psl)) && _PRINT("}");

  case PSL_SERECOMPOUND:
    {
      int retval;
      PslNode_ptr op = psl_node_get_left(psl);
      nusmv_assert(op != PSL_NULL);

      /* left operand */
      retval = _PRINT("{") && _THROW(psl_node_get_left(op));

      switch (psl_node_get_op(op)) {
      case AND: retval = retval && _PRINT(" & "); break;
      case OR: retval = retval && _PRINT(" | "); break;
      case PSL_AMPERSANDAMPERSAND: retval = retval && _PRINT(" && "); break;
      default:
        ErrorMgr_internal_error(errmgr, "printer_psl_print_node: Unsupported sere "\
                       "compound operator");
      }

      /* right operand */
      return _THROW(psl_node_get_right(op)) && _PRINT("}");
    }

  case PSL_SEREREPEATED:
    {
      int retval;
      PslNode_ptr sere, count;

      nusmv_assert(psl_node_get_left(psl) != PSL_NULL);
      sere = psl_node_get_left(psl_node_get_left(psl));
      count = psl_node_get_right(psl);

      retval = _PRINT("{");
      if (sere != PSL_NULL) retval = retval && _THROW(sere);
      retval = retval && _PRINT("[");

      switch (psl_node_get_op(psl_node_get_left(psl))) {
      case PSL_LBSPLAT: retval = retval && _PRINT("*"); break;
      case PSL_LBPLUSRB: retval = retval && _PRINT("+"); break;
      case PSL_LBEQ: retval = retval && _PRINT("="); break;
      case PSL_LBMINUSGT: retval = retval && _PRINT("->"); break;
      default:
        ErrorMgr_internal_error(errmgr, "printer_psl_print_node: Unsupported sere "\
                       "repeated operator");
      }

      if (count != PSL_NULL) retval = retval && _THROW(count);
      return retval && _PRINT("]}");
    }

  case PSL_CONCATENATION:
    return _PRINT("{") && \
      _THROW(psl_node_get_left(psl)) && _PRINT("}");

  case PSL_REPLPROP:
    return _PRINT("( ") &&
      _THROW(psl_node_get_left(psl)) && /* replicator */
      _PRINT(" : ") &&
      _THROW(psl_node_get_right(psl)) && /* property */
      _PRINT(" )");

  case PSL_FORALL: /* replicator */
  case PSL_FORANY:
    {
      PslNode_ptr rvs = psl_node_get_replicator_value_set(psl);
      PslNode_ptr rr = psl_node_get_replicator_range(psl);
      int res;

      if (psl_node_get_op(psl) == PSL_FORALL) res = _PRINT("forall ");
      else res = _PRINT("forany ");
      res = res && _THROW(psl_node_get_replicator_id(psl));

      if (rr != PSL_NULL) {
        res = res && _PRINT(" [") && _THROW(rr) && _PRINT("]");
      }

      res = res && _PRINT(" in ");
      if (psl_node_is_boolean_type(rvs)) res = res && _THROW(rvs);
      else {
        res = res && _PRINT("{") && _THROW(rvs) && _PRINT("}");
      }
      return res;
    }


  case PSL_PIPEMINUSGT:
    {
      int res = _PRINT("(") &&
        _THROW(psl_node_get_left(psl_node_get_left(psl))) &&
        _PRINT(" |-> ") && _THROW(psl_node_get_right(psl_node_get_left(psl)));
      /* is it strong? */
      if (psl_node_get_right(psl) != PSL_NULL) res = res && _PRINT("!");
      return res && _PRINT(")");
    }

  case PSL_DIAMONDMINUSGT:
    {
      int res = _PRINT("(") &&
        _THROW(psl_node_get_left(psl_node_get_left(psl))) &&
        _PRINT(" <>-> ") && _THROW(psl_node_get_right(psl_node_get_left(psl)));
      /* is it strong? */
      if (psl_node_get_right(psl) != PSL_NULL) res = res && _PRINT("!");
      return res && _PRINT(")");
    }

  case PSL_PIPEEQGT:
    {
      int res = _PRINT("(") &&
        _THROW(psl_node_get_left(psl_node_get_left(psl))) &&
        _PRINT(" |=> ") && _THROW(psl_node_get_right(psl_node_get_left(psl)));
      /* is it strong? */
      if (psl_node_get_right(psl) != PSL_NULL) res = res && _PRINT("!");
      return res && _PRINT(")");
    }

  case PSL_ALWAYS:
  case PSL_NEVER:
  case PSL_EVENTUALLYBANG:
    {
      int res;
      switch (psl_node_get_op(psl)) {
      case PSL_ALWAYS: res = _PRINT("always "); break;
      case PSL_NEVER: res = _PRINT("never "); break;
      case PSL_EVENTUALLYBANG: res = _PRINT("eventually! "); break;
      default: error_unreachable_code(); /* no other cases */
      }

      if (!psl_node_is_sere(psl_node_get_left(psl))) res = res && _PRINT("(");

      res = res && _THROW(psl_node_get_left(psl));

      if (!psl_node_is_sere(psl_node_get_left(psl))) res = res && _PRINT(")");
      return res;
    }

  case PSL_WITHINBANG:
  case PSL_WITHIN:
  case PSL_WITHINBANG_:
  case PSL_WITHIN_:
    {
      int res;
      switch (psl_node_get_op(psl)) {
      case PSL_WITHINBANG: res = _PRINT("within!"); break;
      case PSL_WITHIN: res = _PRINT("within"); break;
      case PSL_WITHINBANG_: res = _PRINT("within!_"); break;
      case PSL_WITHIN_: res = _PRINT("within_"); break;
      default: error_unreachable_code(); /* no other cases here */
      }

    return res && _PRINT(" (") &&
      _THROW(psl_node_get_left(psl_node_get_left(psl))) &&
      _PRINT(", ") &&
      _THROW(psl_node_get_right(psl_node_get_left(psl))) &&
      _PRINT(") ") && _THROW(psl_node_get_right(psl));
    }

  case PSL_WHILENOTBANG:
  case PSL_WHILENOT:
  case PSL_WHILENOTBANG_:
  case PSL_WHILENOT_:
    {
      int res;
      switch (psl_node_get_op(psl)) {
      case PSL_WHILENOTBANG: res = _PRINT("whilenot!"); break;
      case PSL_WHILENOT: res = _PRINT("whilenot"); break;
      case PSL_WHILENOTBANG_: res = _PRINT("whilenot!_"); break;
      case PSL_WHILENOT_: res = _PRINT("whilenot_"); break;
      default: error_unreachable_code(); /* no other cases here */
      }

    return res && _PRINT(" (") &&
      _THROW(psl_node_get_left(psl)) && _PRINT(") ") &&
      _THROW(psl_node_get_right(psl));

    }

  case PSL_NEXT_EVENT_ABANG:
  case PSL_NEXT_EVENT_A:
  case PSL_NEXT_EVENT_EBANG:
  case PSL_NEXT_EVENT_E:
    {
      int res;
      switch (psl_node_get_op(psl)) {
      case PSL_NEXT_EVENT_ABANG: res = _PRINT("next_event_a!"); break;
      case PSL_NEXT_EVENT_A: res = _PRINT("next_event_a"); break;
      case PSL_NEXT_EVENT_EBANG: res = _PRINT("next_event_e!"); break;
      case PSL_NEXT_EVENT_E: res = _PRINT("next_event_e"); break;
      default: error_unreachable_code(); /* no other cases here */
      }

    return res && _PRINT(" (") &&
      _THROW(psl_node_get_right(psl_node_get_right(psl))) &&
      _PRINT(")") && _PRINT(" [") &&
      _THROW(psl_node_get_left(psl_node_get_right(psl))) &&
      _PRINT("]") && _PRINT(" (") &&
      _THROW(psl_node_get_left(psl)) && _PRINT(")");
    }


  case PSL_NEXT_EVENTBANG:
  case PSL_NEXT_EVENT:
    {
      int res;
      switch (psl_node_get_op(psl)) {
      case PSL_NEXT_EVENTBANG: res = _PRINT("next_event!"); break;
      case PSL_NEXT_EVENT: res = _PRINT("next_event"); break;
      default: error_unreachable_code(); /* no other cases here */
      }

      res = res && _PRINT(" (") &&
        _THROW(psl_node_get_right(psl_node_get_right(psl))) &&
        _PRINT(")");

      if (psl_node_get_left(psl_node_get_right(psl)) != PSL_NULL) {
        res = res && _PRINT(" [") &&
          _THROW(psl_node_get_left(psl_node_get_right(psl))) &&
          _PRINT("]");
      }

      return res && _PRINT(" (") &&
        _THROW(psl_node_get_left(psl)) && _PRINT(")");
    }

  case PSL_NEXT_ABANG:
  case PSL_NEXT_EBANG:
  case PSL_NEXT_A:
  case PSL_NEXT_E:
  case PSL_NEXTBANG:
  case PSL_NEXT:
    {
      int res;
      switch (psl_node_get_op(psl)) {
      case PSL_NEXT_ABANG: res = _PRINT("next_a!"); break;
      case PSL_NEXT_EBANG: res = _PRINT("next_e!"); break;
      case PSL_NEXT_A: res = _PRINT("next_a"); break;
      case PSL_NEXT_E: res = _PRINT("next_e"); break;
      case PSL_NEXTBANG: res = _PRINT("next!"); break;
      case PSL_NEXT: res = _PRINT("next"); break;
      default: error_unreachable_code(); /* no other cases here */
      }

      if (psl_node_get_right(psl) != PSL_NULL &&
          psl_node_get_left(psl_node_get_right(psl)) != PSL_NULL) {
        res = res && _PRINT(" [") &&
          _THROW(psl_node_get_left(psl_node_get_right(psl))) &&
          _PRINT("]");
      }

      return res && _PRINT(" (") &&
        _THROW(psl_node_get_left(psl)) && _PRINT(")");
    }

  case PSL_RANGE:
    return _THROW(psl_node_get_left(psl)) && _PRINT(":") &&
      _THROW(psl_node_get_right(psl));

    /* binary operators */
  case PSL_BEFOREBANG:
  case PSL_BEFORE:
  case PSL_BEFOREBANG_:
  case PSL_BEFORE_:
  case PSL_UNTILBANG:
  case PSL_UNTIL:
  case PSL_UNTILBANG_:
  case PSL_UNTIL_:
  case PSL_ABORT:
  case PSL_W:
  case PSL_OR:
  case PSL_CARET:
  case PSL_TILDE:
  case PSL_EQEQ:
  case PSL_PIPEPIPE:
  case PSL_AMPERSANDAMPERSAND:
    {
      int res;

      res = _PRINT("(") && _THROW(psl_node_get_left(psl)) && _PRINT(" ");

      switch (psl_node_get_op(psl)) {
      case PSL_BEFOREBANG: res = res && _PRINT("before!"); break;
      case PSL_BEFORE: res = res && _PRINT("before"); break;
      case PSL_BEFOREBANG_: res = res && _PRINT("before!_"); break;
      case PSL_BEFORE_: res = res && _PRINT("before_"); break;
      case PSL_UNTILBANG: res = res && _PRINT("until!"); break;
      case PSL_UNTIL: res = res && _PRINT("until"); break;
      case PSL_UNTILBANG_: res = res && _PRINT("until!_"); break;
      case PSL_UNTIL_: res = res && _PRINT("until_"); break;
      case PSL_ABORT:  res = res && _PRINT("abort"); break;
      case PSL_W: res = res && _PRINT("W"); break;
      case PSL_OR: res = res && _PRINT("or"); break;
      case PSL_CARET: res = res && _PRINT("^"); break;
      case PSL_TILDE: res = res && _PRINT("~"); break;
      case PSL_EQEQ: res = res && _PRINT("=="); break;
      case PSL_PIPEPIPE: res = res && _PRINT("||"); break;
      case PSL_AMPERSANDAMPERSAND: res = res && _PRINT("&&"); break;
      default: error_unreachable_code(); /* no other cases here */
      }

      return _PRINT(" ") && _THROW(psl_node_get_right(psl)) && _PRINT(")");
    }

  case PSL_X:
  case PSL_XBANG:
    {
      int res;

      switch (psl_node_get_op(psl)) {
      case PSL_X: res = _PRINT("X"); break;
      case PSL_XBANG: res = _PRINT("X!"); break;
      default: error_unreachable_code(); /* no other cases here */
      }

      if (psl_node_get_right(psl) != PSL_NULL) { /* simple next expression */
        res = res && _PRINT(" [") &&
          _THROW(psl_node_get_left(psl_node_get_right(psl))) && _PRINT("] ");
      }

      return res && _PRINT("(") &&
        _THROW(psl_node_get_left(psl)) && _PRINT(")");
    }

  case PSL_ITE:
      return _THROW(psl_node_get_ite_cond(psl)) &&
        _PRINT(" ? ") &&
        _THROW(psl_node_get_ite_then(psl)) && _PRINT(" : ") &&
        _THROW(psl_node_get_ite_else(psl));

  case PSL_WSELECT:
    return _PRINT("select(") &&
      _THROW(psl_node_get_left(psl)) &&
      _PRINT(", ") &&
      _THROW(psl_node_get_left(psl_node_get_right(psl))) &&
      _PRINT(", ") &&
      _THROW(psl_node_get_right(psl_node_get_right(psl))) &&
      _PRINT(")");
  default:
    ErrorMgr_internal_error(errmgr, "printer_psl_print_node: not supported type");
  }

  return 0;
}
예제 #14
0
/**Function********************************************************************

  Synopsis    [Checks for a var assignment and adds it to the conjuction set]

  Description [First, looks for the rbc f in cache and eventually gets the
               previous result.
               Else, checks the symbol of f for an IFF or for its two
               level AND equivalent. In these cases if finds a var assignment
               (one vertex being a VAR and the other not), adds it to the
               conjunction set.
               Returns 1 for backtracking, -1 if it does not need.]

  SideEffects [data->tmp_res is always set, except when the symbol of f is
               RBCVAR or a not negated RBCAND.
               if a var assignment is found, _data->res->conj is updated.]

  SeeAlso     []

******************************************************************************/
static int inline_set(Rbc_t* f, char* _data, nusmv_ptrint sign)
{
  InlineDfsData* data = (InlineDfsData*) _data;

  { /* reuses previous result searching in cache */
    InlineResult_ptr cir = rbc_inlining_cache_lookup_result(RbcId(f, sign));
    if (cir != INLINE_RESULT(NULL)) {
      ConjSet_inherit_from(data->res->conj, cir->conj);
      data->tmp_res = cir->fns;
      return 1; /* backtrack */
    }
  }

  switch (f->symbol) {
  case RBCTOP:
  case RBCVAR:
    return -1; /* continue (will be handled by other handler) */

  case RBCAND:
    /* possible inlining, check for an IFF equivalence */
    /* (~s)AND(~AND(x,y),~AND(~x,~y)) = (s)IFF(x,y) */
    {

#if !RBC_ENABLE_ITE_CONNECTIVE
      Rbc_t* left = RBC_GET_LEFTMOST_CHILD(f);
      Rbc_t* right = RBC_GET_SECOND_CHILD(f);
      if ((RbcGetRef(left)->symbol == RBCAND) &&
          (RbcGetRef(right)->symbol == RBCAND) &&
          (RbcIsSet(left)) &&
          (RbcIsSet(right)))
        {
          Rbc_t* l1 = RBC_GET_LEFTMOST_CHILD(left);
          Rbc_t* l2 = RBC_GET_SECOND_CHILD(left);
          Rbc_t* r1 = RBC_GET_LEFTMOST_CHILD(right);
          Rbc_t* r2 = RBC_GET_SECOND_CHILD(right);
          if (((l1 == RbcId(r1, RBC_FALSE)) || (l1 == RbcId(r2, RBC_FALSE))) &&
              ((l2 == RbcId(r1, RBC_FALSE)) || (l2 == RbcId(r2, RBC_FALSE))))
            {
              /* makes v <-> phi */
              if ((RbcGetRef(l1)->symbol != RBCVAR) &&
                  (RbcGetRef(l2)->symbol == RBCVAR))
                {
                  Rbc_t* tmp = l1;
                  l1 = l2; l2 = tmp;
                }
              /* is it a var assignment? */
              if (RbcGetRef(l1)->symbol == RBCVAR)
                {
                  /* no signed variables in cache */
                  if (RbcIsSet(l1))
                    {
                      /* move the "IFF's" sign to the right */
                      ConjSet_add_var_assign(data->res->conj,
                                             RbcId(l1, RBC_FALSE),
                                             RbcId(l2, sign));
                    }
                  else
                    {
                      /* move the "IFF's" sign to the right */
                      ConjSet_add_var_assign(data->res->conj,
                                             l1,
                                             RbcId(l2, sign ^ RBC_FALSE));
                    }
                  /* keeps it, will be substituted later */
                  data->tmp_res = RbcId(f, sign);
                  break;
                }
            }
        }
#endif
      /* AND, continue */
      if (sign == RBC_TRUE) return -1;
      /* OR, keep it, and backtrack */
      data->tmp_res = RbcId(f, sign);
      break;
    }

  case RBCIFF: {
    /* inlining, collects the IFF and removes it */
    Rbc_t* left = RBC_GET_LEFTMOST_CHILD(f);
    Rbc_t* right = RBC_GET_SECOND_CHILD(f);

    if (RbcGetRef(left)->symbol != RBCVAR &&
        RbcGetRef(right)->symbol == RBCVAR) { /* makes v <-> phi */
      Rbc_t* tmp = left;
      left = right; right = tmp;
    }

    /* is it a var assignment? */
    if (RbcGetRef(left)->symbol == RBCVAR) {
      /* move the IFF's sign to the right */
      ConjSet_add_var_assign(data->res->conj, left, RbcId(right, sign));
    }

    /* keeps it, will be subtituted later */
    data->tmp_res = RbcId(f, sign);
    break;
  }

  case RBCITE:
    data->tmp_res = RbcId(f, sign);
    break;

  default:
    error_unreachable_code(); /* no other cases */
  }

  return 1; /* backtrack */
}
예제 #15
0
파일: pslExpr.c 프로젝트: Simranpal/nusmv-1
/**Function********************************************************************

   Synopsis [Converts from base to number: TO BE IMPLEMENTED]

   Description        [optional]

   SideEffects        []

   SeeAlso            [optional]

******************************************************************************/
static int psl_expr_base_num_to_val(char* base_num)
{
  error_unreachable_code(); /* Cannot be called (not implemented) */
  return 0;
}
예제 #16
0
/**Function********************************************************************

  Synopsis           [Checks the truth value of a list of constraints on the
                      current state, transitions and next states,
                      from given starting state. This can be used
                      in guided interactive simulation to propose
                      the set of transitions which are allowed to
                      occur in the interactive simulation.]

  Description        [Given a list of constraints (next-expressions as be_ptr),
                      checks which (flattened) constraints are
                      satisfiable from a given state. Iff
                      from_state is NULL (and not TRUE), the
                      initial state of the fsm is
                      considered. Returned list contains values in
                      {0,1}, and has to be freed.]

  SideEffects        [None]

  SeeAlso            []

******************************************************************************/
Olist_ptr
Bmc_simulate_check_feasible_constraints(BeFsm_ptr be_fsm,
                                        BddEnc_ptr bdd_enc,
                                        Olist_ptr constraints,
                                        be_ptr from_state)
{
  Olist_ptr res = Olist_create();
#if NUSMV_HAVE_INCREMENTAL_SAT
  BeEnc_ptr be_enc = BeFsm_get_be_encoding(be_fsm);
  Be_Manager_ptr be_mgr = BeEnc_get_be_manager(be_enc);

  SatIncSolver_ptr solver;
  be_ptr be_init, be_trans, be_prob;

  /* Create the SAT solver instance */
  solver = Sat_CreateIncSolver(get_sat_solver(OptsHandler_get_instance()));
  if (SAT_INC_SOLVER(NULL) == solver) {
    internal_error("Incremental sat solver '%s' is not available.\n",
                   get_sat_solver(OptsHandler_get_instance()));
  }

  be_init = (from_state == (be_ptr) NULL) ? BeFsm_get_init(be_fsm) : from_state;
  be_init = Be_And(be_mgr, be_init, BeFsm_get_invar(be_fsm));

  be_trans = Be_And(be_mgr,
                    BeFsm_get_trans(be_fsm),
                    BeEnc_shift_curr_to_next(be_enc, BeFsm_get_invar(be_fsm)));

  be_prob = Be_And(be_mgr, be_init, be_trans);
  be_prob = BeEnc_untimed_expr_to_timed(be_enc, be_prob, 0);

  /* pushes the transition relation */
  bmc_simulate_add_be_into_inc_solver_positively(SAT_INC_SOLVER(solver),
                            SatSolver_get_permanent_group(SAT_SOLVER(solver)),
                            be_prob, be_enc);

  { /* loops over the constraints list */
    Oiter iter;
    OLIST_FOREACH(constraints, iter) {
      be_ptr be_constr = (be_ptr) Oiter_element(iter);
      boolean constr_truth;
      SatSolverGroup satGrp;
      SatSolverResult sat_res;

      be_constr = BeEnc_untimed_expr_to_timed(be_enc, be_constr, 0);

      /* pushes the constraint */
      satGrp = SatIncSolver_create_group(solver);
      bmc_simulate_add_be_into_inc_solver_positively(SAT_INC_SOLVER(solver),
                                                     satGrp, be_constr,
                                                     be_enc);

      /* solves */
      sat_res = SatSolver_solve_all_groups(SAT_SOLVER(solver));
      switch (sat_res) {
      case SAT_SOLVER_SATISFIABLE_PROBLEM:
        constr_truth = true; break;

      case SAT_SOLVER_UNSATISFIABLE_PROBLEM:
        constr_truth = false; break;

      default:
        error_unreachable_code(); /* no other options handled! */
      }

      Olist_append(res, (void*) constr_truth);
      SatIncSolver_destroy_group(solver, satGrp);
    } /* constr loop */
  }