Пример #1
0
static inline int
match_record(ErlNifEnv* env, int arity, const ERL_NIF_TERM *tuple, State *st){

  EncRecord *records = enc_records_base(st->records);
  EncField *fields = enc_fields_base(st->records);
  int i, k;
  for(i = 0; i < st->records->records_cnt; i++){
    if(records[i].tag == tuple[0] &&  records[i].arity == (arity -1)){
      unsigned fds_offset = records[i].fds_offset;
      unsigned bin_size = 0;
      b_putc('{', st);
      for(k = 0; k < records[i].arity; k++){
	EncField field = fields[fds_offset + k];
	bin_size += field.size;
	//FIXME {
	b_puts(field.size, st->records->bin.data + field.offset, st);
	if(!match_term(env, tuple[k+1], st))
	  return 0;
      }
      b_putc('}', st);
      return 1;
    }
  }
  return 0;
}
Пример #2
0
static inline int
match_list(ErlNifEnv* env, ERL_NIF_TERM term, State *st){
  ERL_NIF_TERM list, head, tail;
  unsigned len;
  if(!enif_get_list_length(env, term, &len))
    return 0;
  b_putc('[',  st);
  list = term;
  enif_get_list_cell(env, list, &head, &tail);
  if(!match_term(env, head, st)){
    b_unputc(st); // delete '[';
    return 0;
  }
  list = tail;   
  while(enif_get_list_cell(env, list, &head, &tail)){
    b_putc(',',  st);
    if(!match_term(env, head, st)){
      return 0;
    }
    list = tail;
  }
  b_putc(']',  st);
  return 1;
}
Пример #3
0
static inline int
match_pair(ErlNifEnv* env, ERL_NIF_TERM term, State *st){
  const ERL_NIF_TERM *tuple;
  int arity;
  if(enif_get_tuple(env, term, &arity, &tuple)){
    if(arity == 2){
      if(match_string(env, tuple[0], st)){
	b_putc(':', st);
	if(match_term(env, tuple[1], st)){
	  return 1;
	}
      }
    }
  }
  return 0;
}
Пример #4
0
/*
 * Check whether f is a range constraint
 * - if so return a term t and fill in vector v with the formula's constants
 * - otherwise, return NULL_TERM
 *
 * Side effect: use queue and cache.
 * v may be modified even if the function returns NULL_TERM.
 */
static term_t formula_is_range_constraint(sym_breaker_t *breaker, term_t f, ivector_t *v) {
  int_queue_t *queue;
  int_hset_t *cache;
  term_table_t *terms;
  intern_tbl_t *intern;
  term_t r, t;
  term_t x, a, y, b;
  uint32_t neqs;

  queue = &breaker->queue;
  cache = &breaker->cache;
  terms = breaker->terms;
  intern = &breaker->ctx->intern;

  assert(int_queue_is_empty(queue) && int_hset_is_empty(cache));
  push_term(queue, cache, f);

  neqs = 0;
  t = NULL_TERM;

  y = NULL_TERM; // prevent GCC warning
  b = NULL_TERM; // prevent GCC warning

  /*
   * Invariants:
   * - neqs = number of equality atoms seen so far
   * - if neq == 1, then the first equality is stored as (y == b) where b is a constant
   * - if neq >= 2, then all equalities seen so far were of the form (x == constant)
   */
  do {
    // r := root of the first term in the queue
    r = intern_tbl_get_root(intern, int_queue_pop(queue));

    switch (match_term(breaker->ctx, r, &a, &x)) {
    case MATCH_FALSE: // skip false terms
      break;

    case MATCH_OR:
      push_children(queue, cache, or_term_desc(terms, r));
      break;

    case MATCH_EQ:
      assert(term_is_constant(terms, a));
      if (neqs == 0) {
	y = x; b = a;
      } else if (neqs == 1) {
	/*
	 * First equality: (y == b). Second equality: (x == a)
	 */
	if (y == x) {
	  // y is the common term, a and b are constant
	  ivector_push(v, b);
	  ivector_push(v, a);
	} else if (y == a && term_is_uconst(terms, x)) {
	  // y is the common term, b and x are constant
	  ivector_push(v, b);
	  ivector_push(v, a);
	} else if (x == b && term_is_uconst(terms, y)) {
	  // b is the common term, y and a are constant
	  ivector_push(v, y);
	  ivector_push(v, a);
	  y = b;
	} else if (a == b && term_is_uconst(terms, y) && term_is_uconst(terms, x)) {
	  // b is the common term, y and x are constant
	  ivector_push(v, y);
	  ivector_push(v, x);
	  y = b;
	} else {
	  // abort
	  goto done;
	}

      } else {
	/*
	 * All equalities so far have the form (y == constant)
	 * - the current equality is (x == a)
	 */
	if (y == x) {
	  ivector_push(v, a); // match
	} else if (y == a && term_is_constant(terms, x)) {
	  ivector_push(v, x); // swap a and x
	} else {
	  // no match
	  goto done;
	}
      }
      neqs ++;
      break;

    case MATCH_IFF:
      /*
       * the returned term x is equivalent to t
       */
      push_term(queue, cache, x);
      break;

    default:
      // abort
      goto done;
    }
  } while (! int_queue_is_empty(queue));

  assert(y != NULL_TERM && t == NULL_TERM);

  if (neqs >= 2) {
    assert(v->size == neqs);
    t = y;
  }

 done:
  int_queue_reset(queue);
  int_hset_reset(cache);

  return t;
}