pike.git / src / pike_types.cmod

version» Context lines:

pike.git/src/pike_types.cmod:3796:    marker &= 0x0f;       if (flags & PT_FLAG_REMAP_SWAP_MARKERS) marker |= 0x10;       if (!(m = remap->map[marker])) return;       remap->map[marker] = 0;    remap->allocated &= ~(1 << (m & 0x0f));   }    + static struct pike_type *lookup_marker(struct mapping *markers, int marker) + { +  struct svalue key, *val; +  +  if (!markers || !marker) return NULL; +  +  SET_SVAL(key, T_INT, NUMBER_NUMBER, integer, marker); +  +  val = low_mapping_lookup(markers, &key); +  if (!val) return NULL; +  +  if (TYPEOF(*val) == PIKE_T_TYPE) { +  return val->u.type; +  } +  return NULL; + } +  + static void store_marker(struct mapping *markers, int marker, +  struct pike_type *value) + { +  struct svalue key, val; +  +  if (!markers || !marker) return; +  +  SET_SVAL(key, T_INT, NUMBER_NUMBER, integer, marker); +  SET_SVAL(val, T_TYPE, 0, type, value); +  mapping_insert(markers, &key, &val); + } +    static void push_remap_markers(struct pike_type *t, -  +  struct mapping *markers,    struct remap_state *remap,    enum pt_remap_flags flags)   {    if (!remap) {    push_finished_type(t);    return;    }       /* FIXME: Use the type flags to detect whether we can just push    * the type verbatim.    */       switch(t->type & PIKE_T_MASK) {    case T_ASSIGN:    {    int marker = alloc_remap_marker(remap, CAR_TO_INT(t), flags); -  push_remap_markers(t->cdr, remap, flags); +  +  if (!markers || !(flags & PT_FLAG_REMAP_EVAL_MARKERS)) { +  push_remap_markers(t->cdr, markers, remap, flags);    push_assign_type(marker); -  +  } else { +  struct pike_type *old = lookup_marker(markers, marker); +  struct pike_type *new = t->cdr; +  if (old) { +  new = or_pike_types(old, new, 0); +  } else { +  add_ref(new); +  } +  store_marker(markers, marker, new); +  free_pike_type(new); +  push_remap_markers(t->cdr, markers, remap, flags); +  } +  +  if (flags & PT_FLAG_REMAP_BOTH_MARKERS) { +  marker = alloc_remap_marker(remap, CAR_TO_INT(t), +  flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  +  if (!markers || !(flags & PT_FLAG_REMAP_EVAL_MARKERS)) { +  push_assign_type(marker); +  } else { +  struct pike_type *old = lookup_marker(markers, marker); +  struct pike_type *new = t->cdr; +  if (old) { +  new = or_pike_types(old, new, 0); +  } else { +  add_ref(new); +  } +  store_marker(markers, marker, new); +  free_pike_type(new); +  push_remap_markers(t->cdr, markers, remap, flags); +  +  switch(flags & PT_FLAG_REMAP_BOTH_MARKERS_MASK) { +  case PT_FLAG_REMAP_BOTH_MARKERS_AND: +  push_type(T_AND);    break; -  +  case PT_FLAG_REMAP_BOTH_MARKERS_OR: +  push_type(T_OR); +  break; +  default: +  Pike_fatal("Unsupported marker joining method.\n"); +  break;    } -  +  } +  } +  break; +  }       case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, t->type, flags); -  +  struct pike_type *value = lookup_marker(markers, marker); +  +  if (value) { +  push_remap_markers(value, markers, remap, flags); +  } else if ((markers) && (flags & PT_FLAG_REMAP_EVAL_MARKERS)) { +  /* Marker without matching assign. */ +  /* FIXME: Report error? */ +  push_type(T_MIXED); +  } else { +  +  /* Remap the marker. */ +     if (!marker) {    /* FIXME: Improve error handling here. */    push_type(T_MIXED);    } else {    push_type(marker);    } -  +  } +     if (flags & PT_FLAG_REMAP_BOTH_MARKERS) {    marker = remap_marker(remap, t->type,    flags ^ PT_FLAG_REMAP_SWAP_MARKERS); -  +  value = lookup_marker(markers, marker); +  +  if (value) { +  push_remap_markers(value, markers, remap, flags); +  } else if ((markers) && (flags & PT_FLAG_REMAP_EVAL_MARKERS)) { +  /* Marker without matching assign. */ +  /* FIXME: Report error? */ +  push_type(T_MIXED); +  } else { +  +  /* Remap the marker. */ +     if (!marker) {    /* FIXME: Improve error handling here. */    push_type(T_MIXED);    } else {    push_type(marker);    } -  +  } +     switch(flags & PT_FLAG_REMAP_BOTH_MARKERS_MASK) {    case PT_FLAG_REMAP_BOTH_MARKERS_AND:    push_type(T_AND);    break;    case PT_FLAG_REMAP_BOTH_MARKERS_OR:    push_type(T_OR);    break;    default:    Pike_fatal("Unsupported marker joining method.\n");    break;    }    }    break;    }       case PIKE_T_NAME: -  push_remap_markers(t->cdr, remap, flags); +  push_remap_markers(t->cdr, markers, remap, flags);    push_type_name((struct pike_string *)(t->car));    break;       case PIKE_T_ATTRIBUTE: -  push_remap_markers(t->cdr, remap, flags); +  push_remap_markers(t->cdr, markers, remap, flags);    push_type_attribute((struct pike_string *)(t->car));    break;       case T_SCOPE: -  push_remap_markers(t->cdr, remap, flags); +  push_remap_markers(t->cdr, markers, remap, flags);    push_scope_type(CAR_TO_INT(t));    break;       case PIKE_T_OPERATOR: -  push_remap_markers(t->car, remap, flags); +  push_remap_markers(t->car, markers, remap, flags);       if (t->type & 0x8000) { -  push_remap_markers(t->cdr, remap, flags); +  push_remap_markers(t->cdr, markers, remap, flags);    push_reverse_type(t->type);    } else {    switch(t->type) {    case PIKE_T_FIND_LFUN:    push_type_operator(t->type, t->cdr);    break;    default:    Pike_fatal("Unsupported operator %d in push_remap_markers().\n",    t->type);    break;
pike.git/src/pike_types.cmod:3902:    case PIKE_T_MIXED:    push_finished_type(t);    break;       /* Unary */    case T_PROGRAM:    case T_MULTISET:    case T_NOT:    case T_TYPE:    case PIKE_T_AUTO: -  push_remap_markers(t->car, remap, flags); +  push_remap_markers(t->car, markers, remap, flags);    push_type(t->type);    break;       /* Binary */    case T_OR:    case T_AND:    case T_FUNCTION:    case T_MANY:    case T_TUPLE:    case T_MAPPING:    case PIKE_T_RING:    case T_ARRAY:    case T_STRING:    case PIKE_T_TRANSITIVE: -  push_remap_markers(t->car, remap, flags); -  push_remap_markers(t->cdr, remap, flags); +  push_remap_markers(t->car, markers, remap, flags); +  push_remap_markers(t->cdr, markers, remap, flags);    push_reverse_type(t->type);    break;    }   }      /**    * Remap markers (if any) in the type.    */   static struct pike_type *remap_markers(struct pike_type *t, -  +  struct mapping *markers,    struct remap_state *remap,    enum pt_remap_flags flags)   {    type_stack_mark(); -  push_remap_markers(t, remap, flags); +  push_remap_markers(t, markers, remap, flags);    return pop_unfinished_type();   }      static struct pike_type *low_intersect_types(struct pike_type *a,    struct pike_type *b,    struct remap_state *remap,    enum pt_cmp_flags aflags,    enum pt_cmp_flags bflags,    enum pt_remap_flags remap_flags);   static struct pike_type *expand_transitive(struct pike_type *fun,
pike.git/src/pike_types.cmod:3999:    free_marker(remap, CAR_TO_INT(a), remap_flags);    return NULL;    }       case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, a->type, remap_flags);    if (!marker) return NULL;    -  tmp = remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  tmp = remap_markers(b, NULL, remap, +  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    if (!tmp) return NULL;    type_stack_mark();    push_finished_type(tmp);    push_type(T_NOT);    push_type(marker);    push_reverse_type(T_AND);    free_type(tmp);    return pop_unfinished_type();    }    }
pike.git/src/pike_types.cmod:4035:    return NULL;    }       case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, b->type,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    if (!marker) return NULL;    -  tmp = remap_markers(a, remap, remap_flags); +  tmp = remap_markers(a, NULL, remap, remap_flags);    if (!tmp) return NULL;    type_stack_mark();    push_finished_type(tmp);    push_type(marker);    push_type(T_NOT);    push_reverse_type(T_AND);    free_type(tmp);    return pop_unfinished_type();    }    }
pike.git/src/pike_types.cmod:4135:    case T_OR:    /* DeMorgan    *    * a & ~(b1 | b2) <==> a & ~b1 & ~b2    */    tmp = low_subtract_types(a, b->car, remap, aflags, bflags, remap_flags);    if (!tmp) return NULL;    /* NB: We need to remap b->cdr separately to avoid remapping    * markers in a and b->car twice.    */ -  tmp2 = remap_markers(b->cdr, remap, +  tmp2 = remap_markers(b->cdr, NULL, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    ret = low_subtract_types(tmp, tmp2, NULL, aflags, bflags, 0);    free_type(tmp);    free_type(tmp2);    return ret;       case T_AND:    /* DeMorgan    *    * a & ~(b1 & b2) <==> a & (~b1 | ~b2) <==> (a & ~b1) | (a & ~b2)
pike.git/src/pike_types.cmod:4313:    }    free_type(tmp);    if (got_empty) break;    }       if (!got_full) {    return NULL;    }       type_stack_mark(); -  push_remap_markers(a, remap, remap_flags); +  push_remap_markers(a, NULL, remap, remap_flags);    return pop_unfinished_type();    }       /* Advance to the next argument. */    if (ai->type == T_FUNCTION) {    ai = ai->cdr;    }    if (bi->type == T_FUNCTION) {    bi = bi->cdr;    }
pike.git/src/pike_types.cmod:4335:    break;    }    if ((bi->type != T_FUNCTION) && (bi->type != T_MANY)) {    break;    }    }       /* Either of a and/or b is a complex type, or a partial overlap. */       type_stack_mark(); -  push_remap_markers(a, remap, remap_flags); -  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(a, NULL, remap, remap_flags); +  push_remap_markers(b, NULL, remap, +  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_NOT);    push_reverse_type(T_AND);       return pop_unfinished_type();    }       case TWOT(T_ZERO, T_INT):    if ((CAR_TO_INT(b) <= 0) && (CDR_TO_INT(b) >= 0)) {    return NULL;    }
pike.git/src/pike_types.cmod:4439:    add_ref(a);    return a;    }       if (b->type == T_MIXED) {    /* NB: a being void has been handled above. */    return NULL;    }    if (a->type == T_MIXED) {    type_stack_mark(); -  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(b, NULL, remap, +  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_NOT);    return pop_unfinished_type();    }       if (b->type == T_NOT) {    return low_intersect_types(a, b->car, remap, aflags, bflags, remap_flags);    }    if (a->type == T_NOT) {    /* DeMorgan and(not(a), not(b)) <==> not(or(a, b)) */    type_stack_mark(); -  push_remap_markers(a->car, remap, remap_flags); -  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(a->car, NULL, remap, remap_flags); +  push_remap_markers(b, NULL, remap, +  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_OR);    push_type(T_NOT);    return pop_unfinished_type();    }       if (a->type != b->type) {    if (((a->type & PIKE_T_MASK) == PIKE_T_OPERATOR) ||    ((b->type & PIKE_T_MASK) == PIKE_T_OPERATOR)) {    type_stack_mark(); -  push_remap_markers(a, remap, remap_flags); -  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(a, NULL, remap, remap_flags); +  push_remap_markers(b, NULL, remap, +  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_NOT);    push_reverse_type(T_AND);    return pop_unfinished_type();    }    add_ref(a);    return a;    }       switch(a->type) {    case T_VOID:
pike.git/src/pike_types.cmod:4633:   {    struct pike_type *tmp, *tmp2, *ret;    struct pike_type *aret = NULL, *bret = NULL;    enum pt_cmp_flags avoidable;    enum pt_cmp_flags bvoidable;       if (!a || !b) return NULL;       if (a == b) {    /* FIXME: Perform masking of remap_flags here. */ -  return remap_markers(a, remap, +  return remap_markers(a, NULL, remap,    remap_flags | PT_FLAG_REMAP_BOTH_MARKERS_AND);    }       /* First check for markers. */    switch(a->type) {    case T_ASSIGN:    {    int marker = alloc_remap_marker(remap, CAR_TO_INT(a), remap_flags);    tmp = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags);    if (tmp) {
pike.git/src/pike_types.cmod:4660:    free_marker(remap, CAR_TO_INT(a), remap_flags);    return NULL;    }       case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, a->type, remap_flags);    if (!marker) return NULL;    -  tmp = remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  tmp = remap_markers(b, NULL, remap, +  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    if (!tmp) return NULL;    type_stack_mark();    push_finished_type(tmp);    push_type(marker);    push_reverse_type(T_AND);    free_type(tmp);    return pop_unfinished_type();    }    }    switch(b->type) {
pike.git/src/pike_types.cmod:4696:    return NULL;    }       case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':    {    int marker = remap_marker(remap, b->type,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    if (!marker) return NULL;    -  tmp = remap_markers(a, remap, remap_flags); +  tmp = remap_markers(a, NULL, remap, remap_flags);    if (!tmp) return NULL;    type_stack_mark();    push_finished_type(tmp);    push_type(marker);    push_reverse_type(T_AND);    free_type(tmp);    return pop_unfinished_type();    }    }   
pike.git/src/pike_types.cmod:4790:    */    if (a->car->type == T_NOT) {    tmp2 = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags);    if (!tmp2) return NULL;    tmp = low_intersect_types(a->car, b, remap, aflags, bflags, remap_flags);    if (!tmp) {    free_type(tmp2);    return NULL;    }    free_type(tmp); -  tmp = remap_markers(a->car, remap, remap_flags); +  tmp = remap_markers(a->car, NULL, remap, remap_flags);    } else {    tmp = low_intersect_types(a->car, b, remap, aflags, bflags, remap_flags);    if (!tmp) return NULL;    tmp2 = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags);    if (!tmp2) {    free_type(tmp);    return NULL;    }    if (a->cdr->type == T_NOT) {    free_type(tmp2); -  tmp2 = remap_markers(a->cdr, remap, remap_flags); +  tmp2 = remap_markers(a->cdr, NULL, remap, remap_flags);    }    }       type_stack_mark();    push_finished_type(tmp);    push_finished_type(tmp2);    push_reverse_type(T_AND);    free_type(tmp);    free_type(tmp2);    return pop_unfinished_type();
pike.git/src/pike_types.cmod:4838:    case T_AND:    /* NB: Attempt to avoid keeping the result from inverted types,    * in order to reduce type expansion.    */    if (b->car->type == T_NOT) {    tmp = low_intersect_types(a, b->cdr, remap, aflags, bflags, remap_flags);    if (!tmp) return NULL;    tmp2 = low_intersect_types(a, b->car, remap, aflags, bflags, remap_flags);    if (tmp2) {    free_type(tmp2); -  tmp2 = remap_markers(b->car, remap, +  tmp2 = remap_markers(b->car, NULL, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    }    } else {    tmp = low_intersect_types(a, b->car, remap, aflags, bflags, remap_flags);    if (!tmp) return NULL;    tmp2 = low_intersect_types(a, b->cdr, remap, aflags, bflags, remap_flags);    if (tmp2 && (b->cdr->type == T_NOT)) {    free_type(tmp2); -  tmp2 = remap_markers(b->cdr, remap, +  tmp2 = remap_markers(b->cdr, NULL, remap,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    }    }    if (!tmp2) {    free_type(tmp);    return NULL;    }       type_stack_mark();    push_finished_type(tmp);
pike.git/src/pike_types.cmod:5034:    if (bret) {    Pike_fatal("Unsupported type operation.\n");    }    break;    }    }       nargs = pop_stack_mark();       /* Either of a and/or b is a complex type. */ -  tmp = remap_markers(a, remap, remap_flags); +  tmp = remap_markers(a, NULL, remap, remap_flags);    push_finished_type(tmp);    free_type(tmp);    -  tmp = remap_markers(b, remap, remap_flags); +  tmp = remap_markers(b, NULL, remap, remap_flags);    push_finished_type(tmp);    free_type(tmp);       push_reverse_type(T_AND);       while (nargs--) {    push_reverse_type(T_FUNCTION);    }    return pop_unfinished_type();   
pike.git/src/pike_types.cmod:5150:    }    if (b->type == T_VOID) {    if (avoidable) {    add_ref(b);    return b;    }    return NULL;    }       if (a->type == T_MIXED) { -  return remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  return remap_markers(b, NULL, remap, +  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    }    if (b->type == T_MIXED) { -  return remap_markers(a, remap, remap_flags); +  return remap_markers(a, NULL, remap, remap_flags);    }       if (a->type == T_NOT) {    if (b->type == T_NOT) {    /* DeMorgan and(not(a), not(b)) <==> not(or(a, b)) */    type_stack_mark(); -  push_remap_markers(a->car, remap, remap_flags); -  push_remap_markers(b->car, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(a->car, NULL, remap, remap_flags); +  push_remap_markers(b->car, NULL, remap, +  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_type(T_OR);    push_type(T_NOT);    return pop_unfinished_type();    }    /* NB: Swapped argument order! */    return low_subtract_types(b, a->car, remap, bflags, aflags,    remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    }    if (b->type == T_NOT) {    return low_subtract_types(a, b->car, remap, aflags, bflags, remap_flags);    }       if (a->type != b->type) {    if (((a->type & PIKE_T_MASK) == PIKE_T_OPERATOR) ||    ((b->type & PIKE_T_MASK) == PIKE_T_OPERATOR)) {    type_stack_mark(); -  push_remap_markers(a, remap, remap_flags); -  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); +  push_remap_markers(a, NULL, remap, remap_flags); +  push_remap_markers(b, NULL, remap, +  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);    push_reverse_type(T_AND);    return pop_unfinished_type();    }    return NULL;    }       switch(a->type) {    case T_VOID:    case T_ZERO:    case T_FLOAT: