コード例 #1
0
ファイル: wff2nnf.c プロジェクト: ancailliau/pynusmv
/**Function********************************************************************

   Synopsis           [Expands the given case expression]

   Description        [Expands the given case expression]

   SideEffects        []

   SeeAlso            []

******************************************************************************/
static node_ptr w2w_wff_expand_case(node_ptr wff)
{
  node_ptr res;

  nusmv_assert(CASE == node_get_type(wff) || IFTHENELSE == node_get_type(wff));
  res = w2w_wff_expand_case_aux(wff);

  return res;
}
コード例 #2
0
int printer_anon_map_entry_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));

  if (Nil == n) return 1;
  
  switch(node_get_type(n)) {
  case DOT:
    {
      /* since "." is also a separator, we can skip print the "," if
         immediately followed by "." */
      return
        _PRINT(NODE_ANONYMIZER_DOT_STR) &&
        _THROW(car(n)) &&
        ((Nil != cdr(n) && DOT == node_get_type(cdr(n))) || _PRINT(NODE_ANONYMIZER_SEPARATOR_STR)) &&
        _THROW(cdr(n));
    }

  case ATOM:
    /* Here ideally we would let the PrinterWffCore handle it. We can't because
       PrinterWffCore and this printer both handle DOT nodes. So we are
       duplicating the PrinterWffCore code for ATOM and NUMBER */
    if (!_PRINT(UStringMgr_get_string_text((string_ptr) car(n)))) return 0;
    if (cdr(n)) {
      char buf[20];
      int chars = snprintf(buf, 20, "_%d", NODE_TO_INT(cdr(n)));
      SNPRINTF_CHECK(chars, 20);

      return _PRINT(buf);
    }
    return 1;

  case NUMBER:
    {
      char buf[20];
      int c = snprintf(buf, 20, "%d", NODE_TO_INT(car(n)));
      SNPRINTF_CHECK(c, 20);

      return _PRINT(buf);
    }
    /* end of code duplication */

  default:
    ErrorMgr_internal_error(errmgr, "%s: not supported type = %d",
                            __func__,
                            node_get_type(n));
  }
}
コード例 #3
0
ファイル: wff2nnf.c プロジェクト: ancailliau/pynusmv
/**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;
  }
}
コード例 #4
0
ファイル: shader_graph.cpp プロジェクト: 0871087123/godot
Variant Shader::_get(const String& p_name) const {

	if (p_name.begins_with("nodes/")) {
		int idx=p_name.get_slice("/",1).to_int();
		Dictionary data;
		data["type"]=VisualServer::shader_node_get_type_info((VS::ShaderNodeType)node_get_type(idx)).name;
		data["pos"]=node_get_pos(idx);
		data["param"]=node_get_param(idx);
		return data;
	}
	if (p_name.begins_with("conns/")) {
		int idx=p_name.get_slice("/",1).to_int();
		Dictionary data;

		List<Connection> connections;
		get_connections(&connections);
		ERR_FAIL_INDEX_V( idx,connections.size(), Variant() );
		Connection c = connections[idx];

		data["src_id"]=c.src_id;
		data["src_slot"]=c.src_slot;
		data["dst_id"]=c.dst_id;
		data["dst_slot"]=c.dst_slot;
		return data;
	}

	return Variant();
}
コード例 #5
0
int disp_node_run(struct disp_object *disp_obj,
			 struct node_object *hnode, u32 rms_fxn,
			 u32 ul_execute_fxn, nodeenv node_env)
{
	u32 dw_arg;
	struct rms_command *rms_cmd;
	int status = 0;
	u8 dev_type;

	status = dev_get_dev_type(disp_obj->dev_obj, &dev_type);

	if (!status) {

		if (dev_type == DSP_UNIT) {

			/*
                                     
    */
			rms_cmd = (struct rms_command *)disp_obj->buf;
			rms_cmd->fxn = (rms_word) (rms_fxn);
			rms_cmd->arg1 = (rms_word) node_env;
			rms_cmd->arg2 = (rms_word) (ul_execute_fxn);
			rms_cmd->data = node_get_type(hnode);

			status = send_message(disp_obj, node_get_timeout(hnode),
					      sizeof(struct rms_command),
					      &dw_arg);
		}
	}

	return status;
}
コード例 #6
0
ファイル: node.c プロジェクト: wohinzd/oregano
Node *
node_new (Coords pos)
{
	Node *node;

	node = NODE (g_object_new (node_get_type(), NULL));

	node->key = pos;

	return node;
}
コード例 #7
0
ファイル: node.c プロジェクト: jnfeinstein/asuswrt-merlin
/*
 *  ======== node_change_priority ========
 *  Purpose:
 *      Change the priority of a node in the allocated state, or that is
 *      currently running or paused on the target.
 */
int node_change_priority(struct node_object *hnode, s32 prio)
{
	struct node_object *pnode = (struct node_object *)hnode;
	struct node_mgr *hnode_mgr = NULL;
	enum node_type node_type;
	enum node_state state;
	int status = 0;
	u32 proc_id;

	DBC_REQUIRE(refs > 0);

	if (!hnode || !hnode->hnode_mgr) {
		status = -EFAULT;
	} else {
		hnode_mgr = hnode->hnode_mgr;
		node_type = node_get_type(hnode);
		if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
			status = -EPERM;
		else if (prio < hnode_mgr->min_pri || prio > hnode_mgr->max_pri)
			status = -EDOM;
	}
	if (status)
		goto func_end;

	/* Enter critical section */
	mutex_lock(&hnode_mgr->node_mgr_lock);

	state = node_get_state(hnode);
	if (state == NODE_ALLOCATED || state == NODE_PAUSED) {
		NODE_SET_PRIORITY(hnode, prio);
	} else {
		if (state != NODE_RUNNING) {
			status = -EBADR;
			goto func_cont;
		}
		status = proc_get_processor_id(pnode->hprocessor, &proc_id);
		if (proc_id == DSP_UNIT) {
			status =
			    disp_node_change_priority(hnode_mgr->disp_obj,
						      hnode,
						      hnode_mgr->ul_fxn_addrs
						      [RMSCHANGENODEPRIORITY],
						      hnode->node_env, prio);
		}
		if (status >= 0)
			NODE_SET_PRIORITY(hnode, prio);

	}
func_cont:
	/* Leave critical section */
	mutex_unlock(&hnode_mgr->node_mgr_lock);
func_end:
	return status;
}
コード例 #8
0
ファイル: HrcDumper.c プロジェクト: hklarner/NuSMV-a
void hrc_dumper_dump_var_type(HrcDumper_ptr self, node_ptr node)
{
  const NuSMVEnv_ptr env = EnvObject_get_environment(ENV_OBJECT(self));
  const ErrorMgr_ptr errmgr =
    ERROR_MGR(NuSMVEnv_get_value(env, ENV_ERROR_MANAGER));

  int node_type = node_get_type(node);

  switch (node_type) {
  case BOOLEAN:
  case TWODOTS: /* range */
    _HRC_DUMP_NODE(node);
    break;

  case INTEGER:
    _HRC_DUMP_STR("integer");
    break;

  case REAL:
    _HRC_DUMP_STR("real");
    break;

  case SIGNED_WORD:
    _HRC_DUMP_STR("signed word[");
    _HRC_DUMP_NODE(car(node));
    _HRC_DUMP_STR("]");
    break;

  case UNSIGNED_WORD:
    _HRC_DUMP_STR("unsigned word[");
    _HRC_DUMP_NODE(car(node));
    _HRC_DUMP_STR("]");
    break;

  case SCALAR:
    hrc_dumper_dump_scalar_type(self, node);
    break;

  case WORDARRAY_TYPE:
    _HRC_DUMP_STR("array word[");
    _HRC_DUMP_NODE(car(node));
    _HRC_DUMP_STR("]");

    _HRC_DUMP_STR(" of ");
    
    /* recursively prints the array type */
    hrc_dumper_dump_var_type(self, cdr(node));
    break;

  case INTARRAY_TYPE:
    _HRC_DUMP_STR("array integer of ");
    
    /* recursively prints the array type */
    hrc_dumper_dump_var_type(self, car(node));
    break;

  case ARRAY_TYPE:
    _HRC_DUMP_STR("array ");

    /* Prints subrange of array n..m */
    _HRC_DUMP_NODE(car(node));

    _HRC_DUMP_STR(" of ");

    /* recursively prints the array type */
    hrc_dumper_dump_var_type(self, cdr(node));
    break;

  case NFUNCTION_TYPE:
    {
      node_ptr iter;
      boolean is_first = true;
      NODE_CONS_LIST_FOREACH(car(node), iter) {
        node_ptr elem = Node_conslist_get(iter);

        if (! is_first) {
          _HRC_DUMP_STR(" * ");
        }
        is_first = false;

        hrc_dumper_dump_var_type(self, elem);
      }

      _HRC_DUMP_STR(" -> ");
      hrc_dumper_dump_var_type(self, cdr(node));
      break;
    }

  default:
    ErrorMgr_internal_error(errmgr, "Type %d not supported by hrc emitter.\n", node_type);
  }
コード例 #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
ファイル: CheckerPsl.c プロジェクト: ancailliau/pynusmv
/**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
ファイル: CheckerPsl.c プロジェクト: ancailliau/pynusmv
/**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
ファイル: exprWff.c プロジェクト: hklarner/NuSMV-a
int Wff_get_depth(const NuSMVEnv_ptr env, node_ptr ltl_wff)
{
  int depth = -1;
  int d1,d2;

  switch (node_get_type(ltl_wff)) {
  case TRUEEXP:                           /* TRUEEXP   */
  case FALSEEXP:                          /* FALSEEXP  */
    depth = 0;
    break;

  case NOT:                             /* NOT       */
    depth = Wff_get_depth(env, car(ltl_wff));
    break;

  case AND:                             /* AND       */
  case OR:                              /* OR        */
  case IFF:                             /* IFF        */
    d1 = Wff_get_depth(env, car(ltl_wff));
    d2 = Wff_get_depth(env, cdr(ltl_wff));
    depth = max(d1,d2);
    break;

  case OP_NEXT:                         /* OP_NEXT   */
  case OP_PREC:                         /* OP_PREC   */
  case OP_NOTPRECNOT:                   /* OP_NOTPRECNOT */
  case OP_GLOBAL:                       /* OP_GLOBAL */
  case OP_HISTORICAL:                   /* OP_HISTORICAL */
  case OP_FUTURE:                       /* OP_FUTURE */
  case OP_ONCE:                         /* OP_ONCE */
    depth = 1 + Wff_get_depth(env, car(ltl_wff));
    break;

  case UNTIL:                           /* UNTIL     */
  case SINCE:                           /* SINCE     */
  case RELEASES:                        /* RELEASES  */
  case TRIGGERED:                       /* TRIGGERED */
    d1 = Wff_get_depth(env, car(ltl_wff));
    d2 = Wff_get_depth(env, cdr(ltl_wff));
    depth = 1 + max(d1,d2);
    break;

  case IMPLIES:
    {
      const ErrorMgr_ptr errmgr =
        ERROR_MGR(NuSMVEnv_get_value(env, ENV_ERROR_MANAGER));
      ErrorMgr_internal_error(errmgr, "implies should have been nnf-ef away!\n");
      break;
    }

  case BIT:
  case DOT:
  case ARRAY:
    depth = 0;
    break;

    /* in pure bool bmc these nodes these nodes are not present,
       whereas the mathsat add-on calls this function while building
       the tableau for LTL specifications. In the latter case the
       formula is no longer guaranteed to be pure boolean.*/
  case CAST_BOOL:
  case EQUAL:
  case NOTEQUAL:
  case LT:
  case GT:
  case LE:
  case GE:
  case SETIN:
    depth = 0;
    break;

    /* these nodes are expected to be unreachable as already handled
       by previous cases */
  case ATOM:
  case NUMBER:
  case NUMBER_UNSIGNED_WORD:
  case NUMBER_SIGNED_WORD:
  case NUMBER_FRAC:
  case NUMBER_REAL:
  case NUMBER_EXP:
    {
      const ErrorMgr_ptr errmgr =
        ERROR_MGR(NuSMVEnv_get_value(env, ENV_ERROR_MANAGER));
      ErrorMgr_internal_error(errmgr, "Unexpected leaf, node type %d\n",
                              node_get_type(ltl_wff));
    }
    break;

  case EX:
  case AX:
  case EF:
  case AF:
  case EG:
  case AG:
  case EBF:
  case EBG:
  case ABF:
  case ABG:
    {
      const ErrorMgr_ptr errmgr =
        ERROR_MGR(NuSMVEnv_get_value(env, ENV_ERROR_MANAGER));
      ErrorMgr_internal_error(errmgr, "Unexpected CTL operator, node type %d\n",
                              node_get_type(ltl_wff));
    }
    break;

  default:
    {
      const ErrorMgr_ptr errmgr =
        ERROR_MGR(NuSMVEnv_get_value(env, ENV_ERROR_MANAGER));
      /* no other cases are currently allowed */
      ErrorMgr_internal_error(errmgr, "Unexpected node, node type %d\n",
                              node_get_type(ltl_wff));
    }
  }

  return depth;
}
コード例 #13
0
int disp_node_create(struct disp_object *disp_obj,
			    struct node_object *hnode, u32 rms_fxn,
			    u32 ul_create_fxn,
			    const struct node_createargs *pargs,
			    nodeenv *node_env)
{
	struct node_msgargs node_msg_args;
	struct node_taskargs task_arg_obj;
	struct rms_command *rms_cmd;
	struct rms_msg_args *pmsg_args;
	struct rms_more_task_args *more_task_args;
	enum node_type node_type;
	u32 dw_length;
	rms_word *pdw_buf = NULL;
	u32 ul_bytes;
	u32 i;
	u32 total;
	u32 chars_in_rms_word;
	s32 task_args_offset;
	s32 sio_in_def_offset;
	s32 sio_out_def_offset;
	s32 sio_defs_offset;
	s32 args_offset = -1;
	s32 offset;
	struct node_strmdef strm_def;
	u32 max;
	int status = 0;
	struct dsp_nodeinfo node_info;
	u8 dev_type;

	status = dev_get_dev_type(disp_obj->dev_obj, &dev_type);

	if (status)
		goto func_end;

	if (dev_type != DSP_UNIT) {
		dev_dbg(bridge, "%s: unknown device type = 0x%x\n",
			__func__, dev_type);
		goto func_end;
	}
	node_type = node_get_type(hnode);
	node_msg_args = pargs->asa.node_msg_args;
	max = disp_obj->bufsize_rms;	/*                                    */
	chars_in_rms_word = sizeof(rms_word) / disp_obj->char_size;
	/*                                             */
	dw_length =
	    (node_msg_args.arg_length + chars_in_rms_word -
	     1) / chars_in_rms_word;
	/*                                              */
	total = sizeof(struct rms_command) / sizeof(rms_word) +
	    sizeof(struct rms_msg_args)
	    / sizeof(rms_word) - 1 + dw_length;
	if (total >= max) {
		status = -EPERM;
		dev_dbg(bridge, "%s: Message args too large for buffer! size "
			"= %d, max = %d\n", __func__, total, max);
	}
	/*
                                   
                                                
   
                 
                                    
                                          
                       
                  
   
                  
                               
                                            
                                                          
                                   
                          
   
                                        
                 
                   
                          
                      
             
                                
                                                                     
                                 
                                                               
                
                                                                  
                                                                    
   
                                       
   
  */
	if (!status) {
		total = 0;	/*                                        */
		pdw_buf = (rms_word *) disp_obj->buf;
		rms_cmd = (struct rms_command *)pdw_buf;
		rms_cmd->fxn = (rms_word) (rms_fxn);
		rms_cmd->arg1 = (rms_word) (ul_create_fxn);
		if (node_get_load_type(hnode) == NLDR_DYNAMICLOAD) {
			/*                      */
			rms_cmd->arg2 = 1;	/*                */
		} else {
			/*                     */
			rms_cmd->arg2 = 0;	/*                */
		}
		rms_cmd->data = node_get_type(hnode);
		/*
                                                           
                                                             
                         
   */
		args_offset = 3;
		total += sizeof(struct rms_command) / sizeof(rms_word);
		/*              */
		pmsg_args = (struct rms_msg_args *)(pdw_buf + total);
		pmsg_args->max_msgs = node_msg_args.max_msgs;
		pmsg_args->segid = node_msg_args.seg_id;
		pmsg_args->notify_type = node_msg_args.notify_type;
		pmsg_args->arg_length = node_msg_args.arg_length;
		total += sizeof(struct rms_msg_args) / sizeof(rms_word) - 1;
		memcpy(pdw_buf + total, node_msg_args.pdata,
		       node_msg_args.arg_length);
		total += dw_length;
	}
	if (status)
		goto func_end;

	/*                                                                 */
	if (node_type == NODE_TASK || node_type == NODE_DAISSOCKET) {
		task_arg_obj = pargs->asa.task_arg_obj;
		task_args_offset = total;
		total += sizeof(struct rms_more_task_args) / sizeof(rms_word) +
		    1 + task_arg_obj.num_inputs + task_arg_obj.num_outputs;
		/*                     */
		if (total < max) {
			total = task_args_offset;
			more_task_args = (struct rms_more_task_args *)(pdw_buf +
								       total);
			/*
                                                          
                                                    
                                                     
    */
			get_node_info(hnode, &node_info);
			more_task_args->priority = node_info.execution_priority;
			more_task_args->stack_size = task_arg_obj.stack_size;
			more_task_args->sysstack_size =
			    task_arg_obj.sys_stack_size;
			more_task_args->stack_seg = task_arg_obj.stack_seg;
			more_task_args->heap_addr = task_arg_obj.dsp_heap_addr;
			more_task_args->heap_size = task_arg_obj.heap_size;
			more_task_args->misc = task_arg_obj.dais_arg;
			more_task_args->num_input_streams =
			    task_arg_obj.num_inputs;
			total +=
			    sizeof(struct rms_more_task_args) /
			    sizeof(rms_word);
			dev_dbg(bridge, "%s: dsp_heap_addr %x, heap_size %x\n",
				__func__, task_arg_obj.dsp_heap_addr,
				task_arg_obj.heap_size);
			/*                                           
                                                     
                       */
			sio_in_def_offset = total;
			total += task_arg_obj.num_inputs;
			pdw_buf[total++] = task_arg_obj.num_outputs;
			sio_out_def_offset = total;
			total += task_arg_obj.num_outputs;
			sio_defs_offset = total;
			/*                           */
			offset = sio_defs_offset;
			for (i = 0; i < task_arg_obj.num_inputs; i++) {
				if (status)
					break;

				pdw_buf[sio_in_def_offset + i] =
				    (offset - args_offset)
				    * (sizeof(rms_word) / DSPWORDSIZE);
				strm_def = task_arg_obj.strm_in_def[i];
				status =
				    fill_stream_def(pdw_buf, &total, offset,
						    strm_def, max,
						    chars_in_rms_word);
				offset = total;
			}
			for (i = 0; (i < task_arg_obj.num_outputs) &&
			     (!status); i++) {
				pdw_buf[sio_out_def_offset + i] =
				    (offset - args_offset)
				    * (sizeof(rms_word) / DSPWORDSIZE);
				strm_def = task_arg_obj.strm_out_def[i];
				status =
				    fill_stream_def(pdw_buf, &total, offset,
						    strm_def, max,
						    chars_in_rms_word);
				offset = total;
			}
		} else {
			/*                */
			status = -EPERM;
		}
	}
	if (!status) {
		ul_bytes = total * sizeof(rms_word);
		status = send_message(disp_obj, node_get_timeout(hnode),
				      ul_bytes, node_env);
	}
func_end:
	return status;
}
コード例 #14
0
ファイル: wff2nnf.c プロジェクト: ancailliau/pynusmv
/**Function********************************************************************

   Synopsis           [The private function that does the actual
                       wff2nnf conversion]

   Description        [The private function that does the actual
                       wff2nnf conversion]

   SideEffects        []

   SeeAlso            []

******************************************************************************/
static node_ptr w2w_wff_mk_nnf(node_ptr wff, boolean pol)
{
  node_ptr res;

  /* if reached a Nil branch then end recursion with a Nil node */
  if (wff == Nil) return Nil;

  /* Only temporal operator X (node type OP_NEXT) is legal in LTL wffs.
     The operator NEXT used in model definition is trapped. */
  nusmv_assert(node_get_type(wff) != NEXT);

  res = w2w_wff2nnf_hash_lookup_entry(wff, pol);
  if (res != (node_ptr) NULL) return res;

  switch (node_get_type(wff)) {
  case TRUEEXP:
    if (pol) res = Wff_make_truth();
    else res = Wff_make_falsity();  /* !1 <-> 0 */
    break;

  case FALSEEXP:
    if (pol) res = Wff_make_falsity();
    else res = Wff_make_truth();    /* !0 <-> 1 */
    break;

  case NOT:
    /* !(a) <-> (!a) */
    /* !(!a) <-> a */
    res = w2w_wff_mk_nnf(car(wff), !pol);
    break;

  case AND:
    if (pol) res = Wff_make_and(w2w_wff_mk_nnf(car(wff), true),
                                w2w_wff_mk_nnf(cdr(wff), true));
    else {
      /* !(a & b) <-> (!a | !b) */
      res = Wff_make_or(w2w_wff_mk_nnf(car(wff), false),
                        w2w_wff_mk_nnf(cdr(wff), false));
    }
    break;

  case OR:
    if (pol) res = Wff_make_or(w2w_wff_mk_nnf(car(wff), true),
                               w2w_wff_mk_nnf(cdr(wff), true));
    else {
      /* !(a | b) <-> (!a & !b) */
      res = Wff_make_and(w2w_wff_mk_nnf(car(wff), false),
                         w2w_wff_mk_nnf(cdr(wff), false));
    }
    break;

  case IMPLIES:
    if (pol) {
      /* (a -> b) <-> !(a & !b) <-> (!a | b) */
      res = Wff_make_or(w2w_wff_mk_nnf(car(wff), false),
                        w2w_wff_mk_nnf(cdr(wff), true));
    }
    else {
      /* !(a -> b) <-> (a & !b) */
      res = Wff_make_and(w2w_wff_mk_nnf(car(wff), true),
                         w2w_wff_mk_nnf(cdr(wff), false));
    }
    break;

  case IFF:
    if (pol) {
      /* (a <-> b) <->
         !(a & !b) & !(b & !a) <->
         (!a | b) & (!b | a) */
      res = Wff_make_and( Wff_make_or(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)),
                          Wff_make_or(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)) );
    }
    else {
      /* !(a <-> b) <->
         !(!(a & !b) & !(b & !a)) <->
         (a & !b) | (b & !a) */
      res = Wff_make_or( Wff_make_and(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)),
                         Wff_make_and(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)) );
    }
    break;

  case XOR:
    if (pol) {
      /* (a xor b) <-> (a & !b) | (!a & b) */
      res = Wff_make_or( Wff_make_and(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)),
                         Wff_make_and(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)) );
    }
    else {
      /* !(a xnor b) <-> (a | !b) & (!a | b) */
      res = Wff_make_and( Wff_make_or(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)),
                          Wff_make_or(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)) );
    }
    break;

  case XNOR:
    if (pol) {
      /* (a xnor b) <-> (!a | b) & (!b | a) */
      res = Wff_make_and( Wff_make_or(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)),
                          Wff_make_or(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)) );
    }
    else {
      /* !(a xnor b) <-> (a & !b) | (!a & b) */
      res = Wff_make_or( Wff_make_and(w2w_wff_mk_nnf(car(wff), true),
                                      w2w_wff_mk_nnf(cdr(wff), false)),
                         Wff_make_and(w2w_wff_mk_nnf(car(wff), false),
                                      w2w_wff_mk_nnf(cdr(wff), true)) );
    }
    break;

  case OP_NEXT:
    /* !X(a) <-> X(!a) */
    res = Wff_make_opnext(w2w_wff_mk_nnf(car(wff), pol));
    break;

  case OP_PREC:
    /* !Y(a) <-> Z(!a) */
    if (pol) res = Wff_make_opprec(w2w_wff_mk_nnf(car(wff), pol));
    else res = Wff_make_opnotprecnot(w2w_wff_mk_nnf(car(wff), pol));
    break;

  case OP_NOTPRECNOT:
    /* !Z(a) <-> Y(!a) */
    if (pol) res = Wff_make_opnotprecnot(w2w_wff_mk_nnf(car(wff), pol));
    else res = Wff_make_opprec(w2w_wff_mk_nnf(car(wff), pol));
    break;

  case OP_GLOBAL:
    if (pol) res = Wff_make_globally(w2w_wff_mk_nnf(car(wff), pol));
    else {
      /* !G(a) <-> F(!a) */
      res = Wff_make_eventually(w2w_wff_mk_nnf(car(wff), pol));
    }
    break;

  case OP_HISTORICAL:
    if (pol) res = Wff_make_historically(w2w_wff_mk_nnf(car(wff), pol));
    else {
      /* !H(a) <-> O(!a) */
      res = Wff_make_once(w2w_wff_mk_nnf(car(wff), pol));
    }
    break;

  case OP_FUTURE:
    if (pol) res = Wff_make_eventually(w2w_wff_mk_nnf(car(wff), pol));
    else {
      /* !F(a) <-> G(!a) */
      res = Wff_make_globally(w2w_wff_mk_nnf(car(wff), pol));
    }
    break;

  case OP_ONCE:
    if (pol) res = Wff_make_once(w2w_wff_mk_nnf(car(wff), pol));
    else {
      /* !O(a) <-> H(!a) */
      res = Wff_make_historically(w2w_wff_mk_nnf(car(wff), pol));
    }
    break;

  case UNTIL:
    if (pol) res = Wff_make_until(w2w_wff_mk_nnf(car(wff), pol),
                                  w2w_wff_mk_nnf(cdr(wff), pol));
    else {
      /* !(a U b) <-> (!a V !b) */
      res = Wff_make_releases(w2w_wff_mk_nnf(car(wff), pol),
                              w2w_wff_mk_nnf(cdr(wff), pol));
    }
    break;

  case SINCE:
    if (pol) res = Wff_make_since(w2w_wff_mk_nnf(car(wff), pol),
                                  w2w_wff_mk_nnf(cdr(wff), pol));
    else {
      /* !(a S b) <-> (!a T !b) */
      res = Wff_make_triggered(w2w_wff_mk_nnf(car(wff), pol),
                               w2w_wff_mk_nnf(cdr(wff), pol));
    }
    break;

  case RELEASES:
    if (pol) res = Wff_make_releases(w2w_wff_mk_nnf(car(wff), pol),
                                     w2w_wff_mk_nnf(cdr(wff), pol));
    else {
      /* !(a V b) <-> (!a U !b) */
      res = Wff_make_until(w2w_wff_mk_nnf(car(wff), pol),
                           w2w_wff_mk_nnf(cdr(wff), pol));
    }
    break;

  case TRIGGERED:
    if (pol) res = Wff_make_triggered(w2w_wff_mk_nnf(car(wff), pol),
                                      w2w_wff_mk_nnf(cdr(wff), pol));
    else {
      /* !(a T b) <-> (!a S !b) */
      res = Wff_make_since(w2w_wff_mk_nnf(car(wff), pol),
                           w2w_wff_mk_nnf(cdr(wff), pol));
    }
    break;

  case IFTHENELSE:
  case CASE:
    {
      node_ptr nocase_wff = w2w_wff_expand_case(wff);
      res = w2w_wff_mk_nnf(nocase_wff, pol);
      break;
    }

  case BIT:
  case DOT:
  case ARRAY:
    /* it is a bexp var */
    if (pol) res = wff;
    else res = Wff_make_not(wff);
    break;

  case ATOM:
  case NUMBER:
  case NUMBER_UNSIGNED_WORD:
  case NUMBER_SIGNED_WORD:
  case NUMBER_FRAC:
  case NUMBER_REAL:
  case NUMBER_EXP:
    /* internal format for atoms that should have been previously
       hidden within DOT and ARRAY */
    internal_error("w2w_wff_mk_nnf: unexpected leaf %d\n",
                   node_get_type(wff));
    res = (node_ptr) NULL;
    break;

  case MOD:
    internal_error("w2w_wff_mk_nnf: unexpected mod operator\n");

    /* stop recursion when a predicate is found */
  case LE: case LT:
  case GE: case GT:
  case EQUAL: case NOTEQUAL:
  case SETIN:
    res = (pol) ? wff : Wff_make_not(wff);
      break;

  default:
    internal_error("w2w_wff_mk_nnf: unexpected TOKEN %d\n",
                   node_get_type(wff));

  }

  if (res != (node_ptr) NULL) {
    w2w_wff2nnf_hash_insert_entry(wff, pol, res);
  }

  return res;
}
コード例 #15
0
ファイル: node.c プロジェクト: jnfeinstein/asuswrt-merlin
/*
 *  ======== node_allocate ========
 *  Purpose:
 *      Allocate GPP resources to manage a node on the DSP.
 */
int node_allocate(struct proc_object *hprocessor,
			const struct dsp_uuid *node_uuid,
			const struct dsp_cbdata *pargs,
			const struct dsp_nodeattrin *attr_in,
			struct node_res_object **noderes,
			struct process_context *pr_ctxt)
{
	struct node_mgr *hnode_mgr;
	struct dev_object *hdev_obj;
	struct node_object *pnode = NULL;
	enum node_type node_type = NODE_TASK;
	struct node_msgargs *pmsg_args;
	struct node_taskargs *ptask_args;
	u32 num_streams;
	struct bridge_drv_interface *intf_fxns;
	int status = 0;
	struct cmm_object *hcmm_mgr = NULL;	/* Shared memory manager hndl */
	u32 proc_id;
	u32 pul_value;
	u32 dynext_base;
	u32 off_set = 0;
	u32 ul_stack_seg_addr, ul_stack_seg_val;
	u32 ul_gpp_mem_base;
	struct cfg_hostres *host_res;
	struct bridge_dev_context *pbridge_context;
	u32 mapped_addr = 0;
	u32 map_attrs = 0x0;
	struct dsp_processorstate proc_state;
#ifdef DSP_DMM_DEBUG
	struct dmm_object *dmm_mgr;
	struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
#endif

	void *node_res;

	DBC_REQUIRE(refs > 0);
	DBC_REQUIRE(hprocessor != NULL);
	DBC_REQUIRE(noderes != NULL);
	DBC_REQUIRE(node_uuid != NULL);

	*noderes = NULL;

	status = proc_get_processor_id(hprocessor, &proc_id);

	if (proc_id != DSP_UNIT)
		goto func_end;

	status = proc_get_dev_object(hprocessor, &hdev_obj);
	if (!status) {
		status = dev_get_node_manager(hdev_obj, &hnode_mgr);
		if (hnode_mgr == NULL)
			status = -EPERM;

	}

	if (status)
		goto func_end;

	status = dev_get_bridge_context(hdev_obj, &pbridge_context);
	if (!pbridge_context) {
		status = -EFAULT;
		goto func_end;
	}

	status = proc_get_state(hprocessor, &proc_state,
				sizeof(struct dsp_processorstate));
	if (status)
		goto func_end;
	/* If processor is in error state then don't attempt
	   to send the message */
	if (proc_state.proc_state == PROC_ERROR) {
		status = -EPERM;
		goto func_end;
	}

	/* Assuming that 0 is not a valid function address */
	if (hnode_mgr->ul_fxn_addrs[0] == 0) {
		/* No RMS on target - we currently can't handle this */
		pr_err("%s: Failed, no RMS in base image\n", __func__);
		status = -EPERM;
	} else {
		/* Validate attr_in fields, if non-NULL */
		if (attr_in) {
			/* Check if attr_in->prio is within range */
			if (attr_in->prio < hnode_mgr->min_pri ||
			    attr_in->prio > hnode_mgr->max_pri)
				status = -EDOM;
		}
	}
	/* Allocate node object and fill in */
	if (status)
		goto func_end;

	pnode = kzalloc(sizeof(struct node_object), GFP_KERNEL);
	if (pnode == NULL) {
		status = -ENOMEM;
		goto func_end;
	}
	pnode->hnode_mgr = hnode_mgr;
	/* This critical section protects get_node_props */
	mutex_lock(&hnode_mgr->node_mgr_lock);

	/* Get dsp_ndbprops from node database */
	status = get_node_props(hnode_mgr->hdcd_mgr, pnode, node_uuid,
				&(pnode->dcd_props));
	if (status)
		goto func_cont;

	pnode->node_uuid = *node_uuid;
	pnode->hprocessor = hprocessor;
	pnode->ntype = pnode->dcd_props.obj_data.node_obj.ndb_props.ntype;
	pnode->utimeout = pnode->dcd_props.obj_data.node_obj.ndb_props.utimeout;
	pnode->prio = pnode->dcd_props.obj_data.node_obj.ndb_props.prio;

	/* Currently only C64 DSP builds support Node Dynamic * heaps */
	/* Allocate memory for node heap */
	pnode->create_args.asa.task_arg_obj.heap_size = 0;
	pnode->create_args.asa.task_arg_obj.udsp_heap_addr = 0;
	pnode->create_args.asa.task_arg_obj.udsp_heap_res_addr = 0;
	pnode->create_args.asa.task_arg_obj.ugpp_heap_addr = 0;
	if (!attr_in)
		goto func_cont;

	/* Check if we have a user allocated node heap */
	if (!(attr_in->pgpp_virt_addr))
		goto func_cont;

	/* check for page aligned Heap size */
	if (((attr_in->heap_size) & (PG_SIZE4K - 1))) {
		pr_err("%s: node heap size not aligned to 4K, size = 0x%x \n",
		       __func__, attr_in->heap_size);
		status = -EINVAL;
	} else {
		pnode->create_args.asa.task_arg_obj.heap_size =
		    attr_in->heap_size;
		pnode->create_args.asa.task_arg_obj.ugpp_heap_addr =
		    (u32) attr_in->pgpp_virt_addr;
	}
	if (status)
		goto func_cont;

	status = proc_reserve_memory(hprocessor,
				     pnode->create_args.asa.task_arg_obj.
				     heap_size + PAGE_SIZE,
				     (void **)&(pnode->create_args.asa.
					task_arg_obj.udsp_heap_res_addr),
				     pr_ctxt);
	if (status) {
		pr_err("%s: Failed to reserve memory for heap: 0x%x\n",
		       __func__, status);
		goto func_cont;
	}
#ifdef DSP_DMM_DEBUG
	status = dmm_get_handle(p_proc_object, &dmm_mgr);
	if (!dmm_mgr) {
		status = DSP_EHANDLE;
		goto func_cont;
	}

	dmm_mem_map_dump(dmm_mgr);
#endif

	map_attrs |= DSP_MAPLITTLEENDIAN;
	map_attrs |= DSP_MAPELEMSIZE32;
	map_attrs |= DSP_MAPVIRTUALADDR;
	status = proc_map(hprocessor, (void *)attr_in->pgpp_virt_addr,
			  pnode->create_args.asa.task_arg_obj.heap_size,
			  (void *)pnode->create_args.asa.task_arg_obj.
			  udsp_heap_res_addr, (void **)&mapped_addr, map_attrs,
			  pr_ctxt);
	if (status)
		pr_err("%s: Failed to map memory for Heap: 0x%x\n",
		       __func__, status);
	else
		pnode->create_args.asa.task_arg_obj.udsp_heap_addr =
		    (u32) mapped_addr;

func_cont:
	mutex_unlock(&hnode_mgr->node_mgr_lock);
	if (attr_in != NULL) {
		/* Overrides of NBD properties */
		pnode->utimeout = attr_in->utimeout;
		pnode->prio = attr_in->prio;
	}
	/* Create object to manage notifications */
	if (!status) {
		pnode->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
							GFP_KERNEL);
		if (pnode->ntfy_obj)
			ntfy_init(pnode->ntfy_obj);
		else
			status = -ENOMEM;
	}

	if (!status) {
		node_type = node_get_type(pnode);
		/*  Allocate dsp_streamconnect array for device, task, and
		 *  dais socket nodes. */
		if (node_type != NODE_MESSAGE) {
			num_streams = MAX_INPUTS(pnode) + MAX_OUTPUTS(pnode);
			pnode->stream_connect = kzalloc(num_streams *
					sizeof(struct dsp_streamconnect),
					GFP_KERNEL);
			if (num_streams > 0 && pnode->stream_connect == NULL)
				status = -ENOMEM;

		}
		if (!status && (node_type == NODE_TASK ||
					      node_type == NODE_DAISSOCKET)) {
			/* Allocate arrays for maintainig stream connections */
			pnode->inputs = kzalloc(MAX_INPUTS(pnode) *
					sizeof(struct stream_chnl), GFP_KERNEL);
			pnode->outputs = kzalloc(MAX_OUTPUTS(pnode) *
					sizeof(struct stream_chnl), GFP_KERNEL);
			ptask_args = &(pnode->create_args.asa.task_arg_obj);
			ptask_args->strm_in_def = kzalloc(MAX_INPUTS(pnode) *
						sizeof(struct node_strmdef),
						GFP_KERNEL);
			ptask_args->strm_out_def = kzalloc(MAX_OUTPUTS(pnode) *
						sizeof(struct node_strmdef),
						GFP_KERNEL);
			if ((MAX_INPUTS(pnode) > 0 && (pnode->inputs == NULL ||
						       ptask_args->strm_in_def
						       == NULL))
			    || (MAX_OUTPUTS(pnode) > 0
				&& (pnode->outputs == NULL
				    || ptask_args->strm_out_def == NULL)))
				status = -ENOMEM;
		}
	}
	if (!status && (node_type != NODE_DEVICE)) {
		/* Create an event that will be posted when RMS_EXIT is
		 * received. */
		pnode->sync_done = kzalloc(sizeof(struct sync_object),
								GFP_KERNEL);
		if (pnode->sync_done)
			sync_init_event(pnode->sync_done);
		else
			status = -ENOMEM;

		if (!status) {
			/*Get the shared mem mgr for this nodes dev object */
			status = cmm_get_handle(hprocessor, &hcmm_mgr);
			if (!status) {
				/* Allocate a SM addr translator for this node
				 * w/ deflt attr */
				status = cmm_xlator_create(&pnode->xlator,
							   hcmm_mgr, NULL);
			}
		}
		if (!status) {
			/* Fill in message args */
			if ((pargs != NULL) && (pargs->cb_data > 0)) {
				pmsg_args =
				    &(pnode->create_args.asa.node_msg_args);
				pmsg_args->pdata = kzalloc(pargs->cb_data,
								GFP_KERNEL);
				if (pmsg_args->pdata == NULL) {
					status = -ENOMEM;
				} else {
					pmsg_args->arg_length = pargs->cb_data;
					memcpy(pmsg_args->pdata,
					       pargs->node_data,
					       pargs->cb_data);
				}
			}
		}
	}

	if (!status && node_type != NODE_DEVICE) {
		/* Create a message queue for this node */
		intf_fxns = hnode_mgr->intf_fxns;
		status =
		    (*intf_fxns->pfn_msg_create_queue) (hnode_mgr->msg_mgr_obj,
							&pnode->msg_queue_obj,
							0,
							pnode->create_args.asa.
							node_msg_args.max_msgs,
							pnode);
	}

	if (!status) {
		/* Create object for dynamic loading */

		status = hnode_mgr->nldr_fxns.pfn_allocate(hnode_mgr->nldr_obj,
							   (void *)pnode,
							   &pnode->dcd_props.
							   obj_data.node_obj,
							   &pnode->
							   nldr_node_obj,
							   &pnode->phase_split);
	}

	/* Compare value read from Node Properties and check if it is same as
	 * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
	 * GPP Address, Read the value in that address and override the
	 * stack_seg value in task args */
	if (!status &&
	    (char *)pnode->dcd_props.obj_data.node_obj.ndb_props.
	    stack_seg_name != NULL) {
		if (strcmp((char *)
			   pnode->dcd_props.obj_data.node_obj.ndb_props.
			   stack_seg_name, STACKSEGLABEL) == 0) {
			status =
			    hnode_mgr->nldr_fxns.
			    pfn_get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG",
					     &dynext_base);
			if (status)
				pr_err("%s: Failed to get addr for DYNEXT_BEG"
				       " status = 0x%x\n", __func__, status);

			status =
			    hnode_mgr->nldr_fxns.
			    pfn_get_fxn_addr(pnode->nldr_node_obj,
					     "L1DSRAM_HEAP", &pul_value);

			if (status)
				pr_err("%s: Failed to get addr for L1DSRAM_HEAP"
				       " status = 0x%x\n", __func__, status);

			host_res = pbridge_context->resources;
			if (!host_res)
				status = -EPERM;

			if (status) {
				pr_err("%s: Failed to get host resource, status"
				       " = 0x%x\n", __func__, status);
				goto func_end;
			}

			ul_gpp_mem_base = (u32) host_res->dw_mem_base[1];
			off_set = pul_value - dynext_base;
			ul_stack_seg_addr = ul_gpp_mem_base + off_set;
			ul_stack_seg_val = readl(ul_stack_seg_addr);

			dev_dbg(bridge, "%s: StackSegVal = 0x%x, StackSegAddr ="
				" 0x%x\n", __func__, ul_stack_seg_val,
				ul_stack_seg_addr);

			pnode->create_args.asa.task_arg_obj.stack_seg =
			    ul_stack_seg_val;

		}
	}

	if (!status) {
		/* Add the node to the node manager's list of allocated
		 * nodes. */
		lst_init_elem((struct list_head *)pnode);
		NODE_SET_STATE(pnode, NODE_ALLOCATED);

		mutex_lock(&hnode_mgr->node_mgr_lock);

		lst_put_tail(hnode_mgr->node_list, (struct list_head *) pnode);
			++(hnode_mgr->num_nodes);

		/* Exit critical section */
		mutex_unlock(&hnode_mgr->node_mgr_lock);

		/* Preset this to assume phases are split
		 * (for overlay and dll) */
		pnode->phase_split = true;

		/* Notify all clients registered for DSP_NODESTATECHANGE. */
		proc_notify_all_clients(hprocessor, DSP_NODESTATECHANGE);
	} else {
		/* Cleanup */
		if (pnode)
			delete_node(pnode, pr_ctxt);

	}

	if (!status) {
		status = drv_insert_node_res_element(pnode, &node_res, pr_ctxt);
		if (status) {
			delete_node(pnode, pr_ctxt);
			goto func_end;
		}

		*noderes = (struct node_res_object *)node_res;
		drv_proc_node_update_heap_status(node_res, true);
		drv_proc_node_update_status(node_res, true);
	}
	DBC_ENSURE((status && *noderes == NULL) || (!status && *noderes));
func_end:
	dev_dbg(bridge, "%s: hprocessor: %p pNodeId: %p pargs: %p attr_in: %p "
		"node_res: %p status: 0x%x\n", __func__, hprocessor,
		node_uuid, pargs, attr_in, noderes, status);
	return status;
}
コード例 #16
0
ファイル: node.c プロジェクト: jnfeinstein/asuswrt-merlin
/*
 *  ======== node_alloc_msg_buf ========
 *  Purpose:
 *      Allocates buffer for zero copy messaging.
 */
DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize,
			 struct dsp_bufferattr *pattr,
			 u8 **pbuffer)
{
	struct node_object *pnode = (struct node_object *)hnode;
	int status = 0;
	bool va_flag = false;
	bool set_info;
	u32 proc_id;

	DBC_REQUIRE(refs > 0);
	DBC_REQUIRE(pbuffer != NULL);

	DBC_REQUIRE(usize > 0);

	if (!pnode)
		status = -EFAULT;
	else if (node_get_type(pnode) == NODE_DEVICE)
		status = -EPERM;

	if (status)
		goto func_end;

	if (pattr == NULL)
		pattr = &node_dfltbufattrs;	/* set defaults */

	status = proc_get_processor_id(pnode->hprocessor, &proc_id);
	if (proc_id != DSP_UNIT) {
		DBC_ASSERT(NULL);
		goto func_end;
	}
	/*  If segment ID includes MEM_SETVIRTUALSEGID then pbuffer is a
	 *  virt  address, so set this info in this node's translator
	 *  object for  future ref. If MEM_GETVIRTUALSEGID then retrieve
	 *  virtual address  from node's translator. */
	if ((pattr->segment_id & MEM_SETVIRTUALSEGID) ||
	    (pattr->segment_id & MEM_GETVIRTUALSEGID)) {
		va_flag = true;
		set_info = (pattr->segment_id & MEM_SETVIRTUALSEGID) ?
		    true : false;
		/* Clear mask bits */
		pattr->segment_id &= ~MEM_MASKVIRTUALSEGID;
		/* Set/get this node's translators virtual address base/size */
		status = cmm_xlator_info(pnode->xlator, pbuffer, usize,
					 pattr->segment_id, set_info);
	}
	if (!status && (!va_flag)) {
		if (pattr->segment_id != 1) {
			/* Node supports single SM segment only. */
			status = -EBADR;
		}
		/*  Arbitrary SM buffer alignment not supported for host side
		 *  allocs, but guaranteed for the following alignment
		 *  values. */
		switch (pattr->buf_alignment) {
		case 0:
		case 1:
		case 2:
		case 4:
			break;
		default:
			/* alignment value not suportted */
			status = -EPERM;
			break;
		}
		if (!status) {
			/* allocate physical buffer from seg_id in node's
			 * translator */
			(void)cmm_xlator_alloc_buf(pnode->xlator, pbuffer,
						   usize);
			if (*pbuffer == NULL) {
				pr_err("%s: error - Out of shared memory\n",
				       __func__);
				status = -ENOMEM;
			}
		}
	}
func_end:
	return status;
}
コード例 #17
0
LogicType logic_recognizer_core_recognize(LogicRecognizerBase_ptr self,
                                                node_ptr exp,
                                                node_ptr context)
{
  MasterLogicRecognizer_ptr master = MASTER_LOGIC_RECOGNIZER(NODE_WALKER(self)->master);
  LogicType retval = EXP_NONE;
  LogicType left = EXP_NONE;
  LogicType right = EXP_NONE;
  short int exptype = 0;

  nusmv_assert(NULL != exp);

#ifdef DEBUG_CONVERT_PROPERTY_TO_INVAR
  {
    NuSMVEnv_ptr const env = EnvObject_get_environment(ENV_OBJECT(self));
    Logger_ptr const logger = LOGGER(NuSMVEnv_get_value(env, ENV_LOGGER));
    MasterPrinter_ptr const sexpprint =
      MASTER_PRINTER(NuSMVEnv_get_value(env, ENV_SEXP_PRINTER));
    OptsHandler_ptr const opts =
      OPTS_HANDLER(NuSMVEnv_get_value(env, ENV_OPTS_HANDLER));

    Logger_vnlog_error(logger, sexpprint, opts, "Input:\n%N\n",
                       exp);
  }
#endif

  exptype = node_get_type(exp);

  /* fast return */
  switch (exptype) {
  case CONTEXT:
    retval = LR_THROW(self, cdr(exp), car(exp));;
    break;
  case FAILURE:
  case FALSEEXP:
  case TRUEEXP:
  case NUMBER:
  case NUMBER_UNSIGNED_WORD:
  case NUMBER_SIGNED_WORD:
  case NUMBER_FRAC:
  case NUMBER_REAL:
  case NUMBER_EXP:
  case UWCONST:
  case SWCONST:
  case TWODOTS:
  case DOT:
  case ATOM:
  case BIT:
  case SELF:
  case ARRAY:
  case COUNT:
    retval = EXP_SIMPLE; break;

  case NEXT:
    retval = EXP_NEXT; break;

    /* CTL */
  case EX: case AX: case EF: case AF: case EG: case AG:
  case ABU: case EBU:
  case EBF: case ABF: case EBG: case ABG:
  case AU: case EU:
    retval = EXP_CTL; break;

    /* LTL */
  case OP_NEXT: case OP_PREC: case OP_NOTPRECNOT: case OP_GLOBAL:
  case OP_HISTORICAL: case OP_FUTURE: case OP_ONCE:
  case UNTIL: case SINCE:
    retval = EXP_LTL; break;

  default:
    retval = master_logic_recognizer_lookup(master, exp, context);
  } /* end of first switch */

  if (EXP_NONE == retval) {
    switch(exptype) {
      /* unary operators */
    case CAST_BOOL:
    case CAST_WORD1:
    case CAST_SIGNED:
    case CAST_UNSIGNED:
    case WSIZEOF:
    case CAST_TOINT:
    case NOT:
    case UMINUS:
      retval = LR_THROW(self, car(exp), context);
      break;

      /* binary operators */
    case CONS:
      left = LR_THROW(self, car(exp), context);

      if (NULL != cdr(exp)) {
        right = LR_THROW(self, cdr(exp), context);
        retval = master_logic_recognizer_merge(master, left, right);
      }
      else retval = LR_THROW(self, car(exp), context);

      break;

    case BIT_SELECTION:
    case CASE: case COLON:
    case CONCATENATION:
    case TIMES: case DIVIDE: case PLUS :case MINUS: case MOD:
    case LSHIFT: case RSHIFT: case LROTATE: case RROTATE:
    case WAREAD: case WAWRITE:
    case UNION: case SETIN:
    case IFTHENELSE:
    case EXTEND:
    case WRESIZE:
    case AND: case OR: case XOR: case XNOR: case IFF: case IMPLIES:
    case EQUAL: case NOTEQUAL: case LT: case GT: case LE: case GE:
      left = LR_THROW(self, car(exp), context);
      right = LR_THROW(self, cdr(exp), context);
      retval = master_logic_recognizer_merge(master, left, right);
      break;

    case NFUNCTION: {
      node_ptr args = cdr(exp);
      retval = EXP_SIMPLE;

      while (Nil != args) {
        left = LR_THROW(self, car(args), context);
        nusmv_assert((left == EXP_SIMPLE) ||
                     (left == EXP_NEXT));
        retval = master_logic_recognizer_merge(master, retval, left);
        args = cdr(args);
      }
      break;
    }

    default:
      {
        NuSMVEnv_ptr const env = EnvObject_get_environment(ENV_OBJECT(self));
        StreamMgr_ptr const streams =
          STREAM_MGR(NuSMVEnv_get_value(env, ENV_STREAM_MANAGER));
        MasterPrinter_ptr const sexpprint =
          MASTER_PRINTER(NuSMVEnv_get_value(env, ENV_SEXP_PRINTER));
        ErrorMgr_ptr const errmgr =
          ERROR_MGR(NuSMVEnv_get_value(env, ENV_ERROR_MANAGER));

        StreamMgr_nprint_error(streams, sexpprint,
                               "Internal Error: unhandled operator in expr \n%N\n", exp);
        ErrorMgr_nusmv_exit(errmgr, 1);
      }
    } /* end of switch */

    master_logic_recognizer_insert(master, exp, context, retval);
  }

  return retval;
}